Python爬虫 - 爬取肯德基餐厅信息
🔍网页分析
背景介绍
这是我们要爬取的页面 http://www.kfc.com.cn/kfccda/storelist/index.aspx 我们先根据城市查询餐厅信息 选择城市后,可以看到下面的查询结果
页面分析
- 发现查询前后URL没有发生变化,显然下面的内容是动态加载的
- F12进入开发者工具,点击网络进行抓包,刷新页面,选择XHR,再次选择城市
- 网站非常简洁,一眼就看到了我们需要的数据包,点击查看,发现是post请求
- 点击预览可以看到,我们想要的信息都在这啦
💻撸代码
1. URL和参数
-
多次更换城市名和页数发现XHR包的请求URL不变 -
点击Payload发现,cname 代表城市名,pid 每次都为空,pageIndex 是当前页码,pageSize 是每页的信息条数 -
“查询字符串参数”的op 是URL中的参数,代表查询方式,即以cname(城市名查询)| keyword(关键字查询)
我们只演示城市名查询方式,关键字查询方式实际上大同小异!
http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname
于是定义 post_url 请求URL全程不变 city 用户输入城市名 pageIndex 初始为1,下面循环的时候会改变 pageSize 就用10即可
post_url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname'
city = input('输入要查询的城市:')
data = {
'cname': city,
'pid': '',
'pageIndex': '1',
'pageSize': '10'
}
2. 发起请求
- 第一次发起请求,获取到信息总条数,再循环遍历所有页
res = requests.post(url=post_url, data=data, headers=headers)
多次更改页数可以观察到,rowcount 值一直不变,显然这就是信息总条数 于是便可以获取总页数(pageSize 为10的情况下)res_json = json.loads(res.text)
row_counts = res_json['Table'][0]['rowcount']
page_counts = math.ceil(row_counts / 10)
- 循环遍历所有页面
观察发现主要数据都在Table1 里面,于是我们每次遍历只增加Table1 的列表长度pageIndex = 1
while pageIndex < page_counts:
time.sleep(random.random() * 10 % 4)
pageIndex += 1
data['pageIndex'] = str(pageIndex)
res_json['Table1'] += json.loads(requests.post(url=post_url, data=data, headers=headers).text)['Table1']
3. 持久化存储
把最终结果保存到本地,同时又想让数据好看,怎么办呢? 使用json.dumps() 可以格式化JSON字符串,注意是字符串! 然后将格式化后的字符串写入.json 文件即可
with open('TestDir/KFC_'+city+'.json', 'w', encoding='utf-8') as fp:
res_formatted = json.dumps(res_json, indent=4, ensure_ascii=False, sort_keys=False)
fp.write(res_formatted)
🎞所有代码
import requests
import json
import time
import math
import random
if __name__ == '__main__':
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62'
}
post_url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname'
city = input('输入要查询的城市:')
data = {
'cname': city,
'pid': '',
'pageIndex': '1',
'pageSize': '10'
}
res = requests.post(url=post_url, data=data, headers=headers)
res_json = json.loads(res.text)
row_counts = res_json['Table'][0]['rowcount']
page_counts = math.ceil(row_counts / 10)
pageIndex = 1
while pageIndex < page_counts:
time.sleep(random.random() * 10 % 4)
pageIndex += 1
data['pageIndex'] = str(pageIndex)
res_json['Table1'] += json.loads(requests.post(url=post_url, data=data, headers=headers).text)['Table1']
with open('TestDir/KFC_'+city+'.json', 'w', encoding='utf-8') as fp:
res_formatted = json.dumps(res_json, indent=4, ensure_ascii=False, sort_keys=False)
fp.write(res_formatted)
print(res_json)
print('Done')
|