新冠肺炎數(shù)據(jù)可視化

數(shù)據(jù)獲取

目前,騰訊的疫情實時追蹤 網(wǎng)頁能夠看到實時的新冠病毒數(shù)據(jù),網(wǎng)頁的數(shù)據(jù)展示也非常清晰。但這個網(wǎng)頁提供的數(shù)據(jù)沒有每個市的歷史數(shù)據(jù)。其它幾個新聞網(wǎng)頁的數(shù)據(jù)也都大同小異。

為了能夠得到自己想看的數(shù)據(jù),尤其的自己比較關(guān)心的數(shù)據(jù),我觀察了幾個網(wǎng)址的數(shù)據(jù)并且用 Python 進(jìn)行了獲取。下面對數(shù)據(jù)獲取和數(shù)據(jù)展示的方法進(jìn)行介紹,供大家參考。

騰訊網(wǎng)頁數(shù)據(jù)源

為了便于對照,建議大家使用 Chrome 瀏覽器查看,其實每種瀏覽器都類似,但界面不同,看自己的習(xí)慣。用 Chrome 打開 疫情實時追蹤 頁面,然后按下 F12,Chrome 打開 Developer Tools,再次點擊頁面刷新按鈕,追蹤到數(shù)據(jù)獲取的的 Script 如下:

Response 返回的是 applicatio/json 格式的數(shù)據(jù)(Response Headers: application/json),雙擊左邊的 getOnsInfo**, Chrome 打開一個新的頁面,展示最新的病情數(shù)據(jù):


我們再看 Query String Parameters 中有兩個參數(shù),其中 callback 參數(shù)應(yīng)該是一個基于毫秒級別的時間戳。URL 去掉這個 callback 參數(shù)也可以獲得最新的感染人數(shù)數(shù)據(jù)。



對這個返回的 json 數(shù)據(jù),我們可以另存為一個 json 文件,并對數(shù)據(jù)的結(jié)構(gòu)進(jìn)行分析。分析的過程這里就不展開了。在這個網(wǎng)頁中能獲得如下數(shù)據(jù):

  • 中國確認(rèn)的總?cè)藬?shù)(chinaTotal)
  • 新增人數(shù)(chinaAdd)
  • 每日人數(shù)匯總歷史數(shù)據(jù)(chinaDayList)
  • 每日新增人數(shù)歷史數(shù)據(jù)(chinaDayAddList)
  • 每日新增人數(shù)歷史數(shù)據(jù),分湖北、非湖北、全國三個維度 (dailynewAddHistory)
  • 每日死亡率歷史數(shù)據(jù) (dailyDeadRateHistory)
  • areaTree: 這個節(jié)點下面包全世界數(shù)據(jù),中國數(shù)據(jù)到市級的數(shù)據(jù),是最詳細(xì)的。

通過 Web API 獲取

除了騰訊這種新聞頁面,我們利用頁面的數(shù)據(jù)源間接獲取,也可以利用網(wǎng)上 Web API 進(jìn)行獲取。比如天氣 api 就提供了疫情的 API。打開 http://tianqiapi.com/ 網(wǎng)頁,我們可以看到頁面有一個連接:


點擊進(jìn)入開發(fā)者指南頁面,對調(diào)用的 url 和返回格式有詳細(xì)說明。允許每天免費調(diào)用 3 萬次,但需要先注冊一個賬號。

另外,Github 上也比較活躍,有很多項目利用爬蟲,從諸如丁香醫(yī)生的網(wǎng)站上爬取數(shù)據(jù),然后提供數(shù)據(jù)更新和 Web API 服務(wù)。下面的這個項目就挺不錯:

項目地址:https://github.com/BlankerL/DXY-COVID-19-Crawler
數(shù)據(jù)倉庫:https://github.com/BlankerL/DXY-COVID-19-Data

這個項目提供的 api 調(diào)用示例如下:

https://lab.isaaclin.cn/nCoV/api/overall  # 返回全面疫情概況
https://lab.isaaclin.cn/nCoV/api/provinceName  # 返回省列表
https://lab.isaaclin.cn/nCoV/api/area?latest=0&province=湖北省  # 返回湖北省歷史數(shù)據(jù)

