一、前言
最近在家隔离,每天起床第一件事就是看看各地情况,好在目前情况有了些许好转。天佑武汉!天佑种花家! 偶然间在技术贴看到一数据入口,点开一看,如获至宝,爬之分析之!
数据以json的模样展现在我们面前,各省入口是省名称。(因为一些原因不能在博客上贴出数据,可视化上也将数据屏蔽,毕竟实现方法是最重要的,见谅!) url = "https://lab.isaaclin.cn/nCoV/api/area?latest=0&province={0}".format(province)想要获取全国的数据只要遍历省份进行请求解析就好了。各省的数据我只截取到1月24号(除夕)。 现在开始请求
(资料图片仅供参考)
二、爬虫
1. 请求
def spider_virus(url): headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36" } html = requests.get(url=url,headers=headers) html.encoding = "utf-8" html.raise_for_status()
只要挂个UA就能请求通~ 推荐给大伙一个UA包,很好用,不用每次都去粘UA,省了很多事
from fake_useragent import UserAgent
只要"User-Agent": UserAgent().random,就可以了,方便得很。
2. Json解析
解析json这里就很简单了
# 省级 provinceName = results["provinceName"] provinceShortName = results["provinceShortName"]+"全部统计" confirmedCount = results["confirmedCount"] suspectedCount = results["suspectedCount"] curedCount = results["curedCount"] deadCount = results["deadCount"] # locationId = results["locationId"] # 13位时间戳转换 updateTimenum = results["updateTime"] timeStamp = float(int(updateTimenum) / 1000) timeArray = time.localtime(timeStamp) # otherStyleTime = time.strftime("%Y-%m-%d %H:%M:%S", timeArray) updateTime = time.strftime("%Y-%m-%d %H:%M:%S", timeArray) province_list.append((provinceName, provinceShortName, confirmedCount, suspectedCount, curedCount, deadCount,updateTime))
# 市级 try: cities = results["cities"] for city_data in cities: # print(city_data) cityName = city_data["cityName"] confirmedCount = city_data["confirmedCount"] # 确诊人数 suspectedCount = city_data["suspectedCount"] # 疑似感染人数 curedCount = city_data["curedCount"] # 治愈人数 deadCount = city_data["deadCount"] # 死亡人数 # locationId = city_data["locationId"] province_list.append((provinceName, cityName, confirmedCount, suspectedCount, curedCount, deadCount, updateTime)) except Exception as e : cities = "未知" cityName = "未知" confirmedCount = 0000 suspectedCount = 0000 curedCount = 0000 deadCount = 0000 province_list.append((provinceName, cityName, confirmedCount, suspectedCount, curedCount, deadCount, updateTime)) To_MySQL("Virus", province_list)
3. 数据存储(Mysql)
最后的数据我存到了mysql里,建表也是在python里写好的,就不贴了
def Insert_Data(datas_into, table_name): try: # print(datas_into) db = pymysql.connect(host="手动打码", user="root", password="*******", db="liu*手动打码", charset="utf8") cursor = db.cursor() # for data_tups in list(datas_into): sql_insert = """insert into {0} (Province,city,confirmedCount,suspectedCount,curedCount,deadCount,updataTime) values (%s, %s, %s, %s, %s, %s, %s);""".format(table_name) cursor.executemany(sql_insert, datas_into) db.commit() except Exception as e: db.rollback() print(e) finally: cursor.close() db.close()
因为采集下来的数据有各省总人数及其地级市、区等,所以在city这一列总体水平我用了“全部的统计”,以便区分。
截止目前只有40000多条数据,时间设的2秒,没写多进程,就是单机这样跑,毕竟自己用嘛~
三、可视化与分析
我使用的是Jupyter notebook
1. 数据处理
import time,pymysqlimport pandas as pdimport numpy as npfrom pyecharts.charts import Pie, Bar, Map, WordCloud,Line,Gridfrom pyecharts import options as optsfrom pyecharts.globals import SymbolTypefrom pyecharts.globals import ThemeType
db = pymysql.connect(host="*****", user="root", password="*****", db="liu*****", charset="utf8")df_all = pd.read_sql("SELECT * FROM virus", con=db)df_all = pd.read_sql("SELECT * FROM virus", con=db)db.close()df_all.to_excel("原始数据.xls")
修改了中文列名,方便识别,但是实际开发中并不推荐
df_all.columns = ["id","省份","城市","确诊人数","疑似感染人数","治愈人数","死亡人数","更新时间"]df_all.isnull().sum()df_all.info()df_all["更新时间"] = pd.to_datetime(df_all["更新时间"])df_all.head()
修改日期格式,增加了周几一列
df_all["更新日期"] = pd.to_datetime(df_all["更新时间"].map(str).str[0:10], format ="%Y-%m-%d")df_all["更新日期"]=df_all["更新日期"].dt.strftime("%m-%d")df_all["周几"]=df_all["更新时间"].dt.dayofweek+1
提取各省总体数据
df_ProAll = pd.DataFrame(columns=["id","省份","城市","确诊人数","疑似感染人数", "治愈人数","死亡人数","更新时间","更新日期","周几"])for province in province_list: df_pro=df_pro_all.loc[df_pro_all["省份"]==province,:] #提取相同日期第一条 df_pro=df_pro.drop_duplicates(subset=["更新日期"],keep="first") df_ProAll = pd.concat([df_ProAll,df_pro],ignore_index=False,axis=0)col=["id","省份","城市","确诊人数","疑似感染人数","治愈人数","死亡人数","更新时间","更新日期","周几"]df_ProAll=df_ProAll[col]#修改类型df_ProAll[["确诊人数","疑似感染人数","治愈人数","死亡人数"]]=df_ProAll[["确诊人数","疑似感染人数","治愈人数","死亡人数"]].astype(int)#重置索引df_ProAll.index = range(len(df_ProAll.index))
gp_time=df_ProAll.groupby("更新日期")[["确诊人数","疑似感染人数","治愈人数","死亡人数"]].sum()cols = gp_time.columns.tolist()for col in cols: num_list = gp_time[col].tolist() new_list = [0] for i in range(len(num_list)-1): b= num_list[i+1]-num_list[i] new_list.append(b) gp_time["{}增减".format(col)]=new_listgp_time
2. 可视化
2.1 全国情况
2.1.1) 全国治愈与死亡走势
line = ( Line() .add_xaxis(gp_time.index.tolist()) .add_yaxis("治愈人数", gp_time["治愈人数"].tolist()) .add_yaxis("死亡人数", gp_time["死亡人数"].tolist()) .set_global_opts( title_opts=opts.TitleOpts(title="全国治愈与死亡走势"), tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="cross"), yaxis_opts=opts.AxisOpts(name="人数"), xaxis_opts=opts.AxisOpts(name="时间(日)") ) .set_series_opts(label_opts=opts.LabelOpts(is_show=False)) )line.render_notebook()
2.1.2) 全国确诊、死亡、治愈增幅
line = ( Line() .add_xaxis(gp_time.index.tolist()) .add_yaxis("确诊", gp_time["确诊人数增减"].tolist()) .add_yaxis("治愈", gp_time["治愈人数增减"].tolist()) .add_yaxis("死亡", gp_time["死亡人数增减"].tolist()) .set_global_opts( title_opts=opts.TitleOpts(title="全国确诊、死亡增幅"), tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="cross"), yaxis_opts=opts.AxisOpts(name="人数"), xaxis_opts=opts.AxisOpts(name="时间(日)") ) )line.render_notebook()
2.1.3) 全国确诊走势
2.1.4) 全国top10省份
time_list = [list(z) for z in zip(df_pro_new["省份"].tolist()[:10], df_pro_new["确诊人数"].tolist()[:10])]pie = ( Pie() .add("", time_list).set_global_opts(title_opts=opts.TitleOpts(title="")) .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}")))pie.render_notebook()
2.1.5) 全国确诊/治愈/死亡对比
gp_timeday = gp_time.index.tolist()aaa=gp_time["确诊人数增减"].tolist()bbb=gp_time["治愈人数增减"].tolist()ccc=gp_time["死亡人数增减"].tolist()ddd=gp_time["疑似感染人数增减"].tolist()grid = Grid()bar = Bar()# grid.theme = ThemeType.PURPLE_PASSIONline = Line()bar.add_xaxis(day)bar.add_yaxis("治愈增减",bbb,label_opts=opts.LabelOpts(is_show=False))bar.add_yaxis("死亡增减",ccc,label_opts=opts.LabelOpts(is_show=False))bar.extend_axis(yaxis=opts.AxisOpts(type_="value", name="确诊人数增减", min_=0, max_=16000, position="right", axislabel_opts=opts.LabelOpts(formatter="{value}人"), ))bar.set_global_opts(yaxis_opts=opts.AxisOpts( name="治愈/死亡增减", type_="value", axislabel_opts=opts.LabelOpts(formatter="{value}人") ), # xaxis_opts=opts.AxisOpts(name="日期"),# 太挤不好显示 title_opts=opts.TitleOpts("全国每日确诊/治愈/死亡对比"), tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="cross"), ) # 交叉指向工具line.add_xaxis(day)line.add_yaxis("确诊增减",aaa,yaxis_index = 1,label_opts=opts.LabelOpts(is_show=False))# line.add_yaxis("疑似感染增减",ddd,yaxis_index = 1,label_opts=opts.LabelOpts(is_show=False))# 把line添加到bar上bar.overlap(line)# 这里如果不需要grid也可以,直接设置bar的格式,然后显示bar即可#bar.render_notebook()grid.add(chart = bar,grid_opts = opts.GridOpts(),is_control_axis_index = True)grid.render_notebook()
2.1.6) 除湖北省,各省市情况
gp_pro_time_cop=gp_pro_time.copy().reset_index()df_no_hubei=gp_pro_time_cop.loc[gp_pro_time_cop["省份"]!="湖北省",:]# df_no_hubei["省份"].value_counts()gp_no_hubei=df_no_hubei.groupby("更新日期")[["确诊人数","治愈人数","死亡人数", "确诊人数增减","治愈人数增减","死亡人数增减"]].sum()gp_no_hubei
2.1.7) 全国情况结论
2月1号后治愈水平逐步与离开水平拉大距离。在连续三天下降后,2月13号,确诊病例突然增加15139例,武汉市那天将疑似未确诊病例计入,这是件好事,相关报道也做了说明。top10中北方省份只有两个,河南和山东,也是两个劳务输出大省,其中河南省因为紧邻湖北省,达到914例,人们也更愿意选择离家近的发达地区工作。自2月4号开始各省确诊病例逐渐下降,死亡人数增幅较缓
2.2 天津市情况
数据处理
"""天津市基本情况"""df_tianjin_all=df_all.loc[(df_all["省份"]=="天津市")&(df_all["城市"]!="全部统计"),:]df_tianjin_all.index = range(len(df_tianjin_all.index))df_tianjin_all.head()city_list=[]for city in df_tianjin_all["城市"].tolist(): if city=="外地来津": city="外地来津人员" city_list.append(city) elif city=="待明确": city="待明确地区" city_list.append(city) else: city_list.append(city)df_tianjin_all["城市"]=city_list"""检索天津市现有数据每区每日最后一条数据"""df_tianjin_last=df_tianjin_all.iloc[df_tianjin_all.groupby(["城市", "更新日期"]).apply(lambda x: x["确诊人数"].idxmax())]df_tianjin_last.index = range(len(df_tianjin_last.index))df_tianjin_last.head()"""检索天津市各区最新确诊数据"""gp_tianjin=df_tianjin_last.groupby(["城市","更新日期"])["确诊人数","疑似感染人数", "治愈人数","死亡人数"].sum()df_tj_daynew=gp_tianjin.reset_index()df_tj_daynew=df_tj_daynew.iloc[df_tj_daynew.groupby(["城市"]).apply(lambda x: x["确诊人数"].idxmax())]df_tj_daynew=df_tj_daynew.sort_values(by="确诊人数",ascending=False)df_tj_daynew
首先对数据做了下处理,把外地和待明确归纳
2.2.1) 各区县最新确诊人数
2.2.2) 确诊、治愈、死亡情况
2.2.3) 宝坻区与天津市各区趋势
2.2.4) 天津市情况结论
宝坻区有50病例,占到天津1/3,紧接着是河东区15例天津市市内6区 top占了4位,较为发达的和平、南开也在之内,河东,河北相对其他区,外来人口也相对较多。
以上代码就是对此次疫情的很粗略分析,其实可以分析的地方太多了,也能获得很多别的信息,比如,按各省面积人口算一下致病率,各省确诊连续下滑时长等等,方法其实都是一样,就看分析的思路了。 可视化使用的pyecharts,画出来的图也比较好看。 云玩家第一次发博,见笑~·