pyecharts实现新冠肺炎疫情可视化BI数据大屏

己亥末,庚子春,荆楚大疫,染着数万计。众惶恐,举国防,皆闭户。街无舟车,巷无人烟,时天下震动。然九州一心,青丝白发皆身先士卒,布衣商客皆争相解囊,政医兵者扛鼎逆行为之勇战矣,能者皆竭力之。月余,疫尽去,国泰民安。

在这里先向全国抗疫的国内外各行各业的人士致敬!

然后说题目项目

pyecharts 是一个用于生成 Echarts 图表的类库。
Echarts 是百度开源的一个数据可视化 JS 库,主要用于数据可视化。pyecharts 是一个用于生成 Echarts 图表的类库。实际上就是 Echarts 与 Python 的对接。
详情请看官方文档:https://pyecharts.org/#/zh-cn/intro

话不多说先上效果图:
在这里插入图片描述
接下来从头说:

1.数据抓取:
数据源:腾讯疫情实时追踪
首先对该网站F12,点击Network刷新页面,看看每个页面的Response:
在这里插入图片描述
在这里插入图片描述
找到了,是这个:https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5&callback=jQuery34102867663505226432_1581423137066&_=1581423137067
但是在刷新一下会发现callback后面的东西就变了,推测这是一个时间戳,把它去了用https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5试试:
在这里插入图片描述
嗯,也可以,就它了,这就是数据源。
先引入所需模块:

import json
import requests
import pandas as pd
from pyecharts.charts import *
from pyecharts import options as opts
from pyecharts.commons.utils import JsCode
from pyecharts.globals import ThemeType, ChartType
from bs4 import BeautifulSoup

接下来抓取数据:

reponse = requests.get('https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5').json()
data = json.loads(reponse['data'])
'''
print(data.keys())
dict_keys(['lastUpdateTime', 'chinaTotal', 'chinaAdd', 'isShowAdd', 'chinaDayList', 'chinaDayAddList', 'dailyNewAddHistory', 'dailyDeadRateHistory', 'confirmAddRank', 'areaTree', 'articleList'])
判断大概就是截至时间,新增人数,死亡率治愈率等等,就是我们所需的
'''

数据处理:

# 国内
lastUpdateTime = data['lastUpdateTime']
'''
由于后面可视化要用到,但这字典的key都是英文,
为了方便观看,我就将其转化为中文了
'''
chinaTotal = data['chinaTotal']
chinaTotal['确诊'] = chinaTotal['confirm']
chinaTotal['疑似'] = chinaTotal['suspect']
chinaTotal['死亡'] = chinaTotal['dead']
chinaTotal['治愈'] = chinaTotal['heal']
del chinaTotal['confirm']
del chinaTotal['suspect']
del chinaTotal['dead']
del chinaTotal['heal']

sum = chinaTotal['确诊'] + chinaTotal['疑似'] + chinaTotal['死亡'] + chinaTotal['治愈']
'''
本来chinaAdd是用来统计新增人数的,但是不知道哪里出了点问题,新增疑似(suspect)是负的...
(网页上就是这样显示的,咱也不知道,(咱jio的是TX的问题)但咱也不敢问,
所以就用chinaDayAddList(每日新增数据列表)里的最后一项来代替了...
'''
chinaAdd = data['chinaAdd']
chinaAdd['新增确诊'] = data['chinaDayAddList'][-1]['confirm']
chinaAdd['新增疑似'] = data['chinaDayAddList'][-1]['suspect']
chinaAdd['新增死亡'] = data['chinaDayAddList'][-1]['dead']
chinaAdd['新增治愈'] = data['chinaDayAddList'][-1]['heal']
del chinaAdd['confirm']
del chinaAdd['suspect']
del chinaAdd['dead']
del chinaAdd['heal']

areaTree = data['areaTree']

china_data = areaTree[0]['children']
china_list = []
for x in range(len(china_data)):
    province = china_data[x]['name']
    province_list = china_data[x]['children']
    for y in range(len(province_list)):
        city = province_list[y]['name']
        total = province_list[y]['total']
        today = province_list[y]['today']
        china_dict = {'province': province, 'city': city, 'total': total, 'today': today}
        china_list.append(china_dict)

# 定义数据处理函数
def confirm(x):
    confirm = eval(str(x))['confirm']
    return confirm

def suspect(x):
    suspect = eval(str(x))['suspect']
    return suspect

def dead(x):
    dead = eval(str(x))['dead']
    return dead

def heal(x):
    heal = eval(str(x))['heal']
    return heal

china_data = pd.DataFrame(china_list)
china_data.head()

# 函数映射
china_data['confirm'] = china_data['total'].map(confirm)
china_data['suspect'] = china_data['total'].map(suspect)
china_data['dead'] = china_data['total'].map(dead)
china_data['heal'] = china_data['total'].map(heal)
china_data['addconfirm'] = china_data['today'].map(confirm)
china_data['addsuspect'] = china_data['today'].map(suspect)
china_data['adddead'] = china_data['today'].map(dead)
china_data['addheal'] = china_data['today'].map(heal)
china_data = china_data[
    ["province", "city", "confirm", "suspect", "dead", "heal", "addconfirm", "addsuspect", "adddead", "addheal"]]
china_data.head()

# 国际数据处理
global_data = pd.DataFrame(data['areaTree'])
global_data['confirm'] = global_data['total'].map(confirm)
global_data['suspect'] = global_data['total'].map(suspect)
global_data['dead'] = global_data['total'].map(dead)
global_data['heal'] = global_data['total'].map(heal)
global_data['addconfirm'] = global_data['today'].map(confirm)
global_data['addsuspect'] = global_data['today'].map(suspect)
global_data['adddead'] = global_data['today'].map(dead)
global_data['addheal'] = global_data['today'].map(heal)
world_name = pd.read_excel("世界各国中英文对照.xlsx")
global_data = pd.merge(global_data, world_name, left_on="name", right_on="中文", how="inner")
global_data = global_data[
    ["name", "英文", "confirm", "suspect", "dead", "heal", "addconfirm", "addsuspect", "adddead", "addheal"]]
