Python爬取新冠肺炎實時數據及其可視化分析

點贊、關注再看,養成良好習慣
Life is short, U need Python
初學Python,快來點我吧
在這裏插入圖片描述


案例:Python爬取新冠肺炎實時數據及其可視化分析

作者:PyQuant
博客:https://blog.csdn.net/qq_33499889
慕課:https://mooc1-2.chaoxing.com/course/207443619.html

本案例適合作爲大數據技術基礎課程中數據爬取、清洗以及可視化部分的配套教學案例。通過本案例,能夠達到以下教學效果:

  • 培養學生爬取網站數據以及數據清洗、加工處理的能力。

    • 案例中通過Python第三方庫request獲取網站實時數據,並利用pandas清洗數據爲可視化數據做準備。
  • 培養學生對真實數據進行可視化分析的能力。

    • 案例中數據來源於網站爬取得到的新冠肺炎實時數據,對新冠肺炎感染者或疑似感染者等數據進行可視化分析。
  • 幫助學生進一步掌握常用圖表的繪製方法。

    • 案例中涉及到折線圖和柱狀圖等。
  • 提高學生動手實踐能力。

    • 案例中使用Python中的常用可視化工具Matplotlib,提高學生繪製常用圖表的實踐能力。


1. 利用Python爬取實時數據

  • 網站:https://news.qq.com/zt2020/page/feiyan.htm

  • 原理:通過Requests獲取Json請求,從而得到全國各省的疫情數據。

1.1 分析網站

  • 通過瀏覽器 “審查元素” 查看源代碼(右鍵單擊網頁地圖選擇‘審查元素’選項)及 “網絡” 反饋的消息,如下圖所示:
    在這裏插入圖片描述
    在這裏插入圖片描述

  • 對應的HTTP信息如下所示:

在這裏插入圖片描述

1.2 發送請求並獲取Json數據

通過分析url地址、請求方法、參數及響應格式,可以獲取Json數據,注意url需要增加一個時間戳。

import time
import json
import requests

url = 'https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5&callback=&_=%d'%int(time.time()*1000)

# 抓取騰訊疫情實時json數據
data = json.loads(requests.get(url=url).json()['data'])

# 數據太多,打印一個鍵值對
print(data['lastUpdateTime'])
2020-03-11 16:46:29

2. 數據處理

2.1 認識數據

