项目已经上传到github 和 百度网盘 欢迎大家自取
链接https://lixiang007.top/
百度网盘地址:
链接:https://pan.baidu.com/s/1I-qvUn3SIDyLiVEa5q9KxQ
提取码:xaup
项目代码位置:
1.数据下载
首先找到数据源。
https://news.qq.com/zt2020/page/feiyan.htm?from=timeline&isappinstalled=0
有了网址怎么抓数据呢?这里以firefox为例(其他浏览器基本类似)。
刷新页面,我们很快就能发现,应答类型为json格式的这个请求,最有可能包含我们需要的数据了:
深入分析,我们就得到了url地址、请求方法、参数、应答格式等信息。查询参数中,callback是回调函数名,我们可以尝试置空,_应该是以毫秒为单位的当前时间戳。有了这些信息,分分钟就可以抓到数据了。我们先在IDLE中以交互方式抓一下看看效果:
import time, json, requests
url = 'https://view.inews.qq.com/g2/getOnsInfo?name=wuwei_ww_area_counts&callback=&_=%d'%int(time.time()*1000)
data = json.loads(requests.get(url=url).json()['data'])
print(len(data))
print(data[0])
print(data[-1])
只要两行代码,就可以抓到数据了。
2.数据处理
以省为单位画疫情图,我们只需要统计同属一个省的所有地市的确诊数据即可。最终的数据抓取代码如下:
import time, json, requests
def catch_distribution():
"""抓取行政区域确诊分布数据"""
data = dict()
url = 'https://view.inews.qq.com/g2/getOnsInfo?name=wuwei_ww_area_counts&callback=&_=%d'%int(time.time()*1000)
for item in json.loads(requests.get(url=url).json()['data']):
if item['area'] not in data:
data.update({item['area']:0})
data[item['area']] += int(item['confirm'])
return data
3.数据可视化
首先先做一些准备
需要pyproj-1.9.5.1-cp36-cp36m-win_amd64
basemap-1.2.1-cp36-cp36m-win_amd64
已经上传到我csdn的资源 windows用户需要自取 需要1积分哦 嘻嘻嘻
C:\Windows\system32>cd C:\Users\88304\Desktop
C:\Users\88304\Desktop>pip install pyproj-1.9.5.1-cp36-cp36m-win_amd64.whl
Processing c:\users\88304\desktop\pyproj-1.9.5.1-cp36-cp36m-win_amd64.whl
Installing collected packages: pyproj
Successfully installed pyproj-1.9.5.1
C:\Users\88304\Desktop>pip install basemap-1.2.1-cp36-cp36m-win_amd64.whl
Processing c:\users\88304\desktop\basemap-1.2.1-cp36-cp36m-win_amd64.whl
Collecting pyshp>=1.2.0
Using cached pyshp-2.1.0.tar.gz (215 kB)
Requirement already satisfied: six in c:\program files\python36\lib\site-packages (from basemap==1.2.1) (1.13.0)
Requirement already satisfied: pyproj>=1.9.3 in c:\program files\python36\lib\site-packages (from basemap==1.2.1) (1.9.5.1)
Requirement already satisfied: matplotlib!=3.0.1,>=1.0.0 in c:\program files\python36\lib\site-packages (from basemap==1.2.1) (3.1.2)
Requirement already satisfied: numpy>=1.2.1 in c:\program files\python36\lib\site-packages (from basemap==1.2.1) (1.17.4)
Requirement already satisfied: python-dateutil>=2.1 in c:\program files\python36\lib\site-packages (from matplotlib!=3.0.1,>=1.0.0->basemap==1.2.1) (2.8.1)
Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in c:\program files\python36\lib\site-packages (from matplotlib!=3.0.1,>=1.0.0->basemap==1.2.1) (2.4.5)
Requirement already satisfied: kiwisolver>=1.0.1 in c:\program files\python36\lib\site-packages (from matplotlib!=3.0.1,>=1.0.0->basemap==1.2.1) (1.1.0)
Requirement already satisfied: cycler>=0.10 in c:\program files\python36\lib\site-packages (from matplotlib!=3.0.1,>=1.0.0->basemap==1.2.1) (0.10.0)
Requirement already satisfied: setuptools in c:\program files\python36\lib\site-packages (from kiwisolver>=1.0.1->matplotlib!=3.0.1,>=1.0.0->basemap==1.2.1) (42.0.2)
Building wheels for collected packages: pyshp
Building wheel for pyshp (setup.py) ... done
Created wheel for pyshp: filename=pyshp-2.1.0-py3-none-any.whl size=32613 sha256=a96678bf30c567522cbe27504cae084c3148332669b7ad222dac4eeaa690fb25
Stored in directory: c:\users\88304\appdata\local\pip\cache\wheels\1b\ab\b5\333342ac6838b5ab6977d3b5d29140cf3e60b01b220f8178c0
Successfully built pyshp
Installing collected packages: pyshp, basemap
Successfully installed basemap-1.2.1 pyshp-2.1.0
数据可视化,我习惯使用matplotlib模块。matplotlib有很多扩展工具包(toolkits),比如,画3D需要mplot3d工具包,画地图的话,则需要basemap工具包,以及处理地图投影的pyproj模块。另外画海陆分界线、国界线、行政分界线等还需要shape数据。所需模块请自行安装,shape文件可以从这里下载,绘图用到的矢量字库可以从自己的电脑上随便找一个(我用的是simsun.ttf)。我的主程序是2019nCoV.py,shape文件下载下来之后,是这样保存的:
文件夹结构如下:
以下为全部代码,除了疫情地图,还包括了全国每日武汉肺炎确诊数据的下载和可视化。
# -*- coding: utf-8 -*-
import time
import json
import requests
from datetime import datetime
import numpy as np
import matplotlib
import matplotlib.figure
from matplotlib.font_manager import FontProperties
from matplotlib.backends.backend_agg import FigureCanvasAgg
from matplotlib.patches import Polygon
from matplotlib.collections import PatchCollection
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
plt.rcParams['font.sans-serif'] = ['FangSong'] # 设置默认字体
plt.rcParams['axes.unicode_minus'] = False # 解决保存图像时'-'显示为方块的问题
def catch_daily():
"""抓取每日确诊和死亡数据"""
url = 'https://view.inews.qq.com/g2/getOnsInfo?name=wuwei_ww_cn_day_counts&callback=&_=%d'%int(time.time()*1000)
data = json.loads(requests.get(url=url).json()['data'])
data.sort(key=lambda x:x['date'])
date_list = list() # 日期
confirm_list = list() # 确诊
suspect_list = list() # 疑似
dead_list = list() # 死亡
heal_list = list() # 治愈
for item in data:
month, day = item['date'].split('.')
date_list.append(datetime.strptime('2020-%s-%s'%(month, day), '%Y-%m-%d'))
confirm_list.append(int(item['confirm']))
suspect_list.append(int(item['suspect']))
dead_list.append(int(item['dead']))
heal_list.append(int(item['heal']))
return date_list, confirm_list, suspect_list, dead_list, heal_list
def catch_distribution():
"""抓取行政区域确诊分布数据"""
data = {'西藏':0}
url = 'https://view.inews.qq.com/g2/getOnsInfo?name=wuwei_ww_area_counts&callback=&_=%d'%int(time.time()*1000)
for item in json.loads(requests.get(url=url).json()['data']):
if item['area'] not in data:
data.update({item['area']:0})
data[item['area']] += int(item['confirm'])
return data
def plot_daily():
"""绘制每日确诊和死亡数据"""
date_list, confirm_list, suspect_list, dead_list, heal_list = catch_daily() # 获取数据
plt.figure('2019-nCoV疫情统计图表', facecolor='#f4f4f4', figsize=(10, 8))
plt.title('2019-nCoV疫情曲线', fontsize=20)
plt.plot(date_list, confirm_list, label='确诊')
plt.plot(date_list, suspect_list, label='疑似')
plt.plot(date_list, dead_list, label='死亡')
plt.plot(date_list, heal_list, label='治愈')
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%m-%d')) # 格式化时间轴标注
plt.gcf().autofmt_xdate() # 优化标注(自动倾斜)
plt.grid(linestyle=':') # 显示网格
plt.legend(loc='best') # 显示图例
plt.savefig('2019-nCoV疫情曲线.png') # 保存为文件
#plt.show()
def plot_distribution():
"""绘制行政区域确诊分布数据"""
data = catch_distribution()
font = FontProperties(fname='res/simsun.ttf', size=14)
lat_min = 0
lat_max = 60
lon_min = 70
lon_max = 140
handles = [
matplotlib.patches.Patch(color='#ffaa85', alpha=1, linewidth=0),
matplotlib.patches.Patch(color='#ff7b69', alpha=1, linewidth=0),
matplotlib.patches.Patch(color='#bf2121', alpha=1, linewidth=0),
matplotlib.patches.Patch(color='#7f1818', alpha=1, linewidth=0),
]
labels = [ '1-9人', '10-99人', '100-999人', '>1000人']
fig = matplotlib.figure.Figure()
fig.set_size_inches(10, 8) # 设置绘图板尺寸
axes = fig.add_axes((0.1, 0.12, 0.8, 0.8)) # rect = l,b,w,h
m = Basemap(llcrnrlon=lon_min, urcrnrlon=lon_max, llcrnrlat=lat_min, urcrnrlat=lat_max, resolution='l', ax=axes)
m.readshapefile('res/china-shapefiles-master/china', 'province', drawbounds=True)
m.readshapefile('res/china-shapefiles-master/china_nine_dotted_line', 'section', drawbounds=True)
m.drawcoastlines(color='black') # 洲际线
m.drawcountries(color='black') # 国界线
m.drawparallels(np.arange(lat_min,lat_max,10), labels=[1,0,0,0]) #画经度线
m.drawmeridians(np.arange(lon_min,lon_max,10), labels=[0,0,0,1]) #画纬度线
for info, shape in zip(m.province_info, m.province):
pname = info['OWNER'].strip('\x00')
fcname = info['FCNAME'].strip('\x00')
if pname != fcname: # 不绘制海岛
continue
for key in data.keys():
if key in pname:
if data[key] == 0:
color = '#f0f0f0'
elif data[key] < 10:
color = '#ffaa85'
elif data[key] <100:
color = '#ff7b69'
elif data[key] < 1000:
color = '#bf2121'
else:
color = '#7f1818'
break
poly = Polygon(shape, facecolor=color, edgecolor=color)
axes.add_patch(poly)
axes.legend(handles, labels, bbox_to_anchor=(0.5, -0.11), loc='lower center', ncol=4, prop=font)
axes.set_title("2019-nCoV疫情地图", fontproperties=font)
FigureCanvasAgg(fig)
fig.savefig('2019-nCoV疫情地图.png')
if __name__ == '__main__':
plot_daily()
plot_distribution()
运行结果
"C:\Program Files\Python36\pythonw.exe" C:/Users/88304/Desktop/lixiang/2019nCoV_lx.py
进程已结束,退出代码0
还可以使用正射投影:
m = Basemap(projection=‘ortho’, lat_0=30, lon_0=105, resolution=‘l’, ax=axes)
效果如下哈:
"C:\Program Files\Python36\pythonw.exe" C:/Users/88304/Desktop/lixiang/2019nCoV_lx.py
Warning: Cannot label parallels on Orthographic basemap'Warning: Cannot label meridians on full-disk
Geostationary, Orthographic or Azimuthal equidistant basemap
进程已结束,退出代码0
这样没关系的