global_data.head()

# 日数据处理
chinaDayList = pd.DataFrame(data['chinaDayList'])
chinaDayList = chinaDayList[['date', 'confirm', 'suspect', 'dead', 'heal']]
chinaDayList.head()

# 日新增数据处理
chinaDayAddList = pd.DataFrame(data['chinaDayAddList'])
chinaDayAddList = chinaDayAddList[['date', 'confirm', 'suspect', 'dead', 'heal']]
chinaDayAddList.head()

在这里插入图片描述
数据可视化:


# 左上角饼图
total_pie = (
    Pie(init_opts=opts.InitOpts(theme=ThemeType.LIGHT, width='500px', height='350px', bg_color="transparent"))
        .add("", [list(z) for z in zip(['确     诊  ', '疑     似  ', '死     亡  ', '治     愈  '], chinaTotal.values())],
             center=["50%", "60%"], radius=[75, 100], )
        .add("", [list(z) for z in zip(chinaAdd.keys(), chinaAdd.values())], center=["50%", "60%"], radius=[0, 50])
        .set_global_opts(title_opts=opts.TitleOpts(title="全国总量", pos_bottom=0,
                                                   title_textstyle_opts=opts.TextStyleOpts(color="#00FFFF")),
                         legend_opts=opts.LegendOpts(textstyle_opts=opts.TextStyleOpts(color="#FFFFFF")))
        .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{c}")))

# 中间全球疫情地图
world_map = (
    Map(init_opts=opts.InitOpts(theme=ThemeType.WESTEROS))
        .add("", [list(z) for z in zip(list(global_data["英文"]), list(global_data["confirm"]))], "world",
             is_map_symbol_show=False)
        .set_series_opts(label_opts=opts.LabelOpts(is_show=False),
                         toolbox_opts=opts.ToolboxOpts(orient='vertical', pos_right="10%"))
        .set_global_opts(visualmap_opts=opts.VisualMapOpts(is_piecewise=True, background_color="transparent",
                                                           textstyle_opts=opts.TextStyleOpts(color="#F5FFFA"),
                                                           pieces=[
                                                               {"min": 101, "label": '>100', "color": "#893448"},
                                                               {"min": 10, "max": 100, "label": '10-100',
                                                                "color": "#fb8146"},
                                                               {"min": 1, "max": 9, "label": '1-9',
                                                                "color": "#fff2d1"},
                                                           ])))

# 右下角中国疫情地图绘制
area_data = china_data.groupby("province")["confirm"].sum().reset_index()
area_data.columns = ["province", "confirm"]

area_map = (
    Map(init_opts=opts.InitOpts(theme=ThemeType.WESTEROS))
        .add("", [list(z) for z in zip(list(area_data["province"]), list(area_data["confirm"]))], "china",
             is_map_symbol_show=False, label_opts=opts.LabelOpts(color="#fff"),
             tooltip_opts=opts.TooltipOpts(is_show=True), zoom=1.2, center=[105, 30])
        .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
        .set_global_opts(title_opts=opts.TitleOpts(title="中国疫情分布图", pos_top='5%',
                                                   title_textstyle_opts=opts.TextStyleOpts(color="#FF0000")),
                         visualmap_opts=opts.VisualMapOpts(is_piecewise=True, pos_right=0, pos_bottom=0,
                                                           textstyle_opts=opts.TextStyleOpts(color="#F5FFFA"),
                                                           pieces=[
                                                               {"min": 1001, "label": '>1000', "color": "#893448"},
                                                               {"min": 500, "max": 1000, "label": '500-1000',
                                                                "color": "#ff585e"},
                                                               {"min": 101, "max": 499, "label": '101-499',
                                                                "color": "#fb8146"},
                                                               {"min": 10, "max": 100, "label": '10-100',
                                                                "color": "#ffb248"},
                                                               {"min": 0, "max": 9, "label": '0-9',
                                                                "color": "#fff2d1"}])))
                                                                
# 左下角热图及城市分布
city_data = china_data.groupby('city')['confirm'].sum().reset_index()
city_data.columns = ["city", "confirm"]

'''
由于某些名字地图上无法定位,比如“外地来京”、
“外地来津”、“外地来沪”等,这种会报错,
所以要先清洗数据
'''
def is_city(item):
    '''
    判断一个城市能否在Geo地图上被找到
    :param item: 城市名
    :return: T/F
    '''

    lists_1 = []
    lists_1.append(item)
    lists_2 = [10]
    geo = Geo()
    geo.add_schema(maptype="china")
    try:
        geo.add("确诊城市", [list(z) for z in zip(lists_1, lists_2)])
        return True
    except TypeError as e:
        return False


city_index = []
i = 0
for item in city_data['city']:
    if is_city(item) == False:
        city_index.append(i)
    i += 1

for x in city_index:
    del (city_data['city'][x])
    del (city_data['confirm'][x])

city_index_ = []
i = 0
for item in city_data['confirm']:
    if item > 1000:
        city_index_.append(i)
    i += 1

serious_city = []  # 严重城市
serious_submit = []  # 严重人数
for y in city_index_:
    serious_city.append(list(city_data['city'])[y])
    serious_submit.append(list(city_data['confirm'])[y])

# 找不到拉萨,所以我自己添加上去了
list_1 = ["拉萨"]
list_2 = [1]

area_heat_geo = (
    Geo(init_opts=opts.InitOpts(theme=ThemeType.WESTEROS, bg_color='transparent'))
        .add_schema(maptype="china", zoom=1.2, center=[105, 30])
        .add("确诊城市", [list(z) for z in zip(list(city_data["city"]), list(city_data["confirm"]))], symbol_size=10)
        .add("确诊城市", [list(z) for z in zip(list_1, list_2)], symbol_size=10)  # 孤独拉萨
        .add("确诊城市", [list(z) for z in zip(list(serious_city), list(serious_submit))],  # 感染者超1000的城市
             type_=ChartType.EFFECT_SCATTER, effect_opts=opts.EffectOpts(is_show=True, color="black",
                                                                         symbol_size=30, scale=4, period=1))
        .add("", [list(z) for z in zip(list(city_data["city"]), list(city_data["confirm"]))],
             type_=ChartType.HEATMAP)
        .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
        .set_global_opts(
        visualmap_opts=opts.VisualMapOpts(range_size=[0, 25, 50, 75, 100], max_=1000, orient='horizontal',
                                          pos_bottom=0),
        title_opts=opts.TitleOpts(title="中国疫情分布热图", pos_top='5%'),
        legend_opts=opts.LegendOpts(pos_bottom='10%', pos_left=0)))

# 中间线型图和柱状图结合
line = (
    Line(init_opts=opts.InitOpts(theme=ThemeType.CHALK, bg_color="transparent"))
        .add_xaxis(list(chinaDayList["date"]))
        .add_yaxis("累计确诊               ", list(chinaDayList["confirm"]), is_smooth=True, yaxis_index=1)
        .add_yaxis("累计疑似               ", list(chinaDayList["suspect"]), is_smooth=True, yaxis_index=1)
        .add_yaxis("累计死亡               ", list(chinaDayList["dead"]), is_smooth=True, yaxis_index=1)
        .add_yaxis("累计治愈", list(chinaDayList["heal"]), is_smooth=True, yaxis_index=1)
        .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
        .set_global_opts(legend_opts=opts.LegendOpts(pos_left='center')))

bar = (
    Bar(init_opts=opts.InitOpts(theme=ThemeType.CHALK, bg_color="transparent"))
        .add_xaxis(list(chinaDayAddList["date"]))
        .add_yaxis("单日确诊               ", list(chinaDayAddList["confirm"]))
        .add_yaxis("单日疑似               ", list(chinaDayAddList["suspect"]))
        .add_yaxis("单日死亡               ", list(chinaDayAddList["dead"]))
        .add_yaxis("单日治愈", list(chinaDayAddList["heal"]))
        .extend_axis(yaxis=opts.AxisOpts(axislabel_opts=opts.LabelOpts(formatter="{value}")))
        .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
        .set_global_opts(legend_opts=opts.LegendOpts(pos_left='center'),
                         yaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(formatter="{value}")),
                         datazoom_opts=opts.DataZoomOpts())).overlap(line)
                         