type(data),len(data)
(dict, 12)
print(data.keys())
dict_keys(['lastUpdateTime', 'chinaTotal', 'chinaAdd', 'isShowAdd', 'showAddSwitch', 'areaTree', 'chinaDayList', 'chinaDayAddList', 'dailyNewAddHistory', 'dailyHistory', 'wuhanDayList', 'articleList'])
# data['areaTree']
# data['areaTree'][0]
# 統計省份信息
num = data['areaTree'][0]['children']
# print(num)
print(num[0])   # 數據太多,打印部分
{'name': '湖北', 'today': {'confirm': 13, 'confirmCuts': 0, 'isUpdated': True, 'tip': ''}, 'total': {'confirm': 67773, 'suspect': 0, 'dead': 3046, 'deadRate': '4.49', 'showRate': False, 'heal': 49056, 'healRate': '72.38', 'showHeal': True}, 'children': [{'name': '武漢', 'today': {'confirm': 13, 'confirmCuts': 0, 'isUpdated': True}, 'total': {'confirm': 49978, 'suspect': 0, 'dead': 2423, 'deadRate': '4.85', 'showRate': False, 'heal': 33041, 'healRate': '66.11', 'showHeal': True}}, {'name': '孝感', 'today': {'confirm': 0, 'confirmCuts': 0, 'isUpdated': True}, 'total': {'confirm': 3518, 'suspect': 0, 'dead': 126, 'deadRate': '3.58', 'showRate': False, 'heal': 3149, 'healRate': '89.51', 'showHeal': True}}, {'name': '黃岡', 'today': {'confirm': 0, 'confirmCuts': 0, 'isUpdated': True}, 'total': {'confirm': 2907, 'suspect': 0, 'dead': 125, 'deadRate': '4.30', 'showRate': False, 'heal': 2684, 'healRate': '92.33', 'showHeal': True}}, {'name': '荊州', 'today': {'confirm': 0, 'confirmCuts': 0, 'isUpdated': True}, 'total': {'confirm': 1580, 'suspect': 0, 'dead': 49, 'deadRate': '3.10', 'showRate': False, 'heal': 1442, 'healRate': '91.27', 'showHeal': True}}, {'name': '鄂州', 'today': {'confirm': 0, 'confirmCuts': 0, 'isUpdated': True}, 'total': {'confirm': 1394, 'suspect': 0, 'dead': 54, 'deadRate': '3.87', 'showRate': False, 'heal': 1127, 'healRate': '80.85', 'showHeal': True}}, {'name': '隨州', 'today': {'confirm': 0, 'confirmCuts': 0, 'isUpdated': True}, 'total': {'confirm': 1307, 'suspect': 0, 'dead': 44, 'deadRate': '3.37', 'showRate': False, 'heal': 1151, 'healRate': '88.06', 'showHeal': True}}, {'name': '襄陽', 'today': {'confirm': 0, 'confirmCuts': 0, 'isUpdated': True}, 'total': {'confirm': 1175, 'suspect': 0, 'dead': 38, 'deadRate': '3.23', 'showRate': False, 'heal': 1094, 'healRate': '93.11', 'showHeal': True}}, {'name': '黃石', 'today': {'confirm': 0, 'confirmCuts': 0, 'isUpdated': True}, 'total': {'confirm': 1015, 'suspect': 0, 'dead': 38, 'deadRate': '3.74', 'showRate': False, 'heal': 917, 'healRate': '90.34', 'showHeal': True}}, {'name': '宜昌', 'today': {'confirm': 0, 'confirmCuts': 0, 'isUpdated': True}, 'total': {'confirm': 931, 'suspect': 0, 'dead': 35, 'deadRate': '3.76', 'showRate': False, 'heal': 800, 'healRate': '85.93', 'showHeal': True}}, {'name': '荊門', 'today': {'confirm': 0, 'confirmCuts': 0, 'isUpdated': True}, 'total': {'confirm': 928, 'suspect': 0, 'dead': 39, 'deadRate': '4.20', 'showRate': False, 'heal': 817, 'healRate': '88.04', 'showHeal': True}}, {'name': '咸寧', 'today': {'confirm': 0, 'confirmCuts': 0, 'isUpdated': True}, 'total': {'confirm': 836, 'suspect': 0, 'dead': 14, 'deadRate': '1.67', 'showRate': False, 'heal': 812, 'healRate': '97.13', 'showHeal': True}}, {'name': '十堰', 'today': {'confirm': 0, 'confirmCuts': 0, 'isUpdated': True}, 'total': {'confirm': 672, 'suspect': 0, 'dead': 8, 'deadRate': '1.19', 'showRate': False, 'heal': 604, 'healRate': '89.88', 'showHeal': True}}, {'name': '仙桃', 'today': {'confirm': 0, 'confirmCuts': 0, 'isUpdated': True}, 'total': {'confirm': 575, 'suspect': 0, 'dead': 22, 'deadRate': '3.83', 'showRate': False, 'heal': 520, 'healRate': '90.43', 'showHeal': True}}, {'name': '天門', 'today': {'confirm': 0, 'confirmCuts': 0, 'isUpdated': True}, 'total': {'confirm': 496, 'suspect': 0, 'dead': 15, 'deadRate': '3.02', 'showRate': False, 'heal': 473, 'healRate': '95.36', 'showHeal': True}}, {'name': '恩施州', 'today': {'confirm': 0, 'confirmCuts': 0, 'isUpdated': True}, 'total': {'confirm': 252, 'suspect': 0, 'dead': 7, 'deadRate': '2.78', 'showRate': False, 'heal': 235, 'healRate': '93.25', 'showHeal': True}}, {'name': '潛江', 'today': {'confirm': 0, 'confirmCuts': 0, 'isUpdated': True}, 'total': {'confirm': 198, 'suspect': 0, 'dead': 9, 'deadRate': '4.55', 'showRate': False, 'heal': 179, 'healRate': '90.40', 'showHeal': True}}, {'name': '神農架', 'today': {'confirm': 0, 'confirmCuts': 0, 'isUpdated': True}, 'total': {'confirm': 11, 'suspect': 0, 'dead': 0, 'deadRate': '0.00', 'showRate': False, 'heal': 11, 'healRate': '100.00', 'showHeal': True}}]}
hubei = num[0]   # 湖北省
hubei.keys()
dict_keys(['name', 'today', 'total', 'children'])
hubei['total']
{'confirm': 67773,
 'suspect': 0,
 'dead': 3046,
 'deadRate': '4.49',
 'showRate': False,
 'heal': 49056,
 'healRate': '72.38',
 'showHeal': True}
henan = num[2]  # 河南省
henan.keys()
dict_keys(['name', 'today', 'total', 'children'])
henan['total']
{'confirm': 1273,
 'suspect': 0,
 'dead': 22,
 'deadRate': '1.73',
 'showRate': False,
 'heal': 1249,
 'healRate': '98.11',
 'showHeal': True}

2.2 獲取湖北省不同地區疫情確診總數據

