Python爬虫 | 双十一篇之网购买的化妆品从哪里来?

长江三角洲
在这里插入图片描述
示例网站:化妆品生产信息许可信息管理系统服务平台

一、 网页展示

  1. 管理平台首页
    在这里插入图片描述
    点击任意一家企业,即可获取到企业的详细地址信息。

  2. 企业相信信息
    在这里插入图片描述

地址
经纬度
热力图

二、 页面逻辑

主页

在这里插入图片描述
在这里插入图片描述

经测试页面企业数据是通过 Ajax 请求,每点击一次就会获取一个新的页面

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

上图详细数据(脱敏)
{“filesize”:"",“keyword”:"",“list”:[
{“ID”:“a8c852318cb9448092939892be82e155”,“EPS_NAME”:"******** 制造有限公司",“PRODUCT_SN”:“粤妆2016 ****”,“CITY_CODE”:null,“XK_COMPLETE_DATE”:{“date”:9,“day”:1,“hours”:0,“minutes”:0,“month”:10,“nanos”:0,“seconds”:0,“time”:1604851200000,“timezoneOffset”:-480,“year”:120},“XK_DATE”:“2024-03-26”,“QF_MANAGER_NAME”:“广东省药品监督管理局”,“BUSINESS_LICENSE_NUMBER”:“914401113401150236”,“XC_DATE”:“2020-11-09”,“NUM_”:16},
{“ID”:“7369d92fab2941bba84df512849889a4”,“EPS_NAME”:“东莞市 **** 化妆品有限公司”,“PRODUCT_SN”:“粤妆2016 ****”,“CITY_CODE”:null,“XK_COMPLETE_DATE”:{“date”:6,“day”:5,“hours”:0,“minutes”:0,“month”:10,“nanos”:0,“seconds”:0,“time”:1604592000000,“timezoneOffset”:-480,“year”:120},“XK_DATE”:“2021-07-20”,“QF_MANAGER_NAME”:“广东省药品监督管理局”,“BUSINESS_LICENSE_NUMBER”:“91441900MA4UKT7Y27”,“XC_DATE”:“2020-11-06”,“NUM_”:17},{此处省略另外13家企业}],“orderBy”:“createDate”,“orderType”:“desc”,“pageCount”:359,“pageNumber”:2,“pageSize”:15,“property”:"",“totalCount”:5385}

详情页

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

上图详细数据(脱敏)
{“businessLicenseNumber”:“91440101MA5CYUF0XX”,“businessPerson”:“陈 ** “,“certStr”:“一般液态单元(护发清洁类、护肤水类、啫喱类);膏霜乳液单元(护肤清洁类、护发类)”,“cityCode”:””,“countyCode”:"",“creatUser”:"",“createTime”:"",“endTime”:"",“epsAddress”:“广州市白云区 ********************(自主申报)”,“epsName”:“广东****化妆品科技有限公司”,“epsProductAddress”:“广州市白云区 ************************* (自主申报)”,“id”:"",“isimport”:“Y”,“legalPerson”:“陈 ** “,“offDate”:””,“offReason”:"",“parentid”:"",“preid”:"",“processid”:"",“productSn”:“粤妆2020 **** “,“provinceCode”:””,“qfDate”:"",“qfManagerName”:“广东省药品监督管理局”,“qualityPerson”:“高 **** “,“rcManagerDepartName”:“白云区局均禾市场监管所”,“rcManagerUser”:“监管机构指定人员”,“startTime”:””,“xkCompleteDate”:null,“xkDate”:“2025-01-16”,“xkDateStr”:“2021-05-17”,“xkName”:“严 ** “,“xkProject”:””,“xkRemark”:“无”,“xkType”:“201”}

总结:
首页逻辑:通过 Ajax 请求获得15个企业的基本信息及该 企业ID 渲染后展示在页面上, Ajax 使用post请求携带页码条数等信息。
详情页逻辑:详情页网址为http://scxk.nmpa.gov.cn:81/xk/itownet/portal/dzpz.jsp?id= 企业ID
访问详情页触发 Ajax发送 post 请求获取企业的具体数据。Ajax 使用 post 请求携带企业id。
所以通过 Ajax 请求即可获取企业ID,再携带企业ID发送 Ajax 获取企业详细数据,提取需要的字段即可进行分析。

三、 用代码爬取数据

1. 创建数据库

在这里插入图片描述

1. 导入包

import requests
import random
import time
import pymysql

2. 向网页发送 requests 请求,返回 json 格式数据

