项目实训(六)

  1. 目标网站分析

网站名称 URL :

网站名称:“全国防疫政策一键查询”

网站URL:

https://app.21jingji.com/html/2021yiqing_cxcx/index2022.html

该网站采用反爬虫技术:

JavaScript动态加载数据

展示网站的反爬虫存在:

网站截图如下:

网页实时审查元素:

防疫政策相关的所有内容位于“id=result”的div内

查看源代码时(直接对网站发出请求)所得:

发现原本存储防疫政策的块内内容不存在,直接请求网页无法获得数据。

  1. 操作过程

工作思路

因为在审查元素时和检查源代码时发现内容差异,因此判断数据为动态加载,因此使用浏览器查看该网站的脚本文件:

可以发现网站对于选择城市后的处理过程,发现在选择城市后,脚本对‘js/citylist.json’发出请求,那我们同样对这个url进行一次请求,加上前置的网站url:

“https://app.21jingji.com/html/2021yiqing_cxcx/js/citylist.json”

得到如下内容:

可以看到这是一个中国各城市(地区)以及其对应的id,这对后面获得对应疫情数据应该有帮助,我们继续查看JavaScript代码:

如上,根据citylist中的内容和网页上点击的情况,调用InitPolicy(),经查看,代码如下:

可以看到网站对一个接口发出请求,而且参数正是上面我们所获得的citylist中对应的城市(地区)id,但这里参数包含两个城市,出发地和目的地,但我们所需要的是单个城市出入政策,根据规律,我们仅使用一个城市id作为参数,发现请求能够成功,返回单个城市的出入政策以及风险地区:

 

那么接下来的工作就是根据一开始获得的citylist.json文件中对应城市id,对所有城市请求得到所有城市的防疫政策即可,结果如下:

源代码分析

网站源代码:

经由审查能看到所有具体政策存储在id=result的div下,出发地政策放在id=startItem的div下,目的地政策放在id=destinationItem的div下。

        

网站JavaScript源代码:

根据citylist.json中城市和省份对应id,和网页上选择的省和城市作对比,首先对页面上展示出发地和目的地的容器内容进行更改,之后调用initPolicy()。

InitPolicy()根据选择的城市对接口发出请求,然后根据所返回的数据对网页内容进行异步渲染,即更改id=result的div的html内容,具体过程为添加了id=startItem和id=destinationItem的div的内容,包括了出入政策以及中高风险地区(如果存在)。

  1. 爬取数据   

保存格式

.json文件

数据量大小

总计4MB数据。

  1. 源代码分析
  2.     url = 'https://app.21jingji.com/html/2021yiqing_cxcx/index2022.html'
        # 城市表
        citylist = 'https://app.21jingji.com/html/2021yiqing_cxcx/js/citylist.json'
        # 出行政策以及风险地区
        policy = 'https://m.21jingji.com/dynamic/zhanyi2020/getCityPolicy?'

get_city_list()获取城市列表:

        

    req = requests.get(citylist)
    req.encoding = 'utf-8'
    data = json.loads(req.text)

    with open('js/citylist.json', 'w') as f:
        json.dump(data, f)
        print("citylist写入完毕!")

    city_list = []
    # 第一层是以省为单位
    for each in data:
        # 第二层存储在第一层的'list'字段中
        for city in each['list']:
            city_list.append(city['id'])
            # print(city)

    return city_list

因为此处已将citylist.json保存至本地,因此直接打开了该文件,根据该json文件的格式,我们除掉第一层(保存省份id),直接获取所有的城市id。

get_policy_list()获取所有城市的政策:

    policy_list = []
    for each in tqdm(city_list):
        each_policy = get_policy(policy, each)
        # print(each['id']+each['name'])
        sleep(0.01)
        policy_list.append(each_policy)

    with open('js/policylist.json', 'w') as f:
        json.dump(policy_list, f)
        print("policylist写入完毕!")

根据上面获得的城市id,对每一个城市调用get_policy

get_policy()如下:

# ['city_id',城市编号
# 'province',省名
# 'city',市名
# 'leave_policy',出境政策
# 'leave_policy_date',出境政策发布日期
# 'back_policy',入境政策
# 'stay_info',住宿须知
# 'back_policy_date',入境政策发布日期
# 'poi_list',风险地区
#           "area": 社区名称,
#           "type": "1"中风险,“2”高风险
#           "sid": 位置,
#           "province": 所属省,
#           "city": 所属市(地区),
#           "adcode": 同cityid,
#           "district_adcode": 社区编号
# 'leave_policy_list',
# 'back_policy_list',
# 'stay_info_list'同上(格式化数据),
# 'city_code',同上
# 'district'空值]
# 获取某个城市的政策已经风险地区等级
def get_policy(policy, cityid):
    head = {'User-Agent': 'Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, ''like '
                          'Gecko) Chrome/18.0.1025.166  Safari/535.19 '}
    para = {'cityid': cityid}
    req = requests.get(url=policy, params=para, headers=head)
    req.encoding = 'utf-8'
    status = json.loads(req.text)['status']
    # 没有发布防疫政策的地区不含有data字段,status为0
    if status != 1:
        pass
    else:
        data = json.loads(req.text)['data']

        city_policy = {'cityid': cityid, 'data': data}
        return city_policy

注释为所获取数据的格式以及各个字段含义,get_policy()发出请求,根据请求返回的status(状态)字段判断该城市是否有发布对应政策,如果没有则pass。

返回政策。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值