Python爬虫爬取肯德基餐厅信息案例实现(含源码及详细解释)

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。
General
下面是请求头:Request Headers
在From data中可以找到post请求携带的数据:
post请求要携带的参数
从以上我们可以分析得知,携带的请求数据一共包含了五个键值对,不难分析得知,前两个为空值,keyword是搜索关键词,pageIndex是分页中的第几页,pageSize是分页中一页最多包含(展示)多少个餐厅的信息。
以北京为例子,底部1-7即为分页
4. 具体步骤:
难点是对多个页面进行爬取,所以我们要考虑三种情况:1)页面最大容量大于实际页面条目(该地区的餐厅少) ;2)循环到了最后一个页面 ;3)页面最大容量等于实际页面条目。由于获取的是json格式的文件,我们可以按照字典的键值对的方式取值,值得注意的是,有的值是数组,所以我们要对单个页面response的json数据复制粘贴放在在线解析json的网站上进行可视化分析。由于我点击了两个页面,所以有两个ajax异步请求
在单个页面中,我们要进行一个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. 结束语:
这个分享教程,只是对爬虫初学者的入门,最后祝大家学业有成!(觉得不错就点个赞吧,有错误希望可以指正,谢谢!)

评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TerryBlog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值