# 中间大标题
big_title = (
    Pie()
        .set_global_opts(
        title_opts=opts.TitleOpts(title="2019-nCov",
                                  title_textstyle_opts=opts.TextStyleOpts(font_size=40, color='#FFFFFF',
                                                                          border_radius=True, border_color="white"),
                                  pos_top=0)))
# 截至时间
times = (
    Pie()
        .set_global_opts(
        title_opts=opts.TitleOpts(subtitle=("截至 " + lastUpdateTime),
                                  subtitle_textstyle_opts=opts.TextStyleOpts(font_size=13, color='#FFFFFF'),
                                  pos_top=0))
)

# 右上角那一堆
# (本来想用Grid排版,但是始终达不到自己想要的效果,就用笨办法啦)
confirms = (Pie().
            set_global_opts(title_opts=opts.TitleOpts(title="确诊", pos_left='center', pos_top='center',
                                                      title_textstyle_opts=opts.TextStyleOpts(color='#FFFFFF'))))
confirms_people = (Pie().
                   set_global_opts(title_opts=opts.TitleOpts(title=(str(chinaTotal['确诊']) + "   "),
                                                             pos_top='15%', pos_left='center',
                                                             subtitle=("         新增: " + str(chinaAdd['新增确诊'])),
                                                             item_gap=1,
                                                             title_textstyle_opts=opts.TextStyleOpts(color="#00FFFF",
                                                                                                     font_size=30),
                                                             subtitle_textstyle_opts=opts.TextStyleOpts(color="#00BFFF")
                                                             )))                                                            
suspects = (Pie().
            set_global_opts(title_opts=opts.TitleOpts(title="疑似", pos_left='center', pos_top='center',
                                                      title_textstyle_opts=opts.TextStyleOpts(color='#FFFFFF'))))
suspects_people = (Pie().
                   set_global_opts(title_opts=opts.TitleOpts(title=(str(chinaTotal['疑似']) + "   "),
                                                             pos_top='15%', pos_left='center',
                                                             subtitle=("         新增 :" + str(chinaAdd['新增疑似'])),
                                                             item_gap=1,
                                                             title_textstyle_opts=opts.TextStyleOpts(color="#FF00FF",
                                                                                                     font_size=30),
                                                             subtitle_textstyle_opts=opts.TextStyleOpts(color="#EE82EE")
                                                             )))
deads = (Pie().
         set_global_opts(title_opts=opts.TitleOpts(title="死亡", pos_left='center', pos_top='center',
                                                   title_textstyle_opts=opts.TextStyleOpts(color='#FFFFFF'))))
deads_people = (Pie().
                set_global_opts(title_opts=opts.TitleOpts(title=(str(chinaTotal['死亡']) + "   "),
                                                          pos_top='15%', pos_left='center',
                                                          subtitle=("         新增 :" + str(chinaAdd['新增死亡'])),
                                                          item_gap=1,
                                                          title_textstyle_opts=opts.TextStyleOpts(color="#FF0000",
                                                                                                  font_size=30),
                                                          subtitle_textstyle_opts=opts.TextStyleOpts(color="#F08080")
                                                          )))
heals = (Pie().
         set_global_opts(title_opts=opts.TitleOpts(title="治愈", pos_left='center', pos_top='center',
                                                   title_textstyle_opts=opts.TextStyleOpts(color='#FFFFFF'))))
heals_people = (Pie().
                set_global_opts(title_opts=opts.TitleOpts(title=(str(chinaTotal['治愈']) + "   "),
                                                          pos_top='15%', pos_left='center',
                                                          subtitle=("         新增 :" + str(chinaAdd['新增治愈'])),
                                                          item_gap=1,
                                                          title_textstyle_opts=opts.TextStyleOpts(color="#00FF00",
                                                                                                  font_size=30),
                                                          subtitle_textstyle_opts=opts.TextStyleOpts(color="#98FB98")
                                                          )))