def requests_json(url, data):
    User_Agent_list = [
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/18.17763',
        'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko',
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4292.2 Safari/537.36']
    headers = {  # 封装请求头
        'User-Agent': random.choice(User_Agent_list)  # 随机选取一个 User-Agent
    }
    # 随机延时,其实可以调的更快,但是没必要,做人留一线~
    time.sleep(random.uniform(0.6, 1.4))
    return requests.post(url=url, headers=headers, data=data).json()

3. 主函数

if __name__ == '__main__':
    # 1. 连接数据库
    conn = pymysql.connect(host='127.0.0.1',
                           user='root',
                           port=3306,
                           passwd='',
                           database='cosmetics',
                           charset='utf8')
    db = conn.cursor()
    # 2. 数据初始化
    pageCount = 9999
    main_url = 'http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsList'
    details_url = 'http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsById'
    main_data = {
        'on': 'true',  # 暂时不明
        'pageSize': '15',  # 一页显示多少条数据
        'productName': '',  # 搜索词: 历史搜索词['','粤妆2016','2016','2017','2018','2019','2020','1600-1609','161','162']
        'conditionType': '1',  # 搜索方式:1为许可证编号,2为企业名称,3为社会信用代码
        'applyname': '',  # 暂时不明
        'applysn': '',  # 暂时不明
    }
    details_data = {}
    sql = """INSERT INTO nmpa(ID,businessLicenseNumber,epsName,productSn,epsAddress,businessPerson,rcManagerDepartName,xkDate,xkDateStr) VALUES ('%s','%s','%s','%s','%s','%s','%s','%s','%s')"""
    # 3. 爬取首页数据,获得公司ID
    for page in range(1, pageCount):
        # 不知道是反爬机制还是什么鬼,第 51-200 页数据死活就是请求不到,网页上也看不到这些页数据,不如直接跳过去~
        if 50 < page < 200:
            continue
        main_data['page'] = str(page)
        try:
            data_json = requests_json(main_url, main_data)
            if int(data_json['pageCount']) < page:
                break
            print('正在爬取第{}页'.format(page))
        except:
            print('第{}页爬取失败!'.format(page))
            time.sleep(10)  # 网页异常,暂停 10 秒
            continue
        # 4. 爬取详情页数据
        else:
            for dic in data_json['list']:
                if db.execute("""SELECT * FROM nmpa WHERE ID='%s';""" % dic['ID']):
                    print('该公司数据已保存: {}'.format(dic['EPS_NAME']))
                else:
                    try:
                        details_data['id'] = dic['ID']
                        detail_data = requests_json(details_url, details_data)
                    except:
                        time.sleep(10)  # 网页异常,暂停 10 秒
                    else:
                        print('正在保存: {}'.format(detail_data['epsName']))
                        # 5. 将数据保存到数据库当中
                        add_sql = sql % (
                            dic['ID'], detail_data['businessLicenseNumber'], detail_data['epsName'],
                            detail_data['productSn'],
                            detail_data['epsAddress'], detail_data['businessPerson'], detail_data['rcManagerDepartName'],
                            detail_data['xkDate'], detail_data['xkDateStr'])
                        db.execute(add_sql)  # 执行 SQL 语句
                        conn.commit()  # 提交

四、 通过百度地图开放平台 API 接口将地址转化为经纬度


在这里插入图片描述

import pymysql
import requests
import re, json

# 从数据库中取数据
conn = pymysql.connect(host='127.0.0.1', user='root',
                       port=3306,
                       passwd='',
                       database='cosmetics',
                       charset='utf8')

db = conn.cursor()
ak = 'ndWOIl9GdR***'  # 在百度地图开放平台申请接口并替址:http://lbsyun.baidu.com/apiconsole/key#/home
baidu_api_url = 'http://api.map.baidu.com/geocoding/v3/?address={}&output=json&ak={}&callback=showLocation'
select_sql = """SELECT ID,epsAddress FROM nmpa WHERE lat is null;"""  # 找到数据库经纬度当中为null的
update_sql_no_parameters = """UPDATE nmpa SET lat={lat},lng={lng} WHERE ID='{id}';"""

while True:
    data = db.execute(select_sql)
    enterprise = db.fetchone()
    if enterprise is None:
        print('所有企业经纬度已经全部添加完毕!')
        break
    address = re.sub(u"([^\u4e00-\u9fa5])", "", enterprise[1])  # 去掉地址当中的非中文部分
    baidu_text = requests.get(baidu_api_url.format(address, ak)).text  # 取出返回结果当中的json部分
    baidu_text = re.findall(r'[(](.*?)[)]', baidu_text)
    baidu_json = json.loads(baidu_text[0])
    if baidu_json['status'] == 0:  # 0  正常
        baidu_json = baidu_json['result']['location']
        update_sql = update_sql_no_parameters.format(lat=float(baidu_json['lat']), lng=float(baidu_json['lng']),id=enterprise[0])
        db.execute(update_sql)
        conn.commit()
        print('企业:{: <50} lat={} lng={}'.format(enterprise[1], float(baidu_json['lat']), float(baidu_json['lng'])))
    elif baidu_json['status'] == 1:  # 1: 服务器内部错误
        print(baidu_json['msg'])
        update_sql = update_sql_no_parameters.format(lat=0.000000, lng=0.000000, id=enterprise[0])
        db.execute(update_sql)
        conn.commit()
    else:
        print(baidu_json['msg'])
        break

五、 通过百度地图开放平台 API 接口将地址转化为图

在这里插入图片描述
文档写的很清楚,在此就不赘述了,直接上效果图。

效果图

全国热力图

全国

主要化妆品生产省市热力图

北京
广州
长江三角洲
武汉

该网页遇到问题以及解决方案

总结:
普遍性问题:

  1. 爬虫速度过快,需要添加延时函数减慢速度。
  2. User_Agent,多放几个随机使用。

特例性问题:

  1. 第50页-200页数据服务器返回结果为空,通过不断修改搜索词,多次变着花样才完整保存下来。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序猿过家家

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

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

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

打赏作者

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

抵扣说明:

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

余额充值