五一期间新冠疫情可视化:爬虫自动采集疫情数据及可视化

五一期间新冠疫情可视化:爬虫自动采集疫情数据及可视化

本次实践基于丁香园公开的统计数据,通过爬虫技术,实现 2022五一劳动节期间 新冠疫情可视化,包括疫情地图、疫情增长趋势图、疫情分布图等。

效果如下:



那是怎么实现的呢?主要过程如下:

1.数据获取:

爬虫程序 模拟浏览器 --> 往目标站点发送请求 --> 接收响应数据 --> 提取有用的数据 --> 保存到本地。

数据获取主要requests是python实现的简单易用的HTTP库,官网地址:http://cn.python-requests.org/zh_CN/latest/

import sys

import json

import re,os

from pip import main

import requests

import datetime

import numpy as np

from pyecharts.charts import Map

from pyecharts import options as opts

from pyecharts.charts import Line

today = datetime.date.today().strftime('%Y%m%d') #20220504

COVIDA_JSON = f"./data/{today}.json"

STATICS_JSON = "./data/statistics_data.json"

def crawl_dxy_data():

"""

爬取丁香园实时统计数据,保存到data目录下,以当前日期作为文件名,存JSON文件

"""

response = requests.get('https://ncov.dxy.cn/ncovh5/view/pneumonia') #request.get()用于请求目标网站

print(response.status_code) # 打印状态码

try:

url_text = response.content.decode() #更推荐使用response.content.deocde()的方式获取响应的html页面

#print(url_text)

url_content = re.search(r'window.getAreaStat = (.*?)}]}catch', #re.search():扫描字符串以查找正则表达式模式产生匹配项的第一个位置 ,然后返回相应的match对象。

url_text, re.S) #在字符串a中,包含换行符\n,在这种情况下:如果不使用re.S参数,则只在每一行内进行匹配,如果一行没有,就换下一行重新开始;

#而使用re.S参数以后,正则表达式会将这个字符串作为一个整体,在整体中进行匹配。

texts = url_content.group() #获取匹配正则表达式的整体结果

content = texts.replace('window.getAreaStat = ', '').replace('}catch', '') #去除多余的字符

json_data = json.loads(content)

with open(COVIDA_JSON, 'w', encoding='UTF-8') as f:

json.dump(json_data, f, ensure_ascii=False)

except:

print('<Response [%s]>' % response.status_code)

def crawl_statistics_data():

"""

获取各个省份历史统计数据,保存到data目录下,存JSON文件

"""

with open(COVIDA_JSON, 'r', encoding='UTF-8') as file:

json_array = json.loads(file.read())

statistics_data = {}

for province in json_array:

response = requests.get(province['statisticsData'])

try:

statistics_data[province['provinceShortName']] = json.loads(response.content.decode())['data']

except:

print('<Response [%s]> for url: [%s]' % (response.status_code, province['statisticsData']))

with open(STATICS_JSON, "w", encoding='UTF-8') as f:

json.dump(statistics_data, f, ensure_ascii=False)

JSON_ARRAY = None

JSON_DICT = None

DefinedCity = None

if JSON_ARRAY is None or DefinedCity is None:

JSON_ARRAY, DefinedCity, JSON_DICT = load_data()

2. 可视化:

echarts 是一个由百度开源的数据可视化工具,凭借着良好的交互性,精巧的图表设计,得到了众多开发者的认可。而 Python 是一门富有表达力的语言,很适合用于数据处理。当数据分析遇上数据可视化时,pyecharts 诞生了。pyecharts api可以参考:https://pyecharts.org/#/zh-cn/chart_api

2. 获取指定省市疫情数据,并绘图,代码:

def RetailTimeStats(province_name:str = '上海'):

""" 获取实时 新冠数据并绘图

"""

for province in JSON_ARRAY:

if province['provinceName'] == province_name or province['provinceShortName'] == province_name:

json_array_province = province['cities']

result = [(city['cityName'], city['confirmedCount']) for city in json_array_province]

result = sorted(result, key=lambda x: x[1], reverse=True)

labels = [data[0] for data in result]

counts = [data[1] for data in result]

pieces = [

{'min': 10000, 'color': '#540d0d'},

{'max': 9999, 'min': 1000, 'color': '#9c1414'},

{'max': 999, 'min': 500, 'color': '#d92727'},

{'max': 499, 'min': 100, 'color': '#ed3232'},

{'max': 99, 'min': 10, 'color': '#f27777'},

{'max': 9, 'min': 1, 'color': '#f7adad'},

{'max': 0, 'color': '#f7e4e4'},

]

m = Map()

m.add("累计确诊", [list(z) for z in zip(labels, counts)], str(province_name))

m.set_series_opts(label_opts=opts.LabelOpts(font_size=12), is_show=False)

m.set_global_opts(title_opts=opts.TitleOpts(title=f'{province_name}实时确诊数据 - {today}',

subtitle='数据来源:丁香园'),

legend_opts=opts.LegendOpts(is_show=False),

visualmap_opts=opts.VisualMapOpts(pieces=pieces,

is_piecewise=True,

is_show=True))

m.render(path=f'./{province_name}实时确诊数据.html')

效果

全国单日现存确诊病例

def RetailTimeChina():

def getYesterday():

""" 昨天时间 :因为丁香园当天数据第二天才公布,所以取前一天的数据。"""

today=datetime.date.today()

oneday=datetime.timedelta(days=1)

yesterday=today-oneday

return yesterday.strftime('%Y%m%d')

