Python實戰:抓肺炎疫情實時資料,畫2019-nCoV疫情地圖
1. 前言
今天,群裡白堊老師問如何用python畫武漢肺炎疫情地圖。白堊老師是研究海洋生態與地球生物的學者,國家重點實驗室成員,於不惑之年學習python,實為我等學習楷模。先前我並沒有關注武漢肺炎的具體資料,也沒有畫過類似的資料分佈圖。於是就拿了兩個小時,專門研究了一下,遂成此文。
2. 資料下載
網上一搜,首先搜到的是騰訊的疫情實時追蹤,那就用這個資料來源吧。
有了網址怎麼抓資料呢?這裡,我送大家一雙火眼金睛,可以從紛亂中找到最靠譜的下載方式。我習慣用FireFox瀏覽器,下面的講解就以FireFox為例(其他瀏覽器基本類似)。
- 開啟選單,點選“Web開發者”,在遞進選單中選擇"網路":
- 重新整理頁面,我們很快就能發現,應答型別為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))
301
>>> print(data[0])
{'country': '中國', 'area': '湖北', 'city': '武漢', 'confirm': 698, 'suspect': 0, 'dead': 63, 'heal': 42}
>>> print(data[-1])
{'country': '中國', 'area': '山東', 'city': '棗莊', 'confirm': 2, 'suspect': 0, 'dead': 0, 'heal': 0}
只要兩行程式碼,就可以抓到資料了。怎麼樣,是不是超級簡單?
3. 資料處理
以省為單位畫疫情圖,我們只需要統計同屬一個省的所有地市的確診資料即可。最終的資料抓取程式碼如下:
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
4. 資料視覺化
資料視覺化,我習慣使用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()
2019-nCoV疫情曲線:
2019-nCoV疫情地圖:
上圖為圓柱投影,這也是basemap預設的投影模式,我們還可以換用其他投影模式,比如蘭勃託等角投影,只需要將97行程式碼改為:
m = Basemap(projection='lcc', width=5000000, height=5000000, lat_0=36, lon_0=102, resolution='l', ax=axes)
蘭勃託投影效果如下:
還可以使用正射投影:
m = Basemap(projection='ortho', lat_0=30, lon_0=105, resolution='l', ax=axes)
正射投影效果如下:
既然都讀到這裡了,就給我——168號博主天元浪子投上5票吧,謝謝!
相關文章
- 利用Python爬取新冠肺炎疫情實時資料,Pyecharts畫2019-nCoV疫情地圖PythonEcharts地圖
- 【實戰】通過Python實現疫情地圖視覺化Python地圖視覺化
- 武漢肺炎疫情地圖(Vue版)地圖Vue
- 用Python爬取新型冠狀病毒肺炎實時資料,pyecharts v1.x繪製省市區疫情地圖PythonEcharts地圖
- 抗擊疫情實時地圖怎麼做?哪個地圖可以看疫情風控?地圖
- 上海疫情實時動態地圖製作,疫情風控區域地圖”助力精準防疫!地圖
- Python 繪製全球疫情地圖Python地圖
- 小區確診病例實時地圖,怎麼繪製疫情視覺化地圖?地圖視覺化
- 實時防疫地圖怎麼用?怎麼查詢離我最近的疫情病例?地圖
- Python:爬取疫情每日資料Python
- 基於 HTML + WebGL 結合 23D 的疫情地圖實時大屏 PC 版HTMLWeb3D地圖
- 防控新型肺炎疫情,不能太硬核!
- 新冠確診病例軌跡地圖怎麼畫?小區疫情分佈地圖製作!地圖
- 全球疫情實時監控——約翰斯·霍普金斯大學資料大屏實現方案
- 後疫情時代,EIoT助力實體零售ESG戰略落地
- 100行程式碼實現疫情地圖視覺化,原理是什麼?行程地圖視覺化
- 伏影實驗室提醒您謹慎開啟疫情地圖郵件地圖
- 戰疫情——flutter AppFlutterAPP
- Python疫情資料分析,並做資料視覺化展示Python視覺化
- selenium實現疫情簽到
- Python | 資料分析實戰ⅠPython
- Python | 資料分析實戰 ⅡPython
- Flutter - 疫情實況,加油武漢Flutter
- 實現地圖實時定位,拯救“路痴”地圖
- 面對肺炎疫情小貼士-IT奶爸帶娃記
- 2020-3-3.新型肺炎疫情國際形勢分析
- ESCAP:亞太地區如何在後疫情時代實現可持續發展報告
- 【python】爬取疫情資料並進行視覺化Python視覺化
- 後疫情時代中國民航業資料解讀
- 疫情預測、學者資料、學術成果、政策地圖,清華大學AMiner團隊上線一系列疫情相關AI大資料產品地圖AI大資料
- 實時獲取股票資料,免費!——Python爬蟲Sina Stock實戰Python爬蟲
- JavaCV的攝像頭實戰之四:抓圖Java
- Python【爬蟲實戰】提取資料Python爬蟲
- 新冠肺炎疫情後中外合資企業:何去何從?(附下載)
- Python爬蟲實戰:爐石傳說卡牌、原畫資料抓取Python爬蟲
- 疫情期間建立的新型夥伴關係在疫情消退後將為長期戰略(附原資料表)
- 關於2020年個人專案【臻美_疫情實時大資料包告】(專案開源)大資料
- 【COVID-19中國疫情地圖】專案詳細介紹地圖