# hubei   # 湖北所有數據信息
# hubei['children']   # 湖北不同地區數據
hubei['children'][0]['total']  # 武漢總數據
{'confirm': 49978,
 'suspect': 0,
 'dead': 2423,
 'deadRate': '4.85',
 'showRate': False,
 'heal': 33041,
 'healRate': '66.11',
 'showHeal': True}

其數據包括當日數據(today)和累計數據(total),confirm表示確診、suspect表示疑似、dead表示死亡、heal表示治癒。

# 解析湖北省不同地區確診的總數據
hubei_children_total_data = {}
for item in hubei['children']:
    if item['name'] not in hubei_children_total_data:
        hubei_children_total_data.update({item['name']:0})
    hubei_children_total_data[item['name']] += int(item['total']['confirm']) 
print(hubei_children_total_data)
{'武漢': 49978, '孝感': 3518, '黃岡': 2907, '荊州': 1580, '鄂州': 1394, '隨州': 1307, '襄陽': 1175, '黃石': 1015, '宜昌': 931, '荊門': 928, '咸寧': 836, '十堰': 672, '仙桃': 575, '天門': 496, '恩施州': 252, '潛江': 198, '神農架': 11}

2.3 獲取河南省不同地區疫情確診總數據

# henan   # 河南所有數據信息
# henan['children']   # 河南不同地區分數據
henan['children'][1]['total']  # 鄭州總數據
{'confirm': 158,
 'suspect': 0,
 'dead': 5,
 'deadRate': '3.16',
 'showRate': False,
 'heal': 152,
 'healRate': '96.20',
 'showHeal': True}
# 解析河南省不同地區確診的總數據
henan_children_total_data = {}
for item in henan['children']:
    if item['name'] not in henan_children_total_data:
        henan_children_total_data.update({item['name']:0})
    henan_children_total_data[item['name']] += int(item['total']['confirm']) 
print(henan_children_total_data)
{'信陽': 274, '鄭州': 158, '南陽': 156, '駐馬店': 139, '商丘': 91, '周口': 76, '平頂山': 58, '新鄉': 57, '安陽': 53, '許昌': 39, '漯河': 35, '焦作': 32, '洛陽': 31, '開封': 26, '鶴壁': 19, '濮陽': 17, '三門峽': 7, '濟源示範區': 5, '地區待確認': 0}

2.4 獲取全國各省疫情確診總數據

num[0]['total']   # 湖北省總數據
{'confirm': 67773,
 'suspect': 0,
 'dead': 3046,
 'deadRate': '4.49',
 'showRate': False,
 'heal': 49056,
 'healRate': '72.38',
 'showHeal': True}
# 解析每個省份確診的總人數
total_data = {}
for item in num:
    if item['name'] not in total_data:
        total_data.update({item['name']:0})
    for city_data in item['children']:
        total_data[item['name']] += int(city_data['total']['confirm'])    
print(total_data)
{'湖北': 67773, '廣東': 1353, '河南': 1273, '浙江': 1215, '湖南': 1018, '安徽': 990, '江西': 935, '山東': 760, '江蘇': 631, '重慶': 576, '四川': 539, '黑龍江': 482, '北京': 435, '上海': 344, '河北': 318, '福建': 296, '廣西': 252, '陝西': 245, '雲南': 174, '海南': 168, '貴州': 146, '天津': 136, '山西': 133, '香港': 126, '甘肅': 125, '遼寧': 125, '吉林': 93, '新疆': 76, '內蒙古': 75, '寧夏': 75, '臺灣': 48, '青海': 18, '澳門': 10, '西藏': 1}

3. Matplotlib繪製柱狀圖

3.1 繪製湖北省不同地區確診總數據的柱狀圖

print(hubei_children_total_data)
{'武漢': 49978, '孝感': 3518, '黃岡': 2907, '荊州': 1580, '鄂州': 1394, '隨州': 1307, '襄陽': 1175, '黃石': 1015, '宜昌': 931, '荊門': 928, '咸寧': 836, '十堰': 672, '仙桃': 575, '天門': 496, '恩施州': 252, '潛江': 198, '神農架': 11}
hb_names = hubei_children_total_data.keys()
hb_numbers = hubei_children_total_data.values()
import matplotlib.pyplot as plt 
import numpy as np
plt.rcParams['font.sans-serif'] = ['simhei']   # 用來正常顯示中文標籤

# 繪圖
plt.figure(figsize=[12,8])

plt.bar(hb_names,hb_numbers)

plt.xlabel("地區", size=12)
plt.ylabel("人數", fontproperties='SimHei', rotation=90, size=12)
plt.title("湖北省不同地區疫情確診數對比圖", size=16)
plt.xticks(list(hb_names), rotation=90, size=12)
    
plt.show()

在這裏插入圖片描述