statist_time = int(getYesterday())

china_data = {}

for k,v in JSON_DICT.items():

china_data[k] = []

for da in v:

if da['dateId'] >= statist_time:

currentConfirmedCount = da['currentConfirmedCount']

china_data[k].append(currentConfirmedCount)

china_data = [(k, sum(v)) for k,v in china_data.items()]

china_data = sorted(china_data, key=lambda x: x[1], reverse=True)

pieces = [

{'min': 10000, 'color': '#540d0d'},

{'max': 9999, 'min': 1000, 'color': '#9c1414'},

{'max': 999, 'min': 500, 'color': '#d92727'},

{'max': 499, 'min': 100, 'color': '#ed3232'},

{'max': 99, 'min': 10, 'color': '#f27777'},

{'max': 9, 'min': 1, 'color': '#f7adad'},

{'max': 0, 'color': '#f7e4e4'},

]

labels = [data[0] for data in china_data]

counts = [data[1] for data in china_data]

m = Map()

m.add("累计确诊", [list(z) for z in zip(labels, counts)], 'china')

#系列配置项,可配置图元样式、文字样式、标签样式、点线样式等

m.set_series_opts(label_opts=opts.LabelOpts(font_size=12),

is_show=False)

#全局配置项,可配置标题、动画、坐标轴、图例等

m.set_global_opts(title_opts=opts.TitleOpts(title=f'全国现存确诊数据-{statist_time}',

subtitle='数据来源:丁香园'),

legend_opts=opts.LegendOpts(is_show=False),

visualmap_opts=opts.VisualMapOpts(pieces=pieces,

is_piecewise=True, #是否为分段型

is_show=True)) #是否显示视觉映射配置

#render()会生成本地 HTML 文件,默认会在当前目录生成 render.html 文件,也可以传入路径参数,如 m.render("mycharts.html")

m.render(path=f'./全国实时确诊数据-{statist_time}.html')

疫情增长趋势:

def CovidTrend(province_name: str='上海', statist_time = 20220201):

# 获取日期列表

dateId = [str(da['dateId'])[4:6] + '-' + str(da['dateId'])[6:8] for da in JSON_DICT[province_name] if da['dateId'] >= statist_time]

# 分析各省份2月1日至今的新增确诊数据:'confirmedIncr'

statistics__data = {}

for province in JSON_DICT:

statistics__data[province] = []

for da in JSON_DICT[province]:

if da['dateId'] >= statist_time:

statistics__data[province].append(da['confirmedIncr'])

#若当天该省数据没有更新,则默认为0

if(len(statistics__data[province])!=len(dateId)):

statistics__data[province].append(0)

# 全国新增趋势

all_statis = np.array([0] * len(dateId))

for province in statistics__data:

all_statis = all_statis + np.array(statistics__data[province])

all_statis = all_statis.tolist()

# 湖北新增趋势

hubei_statis = statistics__data[province_name]

# 湖北以外的新增趋势

other_statis = [all_statis[i] - hubei_statis[i] for i in range(len(dateId))]

line = Line()

line.add_xaxis(dateId)

line.add_yaxis("全国新增确诊病例", #图例

all_statis, #数据

is_smooth=True, #是否平滑曲线

linestyle_opts=opts.LineStyleOpts(width=4, color='#B44038'),#线样式配置项

itemstyle_opts=opts.ItemStyleOpts(color='#B44038', #图元样式配置项

border_color="#B44038", #颜色

border_width=10)) #图元的大小

line.add_yaxis(f"{province_name}新增确诊病例", hubei_statis, is_smooth=True,

linestyle_opts=opts.LineStyleOpts(width=2, color='#4E87ED'),

label_opts=opts.LabelOpts(position='bottom'), #标签在折线的底部

itemstyle_opts=opts.ItemStyleOpts(color='#4E87ED',

border_color="#4E87ED",

border_width=3))

line.add_yaxis("其他省份新增病例", other_statis, is_smooth=True,

linestyle_opts=opts.LineStyleOpts(width=2, color='#F1A846'),

label_opts=opts.LabelOpts(position='bottom'), #标签在折线的底部

itemstyle_opts=opts.ItemStyleOpts(color='#F1A846',

border_color="#F1A846",

border_width=3))

line.set_global_opts(title_opts=opts.TitleOpts(title=f"{province_name}新增确诊病例-{today}", subtitle='数据来源:丁香园'),

yaxis_opts=opts.AxisOpts(max_=16000, min_=1, type_="

log", #坐标轴配置项

splitline_opts=opts.SplitLineOpts(is_show=True),#分割线配置项

axisline_opts=opts.AxisLineOpts(is_show=True)))#坐标轴刻度线配置项

line.render(path=f'./{province_name}-新增确诊趋势图.html')

以上就是主要思路和过程。免费获取源码请私信。

备注:免费获取方法,关注微信公众号 paperClub, 请您发送私信 :新冠01

1. 感谢各位小伙伴的关注, 您的点赞、鼓励和留言,都是我深夜坚持的一份动力,无论褒贬,都是我们行进途中最好的回馈,也都会被认真对待。

2. 我将持续分享各类、好玩且有趣的算法应用及工程和项目,欢迎分享和转发。沟通、学习和交流,请与我联系,虽然平时忙,但留言必回,勿急,感谢理解!

3. 分享内容包括开源项目和自研项目,如在引用或使用时,考虑不周、遗漏引用信息或涉及版权等,请您及时联系。如果您对某些内容感兴趣,我们可以一起讨论、交流和学习。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容