世界疫情的数据很多网站都有,这里我还是使用手机网易的疫情数据接口。
首先,切换ua,换成手机模式。百度搜索“网易 疫情”,
第一个就是。
打开这个网址,点开开发者工具,刷新一下。就可以看到有这么几个,第一个请求,就是数据
但是这里我们要用的是世界疫情。所以,还得往下多看几眼。
这第一个请求里,会给你今天的世界疫情数据。但是我们想绘制的是随着时间变化,增长的数据竞赛柱状图。只有一天是不行的。
但是,这里有一个游泳的数据是,areaTree下面,每一个国家的id都有了。
后面用数据的请求接口,需要用到这个id。这里我就选7个国家,每个单独记下来就行,也没必要用request提取。
当然了,这里我也是用的python。毕竟第一次也不知道这几个国家的id。
import numpy as np import pandas as pd import matplotlib.pyplot as plt import re import os import time import requests plt.rcParams["font.family"] = "SimHei" wk_dir = "数据分析" data_dir = "数据分析/data" headers = { 'User-Agent': 'Mozilla/5.0 (Linux; Android 11) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.120 Mobile Safari/537.36', 'Accept': '*/*', 'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2', 'Origin': 'https://wp.m.163.com', 'Connection': 'keep-alive', 'Referer': 'https://wp.m.163.com/', 'Sec-Fetch-Dest': 'empty', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'same-site', 'TE': 'trailers', } params = ( ('t', '326632088930'), ) response = requests.get('https://c.m.163.com/ug/api/wuhan/app/data/list-total', headers=headers, params=params) #NB. Original query string below. It seems impossible to parse and #reproduce query strings 100% accurately so the one below is given #in case the reproduced version is not "correct". # response = requests.get('https://c.m.163.com/ug/api/wuhan/app/data/list-total?t=326632088930', headers=headers) rj = response.json() rj.keys() data = rj['data'] data.keys() areaTree = data['areaTree'] countryCode = [ x['id'] for x in areaTree] countryName = [ x['name'] for x in areaTree] dct_country_id = dict(zip(countryName, countryCode)) dct_country_id['美国']
这里的代码,params,里面只有一个t, 这个t刚开始我以为是时间,但是也不知道这个是怎么构造的。反正就用这个,后面请求历史数据的时候,这个t也不需要改,没啥影响。
返回json格式的,我就依次提取 json数据里的 data→areaTree→各国的id
做成一个字典,这样通过字典就可以查询“美国”返回7,中国是0.
然后点击“世界疫情”
出现,各个国家的数据。
美国后面有“详情”,点击一下,看看这个请求时什么结构,
第二个请求,他的数据就是美国的数据,
我们看请求头。
数据最后一行是今天的美国人数。
这个请求头,是这个url
https://c.m.163.com/ug/api/wuhan/app/data/list-by-area-code?areaCode=7&t=1633273396571
直接复制这个网址,到浏览器,可以看出,它就能返回给我们美国的数据。
所以规律就是,替换掉 areaCode的数字,我们分别用几个国家的id,替换,轮番请求。就可以得到一个世界各国的疫情历史数据。
need_countries = ['中国', '美国', '英国', '伊朗', '西班牙', '韩国', '德国', '意大利', '印度'] need_countries dct_allData = {} for country in need_countries: country_id = dct_country_id[country] print(country, "*"*20, country_id) url = f"https://c.m.163.com/ug/api/wuhan/app/data/list-by-area-code?areaCode={country_id}&t=1633160447810" print(url) try: response = requests.get(url, headers = headers) time.sleep(3) rj = response.json() dct_allData[country] = rj['data'] print("success") except: print("failed") country_id url dct_allData dct_allData.keys()
这样就得到了9个国家的数据了。
比如,美国的,都在字典 allData里
usa = dct_allData['美国'] usa['list'] list = usa['list'] len(list)
先保存一下数据。
pd.to_pickle(dct_allData, os.path.join(data_dir, "allData疫情数据"))
后面在操作这个数据就可以了。
不需要爬虫了。
这里我们只需要两个数据就可以了。
就是
date和confirm
其他都不需要。
dct_confirm = {} for c in dct_allData.keys(): confirm = [ x['total']['confirm'] for x in dct_allData[c]['list'] ] dct_confirm[c] = confirm dct_confirm.keys() len(dct_confirm['美国']) len(dct_confirm['印度'])
每一个国家的数据,都可以做成一个dataframe
china_list = china['list'] china_date = [ x['date'] for x in china_list] china_confirm = [ x['total']['confirm'] for x in china_list] df_china = pd.DataFrame({ 'date':china_date, 'confirm':china_confirm }) df_china
这里要注意的是,不同国家,有的时间没有数据。date不是同样的。数据也不等长。
f_china.shape usa_list = usa['list'] usa_date = [ x['date'] for x in usa_list] usa_confirm = [ x['total']['confirm'] for x in usa_list] df_usa = pd.DataFrame({ 'date':usa_date, 'confirm':usa_confirm }) df_usa.shape
可以看出,中国有604个date有数据,美国只有589个。
这样在合并成一个大表的时候,就需要注意日期,有的是缺失值。
def get_data(key): len_key = len(df[key]['list']) print(len_key) data = [] date = [] for i in range(len_key): d = df[key]['list'][i]['total']['confirm'] data.append(d) dt = df[key]['list'][i]['date'] date.append(dt) return dict(zip(date, data)) dct_data = {} for key in df.keys(): dct_data[key] = get_data(key) dct_data.keys() pd.DataFrame(dct_data)
这里我们定义一个提取date和confirm的两个数据的函数,对每个国家执行这个函数,得到dct_data是一个大的字典。
直接用pandas生成这一个字典。
就可以得到一个大表。
pandas还是很智能,会自动按照各个国家的date排序,把没有数值的弄成NAN,只保留一个date作为index
df_test = pd.DataFrame(dct_data) df_test.shape df_test.index
df_test2 = df_test.sort_index(ascending=True) df_test2 df_test2.keys() df_test2.columns = ['china', 'usa','uk', 'iran', 'spain', 'korea', 'germey', 'italian', 'india'] df_test2
把index按照时间顺序排序,把国家名字改成英文。