confirm_liquid = (
    Liquid()
        .add("确诊比例", [chinaTotal['确诊'] / sum], tooltip_opts=opts.TooltipOpts(),
             label_opts=opts.LabelOpts(color="#00FFFF",
                                       font_size=15,
                                       formatter=JsCode(
                                           """function (param) {
                     return (Math.floor(param.value * 10000) / 100) + '%';
                 }"""
                                       ),
                                       position="inside",
                                       ),
             )
)

suspect_liquid = (
    Liquid()
        .add("疑似比例", [chinaTotal['疑似'] / sum], tooltip_opts=opts.TooltipOpts(),
             label_opts=opts.LabelOpts(color="#FF00FF",
                                       font_size=15,
                                       formatter=JsCode(
                                           """function (param) {
                     return (Math.floor(param.value * 10000) / 100) + '%';
                 }"""
                                       ),
                                       position="inside",
                                       ),
             )
)

dead_liquid = (
    Liquid()
        .add("死亡比例", [chinaTotal['死亡'] / sum], tooltip_opts=opts.TooltipOpts(),
             label_opts=opts.LabelOpts(color="#FF0000",
                                       font_size=15,
                                       formatter=JsCode(
                                           """function (param) {
                     return (Math.floor(param.value * 10000) / 100) + '%';
                 }"""
                                       ),
                                       position="inside",
                                       ),
             )
)

heal_liquid = (
    Liquid()
        .add("治愈比例", [chinaTotal['治愈'] / sum], tooltip_opts=opts.TooltipOpts(),
             label_opts=opts.LabelOpts(color="#00FF00",
                                       font_size=15,
                                       formatter=JsCode(
                                           """function (param) {
                     return (Math.floor(param.value * 10000) / 100) + '%';
                 }"""
                                       ),
                                       position="inside",
                                       ),
             )
)

wc = (
    WordCloud()
        .add("", [list(z) for z in zip(list(city_data["city"]), list(city_data["confirm"]))],
             word_gap=0, word_size_range=[10, 30]))

用Page()将上面的一堆添加到一个页面:

'''
方法一:
先用注释掉的两行,打开页面
拖动各个模块到你想要的位置
然后点击左上方的save config保存配置文件
(./chart_config.json)
然后再用另外两行生成你想要的页面
'''
# page = (Page(page_title="2019-nCov",layout=Page.DraggablePageLayout)
page = (Page(page_title="2019-nCov")
        .add(world_map)
        .add(total_pie)
        .add(area_map)
        .add(area_heat_geo)
        .add(bar)
        .add(big_title)
        .add(times)
        .add(confirms)
        .add(confirms_people)
        .add(suspects)
        .add(suspects_people)
        .add(deads)
        .add(deads_people)
        .add(heals)
        .add(heals_people)
        .add(confirm_liquid)
        .add(suspect_liquid)
        .add(dead_liquid)
        .add(heal_liquid)
        .add(wc)
      # ).render("render.html")
        ).save_resize_html("render.html", cfg_file="chart_config.json", dest="2019-nCoV 数据一览.html")