API 調(diào)用請自行閱讀 API 調(diào)用說明。

數(shù)據(jù)可視化

我根據(jù)自己的目的,使用 pandas 模塊,將數(shù)據(jù)保存到 Excel,通過 pyecharts 模塊,將可視化地圖保存為 html 文件,代碼比較直觀,主要的處理過程為對含有多層次的數(shù)據(jù)進(jìn)行扁平化,得到一個二維的數(shù)據(jù)。地圖中顯示的數(shù)據(jù)市確認(rèn)病例的數(shù)據(jù)。pyecharts 的版本迭代較快,并且 0.5 版和 1.0 版不兼容。我使用的是 1.6 版。

import requests
import json
import pandas as pd
import os
import datetime

from pyecharts import options as opts
from pyecharts.charts import *

cities = []
def get_ncov_data() -> str:
    url = 'https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5'
    data = requests.get(url).json()['data']

    return data

def get_daily_data() -> list:
    all = json.loads(get_ncov_data())
    return all['chinaDayList']


def flatten_ncov_data() -> list:
    all = json.loads(get_ncov_data())
    date = all['lastUpdateTime']

    # 第一層:國家
    china = all['areaTree'][0]['children']  # get China data

    # 第二層:省
    for province in china:
        province_ncov = province['children']

        # 第三層:市
        for city in province_ncov:
            # 輸出格式
            city_ncov = {
                '日期': date,
                '省份': province['name'],
                '市': city['name'],
                '新增確認(rèn)': city['today']['confirm'],
                '新增治愈': city['today']['heal'],
                '新增死亡': city['today']['dead'],
                '累計確認(rèn)': city['total']['confirm'],
                '累計治愈': city['total']['heal'],
                '累計死亡': city['total']['dead']
            }

            cities.append(city_ncov)

def export_excel():
    cities.clear()
    flatten_ncov_data()
    df = pd.DataFrame(cities)

    # 導(dǎo)出Excel
    path = os.path.dirname(os.path.abspath(__file__))
    output_file = os.path.join(path, 'output.xlsx')

    df.to_excel(output_file)

def render_map_chart():
    cities.clear()
    flatten_ncov_data()
    df = pd.DataFrame(cities)

    # Render Map chart
    map_chart = Map()
    map_chart.add(
        "中國",  # map name
        [list(z) for z in zip(list(df["省份"]), list(df['累計確認(rèn)']))],
        "china",
        is_map_symbol_show=False
    )

    map_chart.set_global_opts(
        title_opts=opts.TitleOpts(
            title="nCoV疫情地圖(" + str(datetime.date.today()) + ")"
        ),
        visualmap_opts=opts.VisualMapOpts(
            max_=50000,
            is_piecewise=True,
            pieces=[
                {"min": 1, "max": 9, "label": "10人以下", "color": "#FFE6BE"},
                {"min": 10, "max": 99, "label": "10-99人", "color": "#FFB769"},
                {"min": 100, "max": 499, "label": "100-499人", "color": "#FF8F66"},
                {"min": 500, "max": 999, "label": "500-999人", "color": "#ED514E"},
                {"min": 1000, "max": 50000, "label": "1000人以上", "color": "#CA0D11"}
            ]))

    map_chart.render('ncov_map_chart_{}.html'.format(datetime.date.today()))


def render_line_chart():
    daily_data = get_daily_data()
    df = pd.DataFrame(daily_data)

    line_chart = Line()
    line_chart.add_xaxis(list(df["date"]))
    line_chart.add_yaxis("確認(rèn)", list(df["confirm"]))
    line_chart.add_yaxis("疑似", list(df["suspect"]))
    line_chart.set_global_opts(
        title_opts=opts.TitleOpts(title="nCoV確認(rèn)病例與疑似病例曲線")
    )

    line_chart.render('ncov_line_chart-{}.html'.format(datetime.date.today()))


if __name__ == "__main__":

    export_excel()
    render_map_chart()
    render_line_chart()

地圖顯示的效果如下,與騰訊疫情地圖圖例的顏色一樣。

確認(rèn)和疑似病例的日趨勢曲線如下:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容