赞
踩
1. 需求: 爬取肯德基某一地区的餐厅数量以及其具体信息 (以下代码我仅仅展示出餐厅的店名信息,并将其用列表方式保存在.txt文件中)
2.学习python爬虫的好课推荐: b站上的路飞学城IT,提醒:该课程适合对web、计算机网络和python有一定基础的朋友学习,因为爬虫需要对页面源码进行分析,所以有以上基础更加容易入门。此外,学习爬虫的过程其实也是学习python的过程,没有必要为了爬虫专门先学习python,这样容易懈怠学习爬虫的动力。
3. 过程:
第一步:首先进入到需要爬取的静态页面,其网址为: http://www.kfc.com.cn/kfccda/storelist/index.aspx
第二步: Fn+F12,查看页面源码,并对页面源码进行分析。我们可以在下图的搜索框中输入一个城市的名字,比方说: 沈阳,然后点击搜索,发现页面的地址不变,但是页面的内容改变了;页面中用分页技术显示了该地区的肯德基分店的信息。点击第二页,发现页面的地址也没有变,以上说明这是一个ajax的请求,是异步请求服务器、动态刷新页面。
接着,按照Network-XHR(因为是ajax异步请求)的顺序,发现目前没有请求发往服务器端,所以在关键字处输入查询的城市名,发现此时接收到新的信息:
我们对该请求进行分析,可以找到请求头部的url,并发现该请求是用post方法请求的。在Request Headers处可以找到User-Agent的信息,也就是本机的UA。
下面是请求头:
在From data中可以找到post请求携带的数据:
从以上我们可以分析得知,携带的请求数据一共包含了五个键值对,不难分析得知,前两个为空值,keyword是搜索关键词,pageIndex是分页中的第几页,pageSize是分页中一页最多包含(展示)多少个餐厅的信息。
4. 具体步骤:
难点是对多个页面进行爬取,所以我们要考虑三种情况:1)页面最大容量大于实际页面条目(该地区的餐厅少) ;2)循环到了最后一个页面 ;3)页面最大容量等于实际页面条目。由于获取的是json格式的文件,我们可以按照字典的键值对的方式取值,值得注意的是,有的值是数组,所以我们要对单个页面response的json数据复制粘贴放在在线解析json的网站上进行可视化分析。
在单个页面中,我们要进行一个for循环解析json数据并将storeName逐个放进列表里面,这里大家可以自由发挥,用字典采集自己感兴趣的数据。单个页面又在大的while循环中,当判断Table1为空时,跳出循环,爬取结束。
5. 代码(内含详细注释):
# 爬取肯德基指定地区的餐厅数 import requests import json if __name__ == "__main__": # 如果在搜索框输入信息,回车后网址没变而页面有变化,说明这是一个ajax请求 # 在该网页中,这个一个post方法 cityName = input('请输入你想爬取的肯德基餐厅的城市: ') url = "http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword" pageIndex = '1' data = { 'cname': '', 'pid': '', 'keyword': cityName, 'pageIndex': pageIndex, 'pageSize': '10' } # 进行UA伪装,携带请求头参数,否则会被网页认为你是用pycharm等编译器在进行爬虫而被禁止访问 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36 Edg/87.0.664.55' } try: # 以写文件的形式打开一个文件 loop = True # 这个列表/字典用来存放北京市的所有餐厅的名字,或者用一个字典 data_list = [] print('肯德基在'+cityName+'分店分布为:') while loop: response = requests.post(url=url, data=data, headers=headers) json_data = response.json() # 使用if not x这种写法的前提是:必须清楚x等于None, False, 空字符串"", 0, 空列表[], 空字典{}, 空元组()时对你的判断没有影响才行 if not json_data['Table1']: # loop = False break # 不用json格式的数组录入,是因为追加的话,整体就不是json格式的数据了,如果解析json再拼接的话,更加耗费时间 # json.dump(json_data, fp=fp, ensure_ascii=False) 所以该方法被舍弃 # 以下的逻辑看似恐怖,其实只是对分页进行简单的逻辑分析 if int(json_data['Table'][0]['rowcount'])-int(pageIndex)*int(data['pageSize']) >= 0: for i in range(0, int(data['pageSize'])): print(json_data['Table1'][i]['storeName']) data_list.append(json_data['Table1'][i]['storeName']) # 假如该该地区的总餐厅数没有分页的数多,则做以下操作 elif int(data['pageSize']) > int(json_data['Table'][0]['rowcount']): for i in range(0, int(json_data['Table'][0]['rowcount'])): print(json_data['Table1'][i]['storeName']) data_list.append(json_data['Table1'][i]['storeName']) else: for i in range(0, int(json_data['Table'][0]['rowcount'])-(int(pageIndex)-1)*int(data['pageSize'])): print(json_data['Table1'][i]['storeName']) data_list.append(json_data['Table1'][i]['storeName']) # 更新页码 pageIndex = str(int(pageIndex) + 1) data['pageIndex'] = pageIndex print('-----循环结束-----') # 值得注意的是:追加而不覆盖用a,而不是w # fp = open('./Data/BeijingKFC.json', 'a', encoding='utf-8') with open('./Data/BeijingKFC.txt', 'w', encoding='utf-8') as fp: fp.write(str(data_list)) except IOError: print('写入异常!') else: print('爬取结束!') fp.close()
6. 结果展示:
7. 使用工具:
pycharm,需要导入requests和json包
8. 结束语:
这个分享教程,只是对爬虫初学者的入门,最后祝大家学业有成!(觉得不错就点个赞吧,有错误希望可以指正,谢谢!)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。