但是这种方法我试了,不行,(但是官方文档里介绍了这种方法:http://pyecharts.org/#/zh-cn/composite_charts?id=page%ef%bc%9a%e9%a1%ba%e5%ba%8f%e5%a4%9a%e5%9b%be)你们可以试试…所以我用的是下面这种方法:

'''
方法二:
直接修改.html文件
'''
with open("2019-nCov 数据一览.html", "r+", encoding='utf-8') as html:
    html_bf = BeautifulSoup(html, 'lxml')
    divs = html_bf.select('.chart-container')
    divs[0][
        "style"] = "width:605px;height:274px;position:absolute;top:36px;left:333px;border-style:solid;border-color:#444444;border-width:0px;"
    divs[1][
        'style'] = "width:411px;height:303px;position:absolute;top:5px;left:0px;border-style:solid;border-color:#444444;border-width:0px;"
    divs[2][
        "style"] = "width:309px;height:405px;position:absolute;top:313px;left:961px;border-style:solid;border-color:#444444;border-width:0px;"
    divs[3][
        "style"] = "width:305px;height:405px;position:absolute;top:310px;left:0px;border-style:solid;border-color:#444444;border-width:0px;"

    divs[4][
        "style"] = "width:646px;height:304px;position:absolute;top:312px;left:312px;border-style:solid;border-color:#444444;border-width:0px;"
    divs[5][
        "style"] = "width:250px;height:55px;position:absolute;top:2px;left:440px;border-style:solid;border-color:#444444;border-width:0px;"
    divs[6][
        "style"] = "width:200px;height:30px;position:absolute;top:11px;left:675px;border-style:solid;border-color:#444444;border-width:0px;"

    divs[7][
        'style'] = "width:60px;height:75px;position:absolute;top:5px;left:1060px;border-style:solid;border-color:#DC143C;border-width:3px;border-radius:25px 0px 0px 0px"
    divs[8][
        "style"] = "width:130px;height:75px;position:absolute;top:5px;left:1120px;border-style:solid;border-color:#DC143C;border-width:3px;"
    divs[9][
        "style"] = "width:60px;height:75px;position:absolute;top:80px;left:1060px;border-style:solid;border-color:#DC143C;border-width:3px;"
    divs[10][
        "style"] = "width:130px;height:75px;position:absolute;top:80px;left:1120px;border-style:solid;border-color:#DC143C;border-width:3px;"
    divs[11][
        "style"] = "width:60px;height:75px;position:absolute;top:155px;left:1060px;border-style:solid;border-color:#DC143C;border-width:3px;"
    divs[12][
        "style"] = "width:130px;height:75px;position:absolute;top:155px;left:1120px;border-style:solid;border-color:#DC143C;border-width:3px;"
    divs[13][
        "style"] = "width:60px;height:75px;position:absolute;top:230px;left:1060px;border-style:solid;border-color:#DC143C;border-width:3px;"
    divs[14][
        "style"] = "width:130px;height:75px;position:absolute;top:230px;left:1120px;border-style:solid;border-color:#DC143C;border-width:3px;border-radius:0px 0px 25px 0px"

    divs[15][
        "style"] = "width:160px;height:160px;position:absolute;top:-35px;left:920px;border-style:solid;border-color:#444444;border-width:0px;"
    divs[16][
        "style"] = "width:160px;height:160px;position:absolute;top:40px;left:865px;border-style:solid;border-color:#444444;border-width:0px;"
    divs[17][
        "style"] = "width:160px;height:160px;position:absolute;top:115px;left:920px;border-style:solid;border-color:#444444;border-width:0px;"
    divs[18][
        "style"] = "width:160px;height:160px;position:absolute;top:188px;left:865px;border-style:solid;border-color:#444444;border-width:0px;"
    divs[19][
        "style"] = "width:1280px;height:120px;position:absolute;top:600px;left:0px;border-style:solid;border-color:#444444;border-width:0px;"

    body = html_bf.find("body")
    body["style"] = "background-color:#333333;"
    html_new = str(html_bf)
    html.seek(0, 0)
    html.truncate()
    html.write(html_new)
    html.close()

注意,这里的div标签排序方式与你上面page里的添加顺序一致,同时覆盖顺序也一致(最后添加的在最上层)。
然后在项目文件夹里选择 2019-nCov 数据一览.html 选择浏览器打开就好啦!

最后贴出完整代码(复制可用的那种):
(前提是下载世界各国中英文对照.xlsx并和该程序放在同一文件夹里)(链接在后面)

import json
import requests
import pandas as pd
from pyecharts.charts import *
from pyecharts import options as opts
from pyecharts.commons.utils import JsCode
from pyecharts.globals import ThemeType, ChartType
from bs4 import BeautifulSoup


# 抓取数据
reponse = requests.get('https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5').json()
data = json.loads(reponse['data'])

# 国内
lastUpdateTime = data['lastUpdateTime']

chinaTotal = data['chinaTotal']
chinaTotal['确诊'] = chinaTotal['confirm']
chinaTotal['疑似'] = chinaTotal['suspect']
chinaTotal['死亡'] = chinaTotal['dead']
chinaTotal['治愈'] = chinaTotal['heal']
del chinaTotal['confirm']
del chinaTotal['suspect']
del chinaTotal['dead']
del chinaTotal['heal']

sum = chinaTotal['确诊'] + chinaTotal['疑似'] + chinaTotal['死亡'] + chinaTotal['治愈']

chinaAdd = data['chinaAdd']
chinaAdd['新增确诊'] = data['chinaDayAddList'][-1]['confirm']
chinaAdd['新增疑似'] = data['chinaDayAddList'][-1]['suspect']
chinaAdd['新增死亡'] = data['chinaDayAddList'][-1]['dead']
chinaAdd['新增治愈'] = data['chinaDayAddList'][-1]['heal']
del chinaAdd['confirm']
del chinaAdd['suspect']
del chinaAdd['dead']
del chinaAdd['heal']

areaTree = data['areaTree']

china_data = areaTree[0]['children']
china_list = []
for x in range(len(china_data)):
    province = china_data[x]['name']
    province_list = china_data[x]['children']
    for y in range(len(province_list)):
        city = province_list[y]['name']
        total = province_list[y]['total']
        today = province_list[y]['today']
        china_dict = {'province': province, 'city': city, 'total': total, 'today': today}
        china_list.append(china_dict)

# 定义数据处理函数
def confirm(x):
    confirm = eval(str(x))['confirm']
    return confirm


def suspect(x):
    suspect = eval(str(x))['suspect']
    return suspect


def dead(x):
    dead = eval(str(x))['dead']
    return dead


def heal(x):
    heal = eval(str(x))['heal']
    return heal

china_data = pd.DataFrame(china_list)
china_data.head()

# 函数映射
china_data['confirm'] = china_data['total'].map(confirm)
china_data['suspect'] = china_data['total'].map(suspect)
china_data['dead'] = china_data['total'].map(dead)
china_data['heal'] = china_data['total'].map(heal)
china_data['addconfirm'] = china_data['today'].map(confirm)
china_data['addsuspect'] = china_data['today'].map(suspect)
china_data['adddead'] = china_data['today'].map(dead)
china_data['addheal'] = china_data['today'].map(heal)
china_data = china_data[
    ["province", "city", "confirm", "suspect", "dead", "heal", "addconfirm", "addsuspect", "adddead", "addheal"]]
china_data.head()

# 国际数据处理
global_data = pd.DataFrame(data['areaTree'])
global_data['confirm'] = global_data['total'].map(confirm)
global_data['suspect'] = global_data['total'].map(suspect)
global_data['dead'] = global_data['total'].map(dead)
global_data['heal'] = global_data['total'].map(heal)
global_data['addconfirm'] = global_data['today'].map(confirm)
global_data['addsuspect'] = global_data['today'].map(suspect)
global_data['adddead'] = global_data['today'].map(dead)
global_data['addheal'] = global_data['today'].map(heal)
world_name = pd.read_excel("世界各国中英文对照.xlsx")
global_data = pd.merge(global_data, world_name, left_on="name", right_on="中文", how="inner")
global_data = global_data[
    ["name", "英文", "confirm", "suspect", "dead", "heal", "addconfirm", "addsuspect", "adddead", "addheal"]]
global_data.head()

# 日数据处理
chinaDayList = pd.DataFrame(data['chinaDayList'])
chinaDayList = chinaDayList[['date', 'confirm', 'suspect', 'dead', 'heal']]
chinaDayList.head()

# 日新增数据处理
chinaDayAddList = pd.DataFrame(data['chinaDayAddList'])
chinaDayAddList = chinaDayAddList[['date', 'confirm', 'suspect', 'dead', 'heal']]
chinaDayAddList.head()

# 数据可视化

# 饼图
total_pie = (
    Pie(init_opts=opts.InitOpts(theme=ThemeType.LIGHT, width='500px', height='350px', bg_color="transparent"))
        .add("", [list(z) for z in zip(['确     诊  ', '疑     似  ', '死     亡  ', '治     愈  '], chinaTotal.values())],
             center=["50%", "60%"], radius=[75, 100], )
        .add("", [list(z) for z in zip(chinaAdd.keys(), chinaAdd.values())], center=["50%", "60%"], radius=[0, 50])
        .set_global_opts(title_opts=opts.TitleOpts(title="全国总量", pos_bottom=0,
                                                   title_textstyle_opts=opts.TextStyleOpts(color="#00FFFF")),
                         legend_opts=opts.LegendOpts(textstyle_opts=opts.TextStyleOpts(color="#FFFFFF")))
        .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{c}")))

# 全球疫情地图
world_map = (
    Map(init_opts=opts.InitOpts(theme=ThemeType.WESTEROS))
        .add("", [list(z) for z in zip(list(global_data["英文"]), list(global_data["confirm"]))], "world",
             is_map_symbol_show=False)
        .set_series_opts(label_opts=opts.LabelOpts(is_show=False),
                         toolbox_opts=opts.ToolboxOpts(orient='vertical', pos_right="10%"))
        .set_global_opts(visualmap_opts=opts.VisualMapOpts(is_piecewise=True, background_color="transparent",
                                                           textstyle_opts=opts.TextStyleOpts(color="#F5FFFA"),
                                                           pieces=[
                                                               {"min": 101, "label": '>100', "color": "#893448"},
                                                               {"min": 10, "max": 100, "label": '10-100',
                                                                "color": "#fb8146"},
                                                               {"min": 1, "max": 9, "label": '1-9',
                                                                "color": "#fff2d1"},
                                                           ])))

# 中国疫情地图绘制
# 数据处理
area_data = china_data.groupby("province")["confirm"].sum().reset_index()
area_data.columns = ["province", "confirm"]

area_map = (
    Map(init_opts=opts.InitOpts(theme=ThemeType.WESTEROS))
        .add("", [list(z) for z in zip(list(area_data["province"]), list(area_data["confirm"]))], "china",
             is_map_symbol_show=False, label_opts=opts.LabelOpts(color="#fff"),
             tooltip_opts=opts.TooltipOpts(is_show=True), zoom=1.2, center=[105, 30])
        .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
        .set_global_opts(title_opts=opts.TitleOpts(title="中国疫情分布图", pos_top='5%',
                                                   title_textstyle_opts=opts.TextStyleOpts(color="#FF0000")),
                         visualmap_opts=opts.VisualMapOpts(is_piecewise=True, pos_right=0, pos_bottom=0,
                                                           textstyle_opts=opts.TextStyleOpts(color="#F5FFFA"),
                                                           pieces=[
                                                               {"min": 1001, "label": '>1000', "color": "#893448"},
                                                               {"min": 500, "max": 1000, "label": '500-1000',
                                                                "color": "#ff585e"},
                                                               {"min": 101, "max": 499, "label": '101-499',
                                                                "color": "#fb8146"},
                                                               {"min": 10, "max": 100, "label": '10-100',
                                                                "color": "#ffb248"},
                                                               {"min": 0, "max": 9, "label": '0-9',
                                                                "color": "#fff2d1"}])))

city_data = china_data.groupby('city')['confirm'].sum().reset_index()
city_data.columns = ["city", "confirm"]

def is_city(item):
    '''
    判断一个城市能否在Geo地图上被找到
    :param item: 城市名
    :return: T/F
    '''

    lists_1 = []
    lists_1.append(item)
    lists_2 = [10]
    geo = Geo()
    geo.add_schema(maptype="china")
    try:
        geo.add("确诊城市", [list(z) for z in zip(lists_1, lists_2)])
        return True
    except TypeError as e:
        return False


city_index = []
i = 0
for item in city_data['city']:
    if is_city(item) == False:
        city_index.append(i)
    i += 1

for x in city_index:
    del (city_data['city'][x])
    del (city_data['confirm'][x])

city_index_ = []
i = 0
for item in city_data['confirm']:
    if item > 1000:
        city_index_.append(i)
    i += 1

serious_city = []  # 严重城市
serious_submit = []  # 严重人数
for y in city_index_:
    serious_city.append(list(city_data['city'])[y])
    serious_submit.append(list(city_data['confirm'])[y])

list_1 = ["拉萨"]
list_2 = [1]

area_heat_geo = (
    Geo(init_opts=opts.InitOpts(theme=ThemeType.WESTEROS, bg_color='transparent'))
        .add_schema(maptype="china", zoom=1.2, center=[105, 30])
        .add("确诊城市", [list(z) for z in zip(list(city_data["city"]), list(city_data["confirm"]))], symbol_size=10)
        .add("确诊城市", [list(z) for z in zip(list_1, list_2)], symbol_size=10)  # 孤独拉萨
        .add("确诊城市", [list(z) for z in zip(list(serious_city), list(serious_submit))],  # 感染者超1000的城市
             type_=ChartType.EFFECT_SCATTER, effect_opts=opts.EffectOpts(is_show=True, color="black",
                                                                         symbol_size=30, scale=4, period=1))
        .add("", [list(z) for z in zip(list(city_data["city"]), list(city_data["confirm"]))],
             type_=ChartType.HEATMAP)
        .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
        .set_global_opts(
        visualmap_opts=opts.VisualMapOpts(range_size=[0, 25, 50, 75, 100], max_=1000, orient='horizontal',
                                          pos_bottom=0),
        title_opts=opts.TitleOpts(title="中国疫情分布热图", pos_top='5%'),
        legend_opts=opts.LegendOpts(pos_bottom='10%', pos_left=0)))

# 每日数据趋势
line = (
    Line(init_opts=opts.InitOpts(theme=ThemeType.CHALK, bg_color="transparent"))
        .add_xaxis(list(chinaDayList["date"]))
        .add_yaxis("累计确诊               ", list(chinaDayList["confirm"]), is_smooth=True, yaxis_index=1)
        .add_yaxis("累计疑似               ", list(chinaDayList["suspect"]), is_smooth=True, yaxis_index=1)
        .add_yaxis("累计死亡               ", list(chinaDayList["dead"]), is_smooth=True, yaxis_index=1)
        .add_yaxis("累计治愈", list(chinaDayList["heal"]), is_smooth=True, yaxis_index=1)
        .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
        .set_global_opts(legend_opts=opts.LegendOpts(pos_left='center')))

bar = (
    Bar(init_opts=opts.InitOpts(theme=ThemeType.CHALK, bg_color="transparent"))
        .add_xaxis(list(chinaDayAddList["date"]))
        .add_yaxis("单日确诊               ", list(chinaDayAddList["confirm"]))
        .add_yaxis("单日疑似               ", list(chinaDayAddList["suspect"]))
        .add_yaxis("单日死亡               ", list(chinaDayAddList["dead"]))
        .add_yaxis("单日治愈", list(chinaDayAddList["heal"]))
        .extend_axis(yaxis=opts.AxisOpts(axislabel_opts=opts.LabelOpts(formatter="{value}")))
        .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
        .set_global_opts(legend_opts=opts.LegendOpts(pos_left='center'),
                         yaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(formatter="{value}")),
                         datazoom_opts=opts.DataZoomOpts())).overlap(line)

big_title = (
    Pie()
        .set_global_opts(
        title_opts=opts.TitleOpts(title="2019-nCov",
                                  title_textstyle_opts=opts.TextStyleOpts(font_size=40, color='#FFFFFF',
                                                                          border_radius=True, border_color="white"),
                                  pos_top=0)))

times = (
    Pie()
        .set_global_opts(
        title_opts=opts.TitleOpts(subtitle=("截至 " + lastUpdateTime),
                                  subtitle_textstyle_opts=opts.TextStyleOpts(font_size=13, color='#FFFFFF'),
                                  pos_top=0))
)

confirms = (Pie().
            set_global_opts(title_opts=opts.TitleOpts(title="确诊", pos_left='center', pos_top='center',
                                                      title_textstyle_opts=opts.TextStyleOpts(color='#FFFFFF'))))
confirms_people = (Pie().
                   set_global_opts(title_opts=opts.TitleOpts(title=(str(chinaTotal['确诊']) + "   "),
                                                             pos_top='15%', pos_left='center',
                                                             subtitle=("         新增: " + str(chinaAdd['新增确诊'])),
                                                             item_gap=1,
                                                             title_textstyle_opts=opts.TextStyleOpts(color="#00FFFF",
                                                                                                     font_size=30),
                                                             subtitle_textstyle_opts=opts.TextStyleOpts(color="#00BFFF")
                                                             )))
suspects = (Pie().
            set_global_opts(title_opts=opts.TitleOpts(title="疑似", pos_left='center', pos_top='center',
                                                      title_textstyle_opts=opts.TextStyleOpts(color='#FFFFFF'))))
suspects_people = (Pie().
                   set_global_opts(title_opts=opts.TitleOpts(title=(str(chinaTotal['疑似']) + "   "),
                                                             pos_top='15%', pos_left='center',
                                                             subtitle=("         新增 :" + str(chinaAdd['新增疑似'])),
                                                             item_gap=1,
                                                             title_textstyle_opts=opts.TextStyleOpts(color="#FF00FF",
                                                                                                     font_size=30),
                                                             subtitle_textstyle_opts=opts.TextStyleOpts(color="#EE82EE")
                                                             )))
deads = (Pie().
         set_global_opts(title_opts=opts.TitleOpts(title="死亡", pos_left='center', pos_top='center',
                                                   title_textstyle_opts=opts.TextStyleOpts(color='#FFFFFF'))))
deads_people = (Pie().
                set_global_opts(title_opts=opts.TitleOpts(title=(str(chinaTotal['死亡']) + "   "),
                                                          pos_top='15%', pos_left='center',
                                                          subtitle=("         新增 :" + str(chinaAdd['新增死亡'])),
                                                          item_gap=1,
                                                          title_textstyle_opts=opts.TextStyleOpts(color="#FF0000",
                                                                                                  font_size=30),
                                                          subtitle_textstyle_opts=opts.TextStyleOpts(color="#F08080")
                                                          )))
heals = (Pie().
         set_global_opts(title_opts=opts.TitleOpts(title="治愈", pos_left='center', pos_top='center',
                                                   title_textstyle_opts=opts.TextStyleOpts(color='#FFFFFF'))))
heals_people = (Pie().
                set_global_opts(title_opts=opts.TitleOpts(title=(str(chinaTotal['治愈']) + "   "),
                                                          pos_top='15%', pos_left='center',
                                                          subtitle=("         新增 :" + str(chinaAdd['新增治愈'])),
                                                          item_gap=1,
                                                          title_textstyle_opts=opts.TextStyleOpts(color="#00FF00",
                                                                                                  font_size=30),
                                                          subtitle_textstyle_opts=opts.TextStyleOpts(color="#98FB98")
                                                          )))

confirm_liquid = (
    Liquid()
        .add("确诊比例", [chinaTotal['确诊'] / sum], tooltip_opts=opts.TooltipOpts(),
             label_opts=opts.LabelOpts(color="#00FFFF",
                                       font_size=15,
                                       formatter=JsCode(
                                           """function (param) {
                     return (Math.floor(param.value * 10000) / 100) + '%';
                 }"""
                                       ),
                                       position="inside",
                                       ),
             )
)

suspect_liquid = (
    Liquid()
        .add("疑似比例", [chinaTotal['疑似'] / sum], tooltip_opts=opts.TooltipOpts(),
             label_opts=opts.LabelOpts(color="#FF00FF",
                                       font_size=15,
                                       formatter=JsCode(
                                           """function (param) {
                     return (Math.floor(param.value * 10000) / 100) + '%';
                 }"""
                                       ),
                                       position="inside",
                                       ),
             )
)

dead_liquid = (
    Liquid()
        .add("死亡比例", [chinaTotal['死亡'] / sum], tooltip_opts=opts.TooltipOpts(),
             label_opts=opts.LabelOpts(color="#FF0000",
                                       font_size=15,
                                       formatter=JsCode(
                                           """function (param) {
                     return (Math.floor(param.value * 10000) / 100) + '%';
                 }"""
                                       ),
                                       position="inside",
                                       ),
             )
)

heal_liquid = (
    Liquid()
        .add("治愈比例", [chinaTotal['治愈'] / sum], tooltip_opts=opts.TooltipOpts(),
             label_opts=opts.LabelOpts(color="#00FF00",
                                       font_size=15,
                                       formatter=JsCode(
                                           """function (param) {
                     return (Math.floor(param.value * 10000) / 100) + '%';
                 }"""
                                       ),
                                       position="inside",
                                       ),
             )
)

wc = (
    WordCloud()
        .add("", [list(z) for z in zip(list(city_data["city"]), list(city_data["confirm"]))],
             word_gap=0, word_size_range=[10, 30]))

# 图片汇总

# page = (Page(page_title="2019-nCov",layout=Page.DraggablePageLayout)
page = (Page(page_title="2019-nCov")
        .add(world_map)
        .add(total_pie)
        .add(area_map)
        .add(area_heat_geo)
        .add(bar)
        .add(big_title)
        .add(times)
        .add(confirms)
        .add(confirms_people)
        .add(suspects)
        .add(suspects_people)
        .add(deads)
        .add(deads_people)
        .add(heals)
        .add(heals_people)
        .add(confirm_liquid)
        .add(suspect_liquid)
        .add(dead_liquid)
        .add(heal_liquid)
        .add(wc)
        ).render("2019-nCoV 数据一览.html")
with open("2019-nCov 数据一览.html", "r+", encoding='utf-8') as html:
    html_bf = BeautifulSoup(html, 'lxml')
    divs = html_bf.select('.chart-container')
    divs[0][
        "style"] = "width:605px;height:274px;position:absolute;top:36px;left:333px;border-style:solid;border-color:#444444;border-width:0px;"
    divs[1][
        'style'] = "width:411px;height:303px;position:absolute;top:5px;left:0px;border-style:solid;border-color:#444444;border-width:0px;"
    divs[2][
        "style"] = "width:309px;height:405px;position:absolute;top:313px;left:961px;border-style:solid;border-color:#444444;border-width:0px;"
    divs[3][
        "style"] = "width:305px;height:405px;position:absolute;top:310px;left:0px;border-style:solid;border-color:#444444;border-width:0px;"

    divs[4][
        "style"] = "width:646px;height:304px;position:absolute;top:312px;left:312px;border-style:solid;border-color:#444444;border-width:0px;"
    divs[5][
        "style"] = "width:250px;height:55px;position:absolute;top:2px;left:440px;border-style:solid;border-color:#444444;border-width:0px;"
    divs[6][
        "style"] = "width:200px;height:30px;position:absolute;top:11px;left:675px;border-style:solid;border-color:#444444;border-width:0px;"

    divs[7][
        'style'] = "width:60px;height:75px;position:absolute;top:5px;left:1060px;border-style:solid;border-color:#DC143C;border-width:3px;border-radius:25px 0px 0px 0px"
    divs[8][
        "style"] = "width:130px;height:75px;position:absolute;top:5px;left:1120px;border-style:solid;border-color:#DC143C;border-width:3px;"
    divs[9][
        "style"] = "width:60px;height:75px;position:absolute;top:80px;left:1060px;border-style:solid;border-color:#DC143C;border-width:3px;"
    divs[10][
        "style"] = "width:130px;height:75px;position:absolute;top:80px;left:1120px;border-style:solid;border-color:#DC143C;border-width:3px;"
    divs[11][
        "style"] = "width:60px;height:75px;position:absolute;top:155px;left:1060px;border-style:solid;border-color:#DC143C;border-width:3px;"
    divs[12][
        "style"] = "width:130px;height:75px;position:absolute;top:155px;left:1120px;border-style:solid;border-color:#DC143C;border-width:3px;"
    divs[13][
        "style"] = "width:60px;height:75px;position:absolute;top:230px;left:1060px;border-style:solid;border-color:#DC143C;border-width:3px;"
    divs[14][
        "style"] = "width:130px;height:75px;position:absolute;top:230px;left:1120px;border-style:solid;border-color:#DC143C;border-width:3px;border-radius:0px 0px 25px 0px"

    divs[15][
        "style"] = "width:160px;height:160px;position:absolute;top:-35px;left:920px;border-style:solid;border-color:#444444;border-width:0px;"
    divs[16][
        "style"] = "width:160px;height:160px;position:absolute;top:40px;left:865px;border-style:solid;border-color:#444444;border-width:0px;"
    divs[17][
        "style"] = "width:160px;height:160px;position:absolute;top:115px;left:920px;border-style:solid;border-color:#444444;border-width:0px;"
    divs[18][
        "style"] = "width:160px;height:160px;position:absolute;top:188px;left:865px;border-style:solid;border-color:#444444;border-width:0px;"
    divs[19][
        "style"] = "width:1280px;height:120px;position:absolute;top:600px;left:0px;border-style:solid;border-color:#444444;border-width:0px;"

    body = html_bf.find("body")
    body["style"] = "background-color:#333333;"
    html_new = str(html_bf)
    html.seek(0, 0)
    html.truncate()
    html.write(html_new)
    html.close()

然后程序里面用到的世界各国中英文对照.xlsx
链接:https://pan.baidu.com/s/1t4TjgEMPv8kzkvJY-h5ujA
提取码:8bvl

看看在我家“大屏”上的效果:
在这里插入图片描述
在这里插入图片描述

最后再次向全国抗疫的国内外各行各业的人士致敬!

武汉加油!

.
.
.
.
.
.
.
.
.
.

PS:

几天没看,今天又看了看,发现这个不能用了,因为TX页面改了,添加删除了一些东西(比如把确诊分为现存和累计等…),所以我就又改了改,把新增的那些数据补了上去,还有就是把正中央的那个柱状图折线图混合改成了轮播图,这样看着更清晰,再者就是改了个名(原来叫 2019-nCov 我写了那篇文章那天WHO定名 COVID-19 我也就没改… )
新的在这里:

pyecharts实现新冠肺炎疫情可视化并搭建BI数据大屏(Plus)

发布了20 篇原创文章 · 获赞 10 · 访问量 1217

猜你喜欢

转载自blog.csdn.net/qq_43613793/article/details/104268536