数据获取
目前,腾讯的疫情实时追踪 网页能够看到实时的新冠病毒数据,网页的数据展示也非常清晰。但这个网页提供的数据没有每个市的历史数据。其它几个新闻网页的数据也都大同小异。
为了能够得到自己想看的数据,尤其的自己比较关心的数据,我观察了几个网址的数据并且用 Python 进行了获取。下面对数据获取和数据展示的方法进行介绍,供大家参考。
腾讯网页数据源
为了便于对照,建议大家使用 Chrome 浏览器查看,其实每种浏览器都类似,但界面不同,看自己的习惯。用 Chrome 打开 疫情实时追踪 页面,然后按下 F12,Chrome 打开 Developer Tools,再次点击页面刷新按钮,追踪到数据获取的的 Script 如下:
Response 返回的是 applicatio/json
格式的数据(Response Headers: application/json),双击左边的 getOnsInfo**, Chrome 打开一个新的页面,展示最新的病情数据:
我们再看 Query String Parameters 中有两个参数,其中 callback 参数应该是一个基于毫秒级别的时间戳。URL 去掉这个 callback 参数也可以获得最新的感染人数数据。
对这个返回的 json 数据,我们可以另存为一个 json 文件,并对数据的结构进行分析。分析的过程这里就不展开了。在这个网页中能获得如下数据:
- 中国确认的总人数(chinaTotal)
- 新增人数(chinaAdd)
- 每日人数汇总历史数据(chinaDayList)
- 每日新增人数历史数据(chinaDayAddList)
- 每日新增人数历史数据,分湖北、非湖北、全国三个维度 (dailynewAddHistory)
- 每日死亡率历史数据 (dailyDeadRateHistory)
- areaTree: 这个节点下面包全世界数据,中国数据到市级的数据,是最详细的。
通过 Web API 获取
除了腾讯这种新闻页面,我们利用页面的数据源间接获取,也可以利用网上 Web API 进行获取。比如天气 api 就提供了疫情的 API。打开 http://tianqiapi.com/ 网页,我们可以看到页面有一个连接:
点击进入开发者指南页面,对调用的 url 和返回格式有详细说明。允许每天免费调用 3 万次,但需要先注册一个账号。
另外,Github 上也比较活跃,有很多项目利用爬虫,从诸如丁香医生的网站上爬取数据,然后提供数据更新和 Web API 服务。下面的这个项目就挺不错:
项目地址:https://github.com/BlankerL/DXY-COVID-19-Crawler
数据仓库:https://github.com/BlankerL/DXY-COVID-19-Data
这个项目提供的 api 调用示例如下:
https://lab.isaaclin.cn/nCoV/api/overall # 返回全面疫情概况
https://lab.isaaclin.cn/nCoV/api/provinceName # 返回省列表
https://lab.isaaclin.cn/nCoV/api/area?latest=0&province=湖北省 # 返回湖北省历史数据
API 调用请自行阅读 API 调用说明。
数据可视化
我根据自己的目的,使用 pandas 模块,将数据保存到 Excel,通过 pyecharts 模块,将可视化地图保存为 html 文件,代码比较直观,主要的处理过程为对含有多层次的数据进行扁平化,得到一个二维的数据。地图中显示的数据市确认病例的数据。pyecharts 的版本迭代较快,并且 0.5 版和 1.0 版不兼容。我使用的是 1.6 版。
import requests
import json
import pandas as pd
import os
import datetime
from pyecharts import options as opts
from pyecharts.charts import *
cities = []
def get_ncov_data() -> str:
url = 'https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5'
data = requests.get(url).json()['data']
return data
def get_daily_data() -> list:
all = json.loads(get_ncov_data())
return all['chinaDayList']
def flatten_ncov_data() -> list:
all = json.loads(get_ncov_data())
date = all['lastUpdateTime']
# 第一层:国家
china = all['areaTree'][0]['children'] # get China data
# 第二层:省
for province in china:
province_ncov = province['children']
# 第三层:市
for city in province_ncov:
# 输出格式
city_ncov = {
'日期': date,
'省份': province['name'],
'市': city['name'],
'新增确认': city['today']['confirm'],
'新增治愈': city['today']['heal'],
'新增死亡': city['today']['dead'],
'累计确认': city['total']['confirm'],
'累计治愈': city['total']['heal'],
'累计死亡': city['total']['dead']
}
cities.append(city_ncov)
def export_excel():
cities.clear()
flatten_ncov_data()
df = pd.DataFrame(cities)
# 导出Excel
path = os.path.dirname(os.path.abspath(__file__))
output_file = os.path.join(path, 'output.xlsx')
df.to_excel(output_file)
def render_map_chart():
cities.clear()
flatten_ncov_data()
df = pd.DataFrame(cities)
# Render Map chart
map_chart = Map()
map_chart.add(
"中国", # map name
[list(z) for z in zip(list(df["省份"]), list(df['累计确认']))],
"china",
is_map_symbol_show=False
)
map_chart.set_global_opts(
title_opts=opts.TitleOpts(
title="nCoV疫情地图(" + str(datetime.date.today()) + ")"
),
visualmap_opts=opts.VisualMapOpts(
max_=50000,
is_piecewise=True,
pieces=[
{"min": 1, "max": 9, "label": "10人以下", "color": "#FFE6BE"},
{"min": 10, "max": 99, "label": "10-99人", "color": "#FFB769"},
{"min": 100, "max": 499, "label": "100-499人", "color": "#FF8F66"},
{"min": 500, "max": 999, "label": "500-999人", "color": "#ED514E"},
{"min": 1000, "max": 50000, "label": "1000人以上", "color": "#CA0D11"}
]))
map_chart.render('ncov_map_chart_{}.html'.format(datetime.date.today()))
def render_line_chart():
daily_data = get_daily_data()
df = pd.DataFrame(daily_data)
line_chart = Line()
line_chart.add_xaxis(list(df["date"]))
line_chart.add_yaxis("确认", list(df["confirm"]))
line_chart.add_yaxis("疑似", list(df["suspect"]))
line_chart.set_global_opts(
title_opts=opts.TitleOpts(title="nCoV确认病例与疑似病例曲线")
)
line_chart.render('ncov_line_chart-{}.html'.format(datetime.date.today()))
if __name__ == "__main__":
export_excel()
render_map_chart()
render_line_chart()
地图显示的效果如下,与腾讯疫情地图图例的颜色一样。
确认和疑似病例的日趋势曲线如下: