Python requests请求爬虫

Python 疫情__数据【包括国内外】

更多关于机器学习的知识请加关注哟~~。若需联系请私信或者加博主联系方式:
     新浪微博:Jetuser
     微信公众号:不一样的数据分析

    抖音号:1858359940

    CSDN : Jetuser-data

前言

       这几天上班忙的不可开交,纵观新型冠状病毒近日在国外大势猖獗,随国内控制的不错,但仍需努力,不可懈怠,武汉加油!中国加油!全世界人民加油!刚好赶上周末,就闲下来写一下python requests请求方式爬取国内外疫情数据,我的方法是最易懂、最高效、爬取是最全的,我以人头担保【惊恐/滑稽】,没有谁的会比我的全。这次我将以该百度链接进行抓取。

1、如何开始?

       首先我们看看该上网页的数据

       可以看到数据在网页上显示为这个鬼样子,那么我们如何将其抓取下来呢?

2、思路解析

       其实爬虫就如同我们做事情一样的,按部就班,一步一个脚印,解决途中一步步困难。包括读取网页、数据读取、数据清洗以及后期的可视化展现…
       我的思路就是先将网页request出来,text读取里面的内容,然后使用强大的正则表达式匹配出我们想要的内容再写入到excel 中,注意这样是得到一天的数据,那么我们要写一个while循环,让其固定在每天晚上11点过进行自动爬取,每天的数据依次累加到excel里面,最终得到完整的表格 [ps:我这里用Google浏览器]。

3、爬虫解析

       进入页面后按键盘上的F12,依次点击 Network–>XHR–> 并按下ctrl+R,此时点击下方出现的XHR,找到
Request Headers下的Referer,你会看到这是一个链接,这个链接就是我们要请求的网页,将其复制下来。

4、爬虫步骤

4.1 请求网页响应且返回数据

url = 'https://voice.baidu.com/act/newpneumonia/newpneumonia/?from=osari_pc_3'
response = requests.get(url=url)
response.text

       这时候往下滑动你会得到一串带有"\u"的字符串