3.2 繪製河南省不同地區確診總數據的柱狀圖

print(henan_children_total_data)
{'信陽': 274, '鄭州': 158, '南陽': 156, '駐馬店': 139, '商丘': 91, '周口': 76, '平頂山': 58, '新鄉': 57, '安陽': 53, '許昌': 39, '漯河': 35, '焦作': 32, '洛陽': 31, '開封': 26, '鶴壁': 19, '濮陽': 17, '三門峽': 7, '濟源示範區': 5, '地區待確認': 0}
hn_names = henan_children_total_data.keys()
hn_numbers = henan_children_total_data.values()
import matplotlib.pyplot as plt 
import numpy as np
plt.rcParams['font.sans-serif'] = ['simhei']   # 用來正常顯示中文標籤

# 繪圖
plt.figure(figsize=[12,8])

plt.bar(hn_names,hn_numbers)

plt.xlabel("地區", size=12)
plt.ylabel("人數", fontproperties='SimHei', rotation=90, size=12)
plt.title("河南省不同地區疫情確診數對比圖", size=16)
plt.xticks(list(hn_names), rotation=90, size=12)
    
plt.show()

在這裏插入圖片描述

3.3 繪製中國不同省份確診總數據的柱狀圖

names = total_data.keys()
print(names)
dict_keys(['湖北', '廣東', '河南', '浙江', '湖南', '安徽', '江西', '山東', '江蘇', '重慶', '四川', '黑龍江', '北京', '上海', '河北', '福建', '廣西', '陝西', '雲南', '海南', '貴州', '天津', '山西', '香港', '甘肅', '遼寧', '吉林', '新疆', '內蒙古', '寧夏', '臺灣', '青海', '澳門', '西藏'])
numbers = total_data.values()
print(numbers)
dict_values([67773, 1353, 1273, 1215, 1018, 990, 935, 760, 631, 576, 539, 482, 435, 344, 318, 296, 252, 245, 174, 168, 146, 136, 133, 126, 125, 125, 93, 76, 75, 75, 48, 18, 10, 1])
import matplotlib.pyplot as plt 
import numpy as np
plt.rcParams['font.sans-serif'] = ['simhei']   # 用來正常顯示中文標籤

# 繪圖
plt.figure(figsize=[12,8])

plt.bar(names,numbers)

plt.xlabel("地區", size=12)
plt.ylabel("人數", fontproperties='SimHei', rotation=90, size=12)
plt.title("中國不同省份疫情確診數對比圖", size=16)
plt.xticks(list(names), rotation=90, size=12)
    
plt.show()

在這裏插入圖片描述

補充

  • 同樣可以獲得其他省份的柱狀圖(只要做適當調整即可);
  • 同樣也可以獲得不同數據對應的柱狀圖(如疑似數據、死亡數據和出院數據等)。

4. 繪製中國疫情趨勢圖

類似以上方法可以爬取到中國疫情不同日期的歷史數據資料(只要把下圖中步驟5下面的URL替換掉即可)。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-BUtcM3Gz-1583918215651)(D:\zgq\Anaconda3\3–網絡爬蟲–經典案例\22.png)]

from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()
import time
import json
import requests
from datetime import datetime

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']))
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

plt.rcParams['font.sans-serif'] = ['simhei']   # 用來正常顯示中文標籤

plt.figure(figsize=(12, 8))
plt.title('2019-2020年新冠肺炎疫情曲線圖', fontsize=16)

plt.plot(date_list, confirm_list, 'r-', label='確診')
plt.plot(date_list, confirm_list, 'rs')

plt.plot(date_list, suspect_list, 'b-',label='疑似')
plt.plot(date_list, suspect_list, 'b*')

plt.plot(date_list, dead_list, 'y-', label='死亡')
plt.plot(date_list, dead_list, 'y+')

plt.plot(date_list, heal_list, 'g-', label='治癒')
plt.plot(date_list, heal_list, 'gd')
    
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%m-%d')) # 格式化時間軸標註
plt.gcf().autofmt_xdate() # 優化標註(自動傾斜)
plt.grid(axis='x')       # 顯示網格
plt.legend() # 顯示圖例

plt.show()

在這裏插入圖片描述

5. 小結

以上就是通過Python爬取新冠肺炎數據並進行可視化分析的實戰案例,由於時間關係暫時先分析到這裏,後續將會對河南省不同時期的新冠肺炎歷史數據進行可視化分析(利用PyEcharts包進行動態圖分析)!

迫不及待中。。。

補充:

Matplotlib中不同參數可以得到不同的效果,更加美觀的繪圖方法參見 官網。


  • 寫作不易,切勿白剽
  • 博友們的點贊關注就是對博主堅持寫作的最大鼓勵
  • 持續更新,未完待續…
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章