requests模块实现药监总局相关数据爬取

  在爬取数据时,我们首先需要通过F12抓包观看它的请求方式、响应数据格式与内容等,一般情况下,可以在响应数据中看到该页面完整的内容,但有时存在其它情况,就是在刷新页面后,发现抓取到的数据只是当前页面的一部分数据,说明没有展现出来的数据很可能是动态加载的,那么这种情况我们肯定不能直接对当前URL发出请求就能获取的,本例就是这种情况。

  该页面抓取到的信息如下:

 

   我们把其中响应数据粘贴出来:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>化妆品生产许可信息管理系统服务平台</title>
    <meta http-equiv="keywords" content="化妆品生产许可信息管理系统服务平台,化妆品生产许可证查询,化妆品生产许可企业查询,化妆品生产许可企业"/>
    <meta http-equiv="description" content="化妆品生产许可信息管理系统服务平台是由国家药品监督管理局主办,此平台可以查到化妆品生产企业信息"/>
    <script language="javascript" type="text/javascript">
       var G = {"baseUrl":"http://scxk.nmpa.gov.cn:81/xk/"};
    </script>
    <script src="http://scxk.nmpa.gov.cn:81/xk/itownet/_static/common/jquery/jquery-1.7.1.min.js"  type="text/javascript" charset="utf-8"></script>
    <script    src="http://scxk.nmpa.gov.cn:81/xk/itownet/_static/common/jquery/plugins/jquery.cookie.js"    type="text/javascript" charset="utf-8"></script>
    <script src="http://scxk.nmpa.gov.cn:81/xk/itownet/portal/jquery.myPagination.js"   type="text/javascript" charset="utf-8"></script>
    <link rel="stylesheet" href="http://scxk.nmpa.gov.cn:81/xk/itownet/portal/style_portal.css" type="text/css" />
    <link rel="stylesheet" href="http://scxk.nmpa.gov.cn:81/xk/itownet/_static/css/page.css"    type="text/css" />

    <script    src="http://scxk.nmpa.gov.cn:81/xk/itownet/portal/portal.js?v=2017-01-15"    type="text/javascript" charset="utf-8"></script>

</head>
<body >
    <div class="hzbbanner"><div class="hzbbannertxt"><a href="http://scxk.nmpa.gov.cn:81/xk/itownet/allQyxx/allQyxx.jsp" target="_self" title="进入化妆品生产许可信息管理系统">【全部许可证】</a><a href="http://scxk.nmpa.gov.cn:81/xk/login.jsp" target="_blank" title="进入化妆品生产许可信息管理系统">【业务办理】</a></div></div>
    <div class="hzbscbox">
        <div class="hzbscin">
            <div style="position:relative;">
                <div class="hzbtabs">
                        <span id="xkzh" class="hzbtabon" dataid="1">许可证编号</span>
                        <span id="qymc" dataid="2">企业名称</span>
                        <span id="xydm" dataid="3">社会信用代码</span>
                        <span id="sf" dataid="4">所属省份</span>
                        <span id="lb" dataid="5">生产类别</span>
                        <input type="hidden" id="conditionType" value="1"/>
                </div>
            </div>
            <input type="text" id="searchtext" class="hzbsr" name="kw" value=""    placeholder="请输入许可证号" />
                <input type="button" class="hzbbtn"    id="searchInfo" value="查询" />
        </div>
    </div>

    <div class="dzpzmain">
        <div id="FileItems">
            <ul class="hzblist"  style="margin-top: 0px;margin-bottom: 0px;border-top: 0px;border-bottom: 0px;">
                <li class="columm"><i>发证日期</i>
                    <dl>企业名称
                    </dl>
                    <ol>许可证编号
                    </ol>
                    <p>发证机关</p> <em>有效期至</em>
                </li>
            </ul>
            <ul class="hzblist" id="gzlist" style="margin-top: 0px;border-top: 0px;">

            </ul>
        </div>
        <div id="itownetPage"></div>

    </div>


    <div class="hzbbtm">
        本站由<a href="http://www.sfda.gov.cn/WS01/CL0479/" target="_blank">国家药品监督管理局</a>主办
        版权所有 未经许可禁止转载或建立镜像 Copyright &copy; NMPA All Rights Reserved
    </div>
</body>
</html>

  显然,里面并没有相关公司的具体数据,当我们再次刷新页面,并选中XHR,会发现发送了一个新的POST请求(此时URL并没有改变,说明存在ajax):

 

   此外,我们发现返回的响应数据是多个列表存放在一个字典中,而且每个公司对应了一个ID属性,接下来进入到具体的某个公司的详情页,同上操作会发现详情页中的数据仍然存在动态加载的数据:

 

   因此,通过分析,我们可以得出结论:每个公司对应唯一的属性值id,每次刷新时会根据id动态加载出对应公司的详情页,然后再把该详情页的URL以超链接的形式动态加载到首页中,如此一来爬虫程序就比较复杂了。

  首先,我们要批量获取ID值,因为有了ID才能找到对应的公司(顺便实现分页爬取功能):

  for page in range(1,3):
        page = str(page)
        data = {
            'on':' true',
            'page':page,
            'pageSize':' 15',
            'productName':'',
            'conditionType':' 1',
            'applyname':'',
            'applysn':'',
        }
        json_ids = requests.post(url=url,data=data,headers=headers).json()
        # print(json_ids)

        # 从json_ids字典中取出list对应的value值(是个列表):json_ids['list'],然后遍历该列表,拿到的每一部分都是个字典
        for dic in json_ids['list']:
            # dic是每个小字典,里面含有ID等信息,我们只需要拿出ID对应的value值,然后把它添加到一个列表中id_list
            # aaa.append(data):把数据data添加到链表aaa末尾
            id_list.append(dic['ID'])
        # print(id_list)

  此时,id_list中就已经存储了前两页的企业对应的id,接下来一边遍历该列表,一边模拟浏览器发送请求,最终可得到前两页所有企业的详情数据:

   post_url = 'http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsById'
    for id in id_list:
        data = {
            'id':id
        }
        detail_json = requests.post(url=post_url,data=data,headers=headers).json()
        # print(detail_json)
        all_data_list.append(detail_json)

  最后,持久化存储后,可成功爬取前两页企业的详情数据:

  

  至此,requests模块暂时告一段落,接下来学习数据解析部分,先简单介绍一下:

  数据解析适用于聚焦爬虫,用于爬取一整张页面的局部数据,有三种方式:正则、bs4、Xpath。

 

 

 

  

posted @ 2022-01-16 17:43  Sunshine_y  阅读(935)  评论(0编辑  收藏  举报