爬虫入门—requests模块基础之药监企业信息爬取

爬虫入门—requests模块基础之药监企业信息爬取


Author: Labyrinthine Leo   Init_time: 2021.02.22


Key Words: Spiderrequests库


公众号:Leo的博客城堡

Leo


head.png


1、需求分析

需求:在上一节中,通过输入关键字对肯德基餐厅信息进行爬取;这一节,我们主要对国家药监局化妆生产许可证的企业信息进行爬取(首页地址:http://scxk.nmpa.gov.cn:81/xk/)。此案例是对requests模块的综合使用,设计到抓包数据的分析,可能相对前面的简单案例来说有点复杂,但是难度不大。

分析

  1. 首先,我们通过urlhttp://scxk.nmpa.gov.cn:81/xk/进入网页,可以看到如下图的药监局化妆品许可证信息的页面。其中包含各企业的简要信息,包括企业名称、许可证编号等。

00.png

  1. 我们打开开发者模式进行网页分析时,会发现这些简要信息也是异步渲染显示的,因此对首页进行爬取是无法获取的,于是和前几个案例一样,进行POST请求,同时,该请求包含多个参数,这样参数都可以固定,当然,其中的page表示页面索引,我们可以设置索引方便访问多个页面数据,参数封装与前面大同小异,不多赘述。

02.png

02.png

  1. 但是我们真正需要的并不是上面页面的简要信息,我们需要的是每个企业名称点进去的超链接显示出来的许可证详情信息,如下图所示。

03.png

04.png

  1. 既然每一个企业名称对应一个超链接,我们可以先在首页中获取每个企业信息中的链接,然后根据对应的链接再依次访问并获取详细信息。于是我们在详情页打开开发者模式,可以发现,详情数据的请求也是ajax页面加载,并且每个页面的url相同,只是在POST参数中有一个id参数,并且各不相同。基本可以断定,该id参数就是每个详细页的唯一标识,既然如此,那我们只需要知道每个详细页的id即可直接访问并获取页面了,那该编码id如何获取?

06.png

07.png

08.png

  1. 我们重新返回首页,发现在简要信息也获取时,网站响应的json数据中就包含了每个公司对应的id,那就好办了,我们可以根据需要页面数先访问首页,获取对应的id,然后再对id参数封装访问详细页数据即可爬取每个公司的信息。

05.png

  1. 基础的流程已经分析清楚,接下来便可动手编码了。
2、编码
# coding  : utf-8
# fun     : 爬取药品监管局化妆品许可证信息
# @Author : Labyrinthine Leo
# @Time   : 2021.01.31

import requests
import json

def nmpa_spider(url=None):
    """
    根据首页url动态爬取信息
    :param url: url链接
    :param num: 欲爬取页数数量
    :return: json_list
    """
    if url is None:
        print("url should not be None!")
        return
    # ----------获取公司信息的id----------
    # 1.指定url
    url = url
    num = 10 # 页数
    # 2.UA伪装
    headers = {
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36'
    }
    # 3.设置请求参数
    id_list = [] # 初始化保存id的list
    for i in range(1, num):
        # 遍历每一页
        params = {
            'on': 'true',
            'page': str(i),
            'pageSize': '15',
            'productName': '',
            'conditionType': '1',
            'applyname': ''
        }
        # 4.发送请求
        response = requests.post(url=url, data=params,headers=headers)
        # 5.获取响应数据
        jsons = response.json() # 获取响应的json数据
        for dic in jsons["list"]:
            id_list.append(dic["ID"])
    print("已成功爬取id {}条!".format(len(id_list)))

    #----------获取每页公司信息的详细信息----------
    # 1.根据id构建url
    detail_url = "http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsById"
    # 2.设置请求参数
    json_list = [] # 初始化公司信息list
    for id in id_list:
        params = {
            'id': id
        }
        # 3.发送请求
        response =  requests.post(url=detail_url, data=params, headers=headers)
        # 4.获取响应数据
        page_json = response.json()
        json_list.append(page_json)
    print("已成功爬取公司信息 {}条!".format(len(json_list)))
    return json_list

def parse_json(json_list):
    """
    解析json数据并持久化存储
    :param json_list: json数据的list
    :return:
    """
    dict_head = {
        '企业名称':'epsName',
        '许可证编号':'productSn',
        '法定代表人':'legalPerson',
        '发证日期':'xkDateStr',
        '有效期至':'xkDate',
        '状态':'xkType'
    }
    fp = open('./nmpa.txt', 'a', encoding='utf-8')
    # ----------交叉合并----------
    # 双列表交叉合并作为表头
    # key_list = list(dict_head.keys()) # 获取key列表
    # empty_list = [' ' for i in range(len(key_list))] # 生成空格
    # new_list = list([y for x in zip(key_list, empty_list) for y in x]) # 交叉合并
    # new_list.append('\n')
    # ----------格式化输出----------
    new_list = [] #
    for i in list(dict_head.keys()):
        new_list.append('{:<20}'.format(i))
    new_list.append('\n')
    fp.writelines(new_list) # 写入表头,按行写入
    for json in json_list: # 遍历json信息list
        info_list = []
        for k in list(dict_head.values()): # 获取json信息关键字
            info_list.append('{:<40}'.format(json[k]))
        info_list.append('\n')
        fp.writelines(info_list)
        print("已成功保存信息:{}".format(json["epsName"]))
    print("已成功保存{}条公司信息!请在nmpa.txt文件中查看!".format(len(json_list)))


if __name__ == '__main__':
    # 主页url
    url = "http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsList"
    # 获取具体信息的json数据
    json_list = nmpa_spider(url)
    # 持久化存储
    parse_json(json_list)

运行结果:

09.png

这里,博主还将其写入了txt文本文件中,排版显得差强人意(供读者自行修正),当然,也可以直接写入excel文件或者数据库中,比较规范,这里主要做爬虫案例解析,这些后续细节读者可自行优化。

10.png

3、总结
  • 此案例,整体来说不算难,只是需要对抓包数据进行细心观察,包含了两个页面的跳转(并且均为异步加载的数据),同时第二个页面需要用到第一个页面响应结果中的id信息,所以两个步骤紧密相连,耦合度高,需要耐心分析,前者保证无误方可。

临渊羡鱼不如退而结网
创作不易,如果您觉得这篇文章对你有用,可以点个赞,算是对笔者的支持和激励!这里是Leo的博客城堡,以Python为核,ML&DL为主,泛之形形色色,输寥寥拙见,摄浮光掠影,讲三两故事。临渊羡鱼,不如退而结网,持续干货输出,有趣的灵魂值得你的关注!
原文可以去笔者的github主页:https://github.com/LabyrinthineLeo/Yxs_Git_Learning_repos查看(如果可以,点个star也无妨呀,嘿嘿)。


Leo的博客城堡


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值