"subList":[{"city":"\\u897f\\u5b81","confirmed":"15","died":"","crued":"1
5","confirmedRelative":"0","curConfirm":"0","cityCode":"66"},{"city":"\\u6d77\\u5317\\u5dde","confirmed":"3","died":"","crue
d":"3","confirmedRelative":"0","curConfirm":"0","cityCode":"67"
}]},
{"confirmed":"298","died":"2","crued":"30","relativeTime":"1585
324800","confirmedRelative":"16","diedRelative":"0","curedRelat
ive":"0","curConfirm":"266","curConfirmRelative":"16","icuDisab
le":"1","area":"\\u53f0\\u6e7e","subList":[]},
{"confirmed":"641","died":"4","crued":"118","relativeTime":"158
5324800","confirmedRelative":"64","diedRelative":"0","curedRelative":"1","curConfirm":"519","curConfirmRelative":"63","cityCode":"2912","icuDisable":"1","area":"\\u9999\\u6e2f","subList":[]}

       这TM是什么鬼,好!既然是鬼就收它,我猜这个Unicode就是城市名称,打开站长解码输入带有"\u"的任意字符比如"\u897f\u5b81"你会得到“\西\宁”二字,果然就是,那么其实我们已经找到了,只是需要将其解码出来即可。
       此时我们又有新思路,先将中国疫情数据找到并且匹配出来,再将国外疫情数据找到又匹配出来,最终得到每个字段并且存入excel即可。

4.2 找到数据列表

       其实将带有"\u"的字符串进行解码可知,网页上的图表数据在返回的"captain-config"到"bundle"之间,于是有

datas=re.findall(r'id="captain-config">(.*?)"bundle"', response.text)# 得到初步  来源方式
data=re.findall(r'(.*),"version"', datas[0])# 得到初步 来源方式 加?是贪婪模式 最短匹配

       这样就会得到我们所需的数据集,但是我后来发现,老是这样一次次解码太麻烦,干脆一次性将其转为中文,便于观察,但是带有"\u"的翻译出来又多一个"",所以先将其替换掉再转为中文,于是有

data0 = 'u'+'\''+data[0].replace('\\\\', '\\')+'\''
data3=eval(data0) # 替换斜杠并转编码 神奇的eval函数
# 打印部分结果

"area":"贵州","subList":[{"city":"六盘水","confirmed":"10","died":"1","crued":"9","confirmedRelative":"0","curConfirm":"0","cityCode":"147"},
{"city":"毕节地区","confirmed":"23","died":"","crued":"23","confirmedRelative":"0","curConfirm":"0","cityCode":"206"},
{"city":"黔西南州","confirmed":"4","died":"","crued":"4","confirmedRelative":"0","curConfirm":"0","cityCode":"343"},

4.3 找到国内疫情数据

       同样的正则表达式匹配方法,先找出国内的疫情数据,再将其按照字段封为列表,最后将列表挨个存到datefream里最后写为excel文件。

Home_List=re.findall(r'"caseList":(.*),"caseOutsideList"',data3)  # 得到国内疫情
Home_Lis=eval(Home_List[0])
Home_Lis[6] # 得到吉林省[你的可能不是吉林]以及其各城市疫情数据
{'confirmed': '98',
'died': '1',
'crued': '92',
'relativeTime': '1585324800',
'confirmedRelative': '1',
'diedRelative': '0',
'curedRelative': '0',
'curConfirm': '5',
'curConfirmRelative': '1',
'icuDisable': '1',
'area': '吉林',
'subList': [{'city': '延边',
'confirmed': '5',
'died': '',
'crued': '5',
'confirmedRelative': '0',
'curConfirm': '0',
'cityCode': '54'},
{'city': '四平',
'confirmed': '15',
'died': '1',
'crued': '14',
'confirmedRelative': '0',
'curConfirm': '0',
'cityCode': '56'},
{'city': '通化',
'confirmed': '6',
'died': '',
'crued': '6',
'confirmedRelative': '0',
'curConfirm': '0',
'cityCode': '165'},...]}

       到这里可以发现Home_Lis下的前11个键值就是该省份数据,而该省各城市数据就在’subList’里面,对应的建就有:“累计确诊”,“新增确诊”,“累计治愈”,“新增治愈”,“累计死亡”,“新增死亡”,“累计确诊”,"新增确诊"等数据。此时对于一个省份我想生成这样的数据集:

   报道时间   国家  省分  城市 累计确诊 新增确诊 累计治愈 ...
2020-03-29 中国 吉林 - 98 0 92 ...
2020-03-29 中国 吉林 四平 5 0 14 ...
2020-03-29 中国 吉林 通化 15 0 6 ...
....

       也就是要生成时间列、国家列、省份,而且这些列的长度刚好等于每个’subList’下城市个数+1(因为Home_Lis下的前11个键值就是列表的第一行,这行就是该省的汇总行,也是该省的第一行,所以长度得多出一个),这样得到每个省份数据然后再拼接起来就是国内数据啦!!代码为:

date=datetime.datetime.now()  # 获取当地时间
start_date = '%s-%02d-%02d'%(date.year,date.month,date.day)
province=[Home_Lis[6]['area']]*(len(Home_Lis[6]['subList'])+1) # 得到省份
dataloct=[start_date]*(len(Home_Lis[6]['subList'])+1) # 为了扩展长度一致
country=["中国"]*(len(Home_Lis[6]['subList'])+1)
countren=["China"]*(len(Home_Lis[6]['subList'])+1)
city=re.findall(r"city: (.*?),", str(Home_Lis[6]['subList']).replace("'",'')) # 得到城市
city.insert(0,'-')
confirmed=re.findall(r"confirmed: (.*?),", str(Home_Lis[6]).replace("'",''))#得到累积确诊
died=re.findall(r"died: (.*?),", str(Home_Lis[6]).replace("'",'')) # 得到累积死亡
confirmedRelative=re.findall(r"confirmedRelative: (.*?),", str(Home_Lis[6]).replace("'",'')) # 得到新增确诊
Cure=re.findall(r"crued: (.*?),", str(Home_Lis[6]).replace("'",'')) # 得到累积治愈
curedRelative=re.findall(r"curedRelative: (.*?),", str(Home_Lis[6]).replace("'",'')) # 得到新增治愈
curedRelative.extend(['']*len(Home_Lis[6]['subList']))
diedRelative=re.findall(r"diedRelative: (.*?),", str(Home_Lis[6]).replace("'",'')) # 得到新增死亡
diedRelative.extend(['']*len(Home_Lis[6]['subList']))
requ=pd.DataFrame({'报道时间':dataloct,'国家':country,'国家EN':countren,'省份/国家(国外)':province,
'城市':city,'累积确诊':confirmed,'新增确诊':confirmedRelative,
'累积治愈':Cure,'新增治愈':curedRelative,'累积死亡':died,
'新增死亡':diedRelative})

4.3 匹配综述

       到这里其实你想要的数据都可以获取到,只要正则表达式匹配的正确,按照同样的思路即可找出国内外的疫情数据,以及国内外疫情数据汇总,方法和思路都是一样的,当然这仅仅是我的方法和思路,还有很多种做法供大家发散思维,欢迎评论区探讨。

5、主函数[你可以直接运行]

       运行说明:1、当你打开if __name__ == '__main__':里面的“控制链1”和“控制链2”并且调整好缩进后,程序就会在固定每天晚上23:55:59运行该脚本下载当天的疫情数据,如果挂机30天将会下载一个整月的数据!如果不打卡这两个控制链,程序仅会运行一次且下载当天的疫情数据。结果会生成两个excel文档,“全球疫情汇总数据”和“全球疫情数据”,前者是每日都有的,后者是当天的,生成的路径是在指定的“D:\Data\epidemic_situation\疫情数据”下。

import pandas as pd
import requests
import urllib.request
import time
import datetime
import http.cookiejar as cj
import time
import os
import json
import ast
import xlwt
import re
import warnings

def catch_daily():
"""抓取每日确诊和死亡数据"""
url = 'https://voice.baidu.com/act/newpneumonia/newpneumonia/?from=osari_pc_3'
response = requests.get(url=url)
datas=re.findall(r'id="captain-config">(.*?)"bundle"', response.text)# 得到初步 来源方式
data=re.findall(r'(.*),"version"', datas[0])# 得到初步 来源方式 加?是贪婪模式 最短匹配
data0 = 'u'+'\''+data[0].replace('\\\\', '\\')+'\''
data2=eval(data0)
return data2

def China_epid_situ(data3,start_date
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值