摘要:
受2019-nCoV的影响,一场没有硝烟的疫情防御阻击战已经打响。在全国人民众志成城的努力下,疫情情况在逐步趋于稳定,但我们仍然不能掉以轻心。
疫情没开始爆发的时候,我就每天关注疫情情况,特别是全国疫情地图。之后,就一直想着拿到数据自己做一个,但是没有坚持做这个事,前几天用Python爬了一下成绩查询网站,顺着下去,把这个需求给做出来。
话不多说,先上图吧:
嫌动图不过瘾的话,图表均上传服务器,可在线预览:
①:中国疫情地图 地址: 中国疫情地图
②:中国各省疫情数据展示 地址: 各省疫情数据展示
③:中国各省(直辖市、自治区)各市(区)数据展示 湖北省各市数据展示: 湖北省各市数据展示
其余各省直接访问:(http://39.96.52.136:8088/中国各省情况/xx省各市(区)情况.html)【直辖市、自治区为全称】
数据来源分析:
数据来源于 丁香医生:https://ncov.dxy.cn/ncovh5/view/pneumonia
丁香医生数据见下图:
看到这,可能会想,这数据应该直接放tr,td或者ul,li里的啊,直那接发送请求,获取页面DOM中的文本就行了
最开始我也这样想的,看完网页源代码之后,才发现并不是-_-||
实际上,中国各省数据都存储在id为getAreaStat的script标签中,然后动态渲染到view上。
所以我们要做的就是抓取id为getAreaStat的script标签中的文本内容
数据整理:
很容易看出,script标签中的数据是以json形式存储的,我们把json串进行验证、格式化,整理好里面的数据。
左边密密麻麻的数据经过格式化之后,就很直观看到json串内部的存储情况,大致如下:整个json串中,每个省是一个dict,每个省里面的cities是一个子list存储该省各市数据。
代码部分
代码中要使用的第三方库如下:
- requests 发送http请求,处理url资源
- pyquery 提取页面dom中数据 (或者:Beautiful Soup4)
- pandas 将数据生成csv表格
- pyecharts 绘制图表
一、抓取全国各省疫情信息,生成csv文件 基础
1.代码分析:
2.源码:
import requests
from pyquery import PyQuery as pq
import json
import pandas as pd
import time
url="https://ncov.dxy.cn/ncovh5/view/pneumonia"
response=requests.get(url)
if response.status_code==200:
response.encoding="utf-8"
dom=pq(response.content)
data=dom("script#getAreaStat").text().split(" = ")[1].split("}catch")[0]
jsonobj=json.loads(data) #json对象
print("数据抓取成功...")
province_data=[]
for item in jsonobj:
dic={}
dic["省全称"]=item["provinceName"]
dic["省简称"]=item["provinceShortName"]
dic["现存确诊人数"]=item["currentConfirmedCount"]
dic["累计确诊人数"]=item["confirmedCount"]
dic["疑似人数"]=item["suspectedCount"]
dic["治愈人数"]=item["curedCount"]
dic["死亡人数"]=item["deadCount"]
province_data.append(dic)
if(province_data.__len__()>0):
print("写入数据...")
try:
df=pd.DataFrame(province_data)
time_format=time.strftime("%Y-%m-%d_%H_%M_%S", time.localtime())
df.to_csv(time_format+"全国各省疫情数据.csv",encoding="gbk",index=False)
print("写入成功...")
except:
print("写入失败....")
3.运行效果:
二、利用pyecharts绘制中国疫情地图 进阶
说到绘制表格,最先想到的就是Apache开源的echarts框架,效果好、功能强大。因为对Matplotlib库不熟悉,本想拿到数据后,用echarts框架前端自己画一个,然后了解到有专门的pyecharts,所以很nice!
建议不了解echarts或者是pyecharts的同学,一定要先阅读官方API,了解基本图表类型和各种参数,要不写起来一段链式操作里面各种各样的参数,会有点懵o((⊙﹏⊙))o!
1.代码分析:
2.源码:
from pyecharts import options as opts
from pyecharts.charts import Map
import requests
from pyquery import PyQuery as pq
import json
import time
def map_visualmap() -> Map:
c = (
Map(init_opts=opts.InitOpts(page_title="中国疫情地图"))
.add("现存确诊人数",data_pair=current_data_dic.items(),maptype="china")
.set_global_opts(
title_opts=opts.TitleOpts(title="中国疫情地图",subtitle="数据更新于"+time_format),
visualmap_opts=opts.VisualMapOpts(pieces=[
{"value":0,"label":"无","color":"#9AFF9A"},
{"min": 1, "max": 9, "label": "1~9","color":"#FFCCCC"},
{"min": 10, "max": 99, "label": "10~99","color":"#DB5A6B"},
{"min": 100, "max": 499, "label": "100~499","color":"#FF6666"},
{"min": 500, "max": 999, "label": "500~999","color":"#CC2929"},
{"min": 1000, "max": 9999, "label": "1000~9999","color":"#8C0D0D"},
{"min": 10000, "label": ">10000","color":"#9d2933"}
], is_piecewise=True),
)
)
return c
if __name__ == '__main__':
url = "https://ncov.dxy.cn/ncovh5/view/pneumonia"
response = requests.get(url)
if response.status_code == 200:
response.encoding = "utf-8"
dom = pq(response.content)
data = dom("script#getAreaStat").text().split(" = ")[1].split("}catch")[0]
jsonobj = json.loads(data) # json对象
print("数据抓取成功...")
current_data_dic = {}
time_format = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
for item in jsonobj:
current_data_dic[item["provinceShortName"]] = item["currentConfirmedCount"]
print(current_data_dic)
map_visualmap().render("疫情地图.html")
3.运行效果:
三、 抓取全国各省市区疫情数据并进行数据可视化 扩展
我们以上都只使用了各个省的数据,而最开始分析了,每个省的dict中还包含该省个市(区)的数据,我们不能把这些数据浪费了,爬取到了就要把它们好好利用起来,所以我们把全国各省市区所有疫情数据进行分类可视化。
这里要说的是:我们对每个省(直辖市)下面市(区)疫情数据进行可视化时也可以用pyecharts中的Map,但是为了更加熟悉pyecharts我们这里换一种表格类型 Pie 饼图。
看起来很麻烦,请求各个省还要包括市的数据,最后还要绘图,太麻烦了吧,实则不然(*^▽^*) 短短30行代码即可
1.代码分析
2.源码
import requests
import json
from pyecharts.charts import Pie
import pyecharts.options as opts
import time
from pyquery import PyQuery as pq
def create_Pie(provinceName,dic_citys) -> Pie:
c = (
Pie(init_opts=opts.InitOpts(width="100%",height="800px",page_title=provinceName+"各市(区)情况"))
.add("",data_pair=dic_citys.items(),center=["50%", "58%"],)
.set_global_opts(title_opts=opts.TitleOpts(title=provinceName+"各市(区)情况",subtitle="数据更新于:"+timeformat))
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
)
c.render("./中国各省情况/"+provinceName+"各市(区)情况.html")
if __name__ == '__main__':
url="https://ncov.dxy.cn/ncovh5/view/pneumonia"
timeformat = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
response=requests.get(url)
response.encoding="utf-8"
if response.status_code==200:
print("数据抓取成功!")
dom=pq(response.text)
jsonobj=json.loads(dom("script#getAreaStat").text().split(" = ")[1].split("}catch")[0])
for province in jsonobj:
dic_city={}
for city in province["cities"]:
dic_city[city["cityName"]]=city["currentConfirmedCount"]
if dic_city.__len__()>0:
create_Pie(province["provinceName"],dic_city)
print(province["provinceName"]+"各市数据汇总完毕!")
3.运行效果:
短短1.1s我们就爬取到了全国所有省市的疫情数据、整理并且生成数据图表
随机打开一个饼图查看效果:
总结
至此,我们就完成了全国各省市疫情实时数据的抓取和处理,同时绘制了中国疫情地图。在此之上,我们又进一步扩展, 对中国省、自治区、直辖市的疫情数据进行了批量归整和可视化。在这期间温习了requests库、pandas、pyquery库等,同时也认识和学习了强大的图表绘制pyecharts库,可谓收获颇深!故在此分享共同了解和学习!
最后,武汉加油,中国加油!疫情终会过去,春天必会到来!
希望下次再运行这段代码时,看到的疫情地图会是这样的: