requests+pyecharts爬取疫情数据并绘制各种图

文中有些代码出现了render是因为该函数是在Django框架下写的

一、国内省份疫情

1、获取百度接口数据
def getData():
    """爬虫获取数据"""
    url = "https://voice.baidu.com/newpneumonia/get?target=trend&isCaseIn=0&stage=publish&&qq-pf-to=pcqq.groupnewpneumonia"
    # 请求头,作用:伪装成浏览器反爬虫(虽然这个链接就是用来爬的)
    headers = {
        'user-agent': 'User-Agent: Mozilla/5.0 (Windows NT 10.0 Win64 x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36',
    }
    # 这个网址请求方式为get
    r = requests.get(url, headers)
    info = json.loads(r.text)
    data = info["data"]

    # 遍历省份,将所有省份的名字按序存储到name_list
    for i in range(len(data)):
        name = data[i]["name"]
        name_list.append(name)

    return data

其中的data结构就是这样的。
在这里插入图片描述

2、对该省份数据进行处理,使之能用于pyecharts

下面的代码除了正常的从json中提取所需日期、省份的数据外,也对某些日期没有上报疫情信息的情况做了try-except异常处理(因为港澳台等地的信息更新不及时)。处理思想如下:
(1)如果是当天信息没有上报才导致的日期列表没有该日期,那就用二分法找前一个有上报信息的日期,代码如下

def BinarySearch(array_strlist, t):
    """
    二分法找不存在的日期的前一个日期的索引
    :param array_strlist:
    :param t:
    :return:
    """
    mid = 0
    array = [int(float(x) * 100) for x in array_strlist]
    low = 0
    height = len(array) - 1
    while low < height:
        mid = (low + height) // 2
        if array[mid] < t:
            low = mid + 1

        elif array[mid] > t:
            height = mid - 1
    # else:
    #     return array[mid]

    return mid - 1

(2)如果是因为不存在日期2.30、2.31,也不告诉用户该日期不合法,直接就用前1天或前2天的数据顶上。下面是处理出具体的每个省份、日期下的疫情数据的代码

def getSpecial(data, date, kind="新增"):
    """
    获取具体的每个省份、日期下的疫情数据
    :param kind:
    :param data:    getData函数返回的数据(字典类型)
    :param date:    要显示的日期
    :return:        返回指定指定日期的数据
    """
    province_info = {}
    
    # 获取想要的日期的下标(因为除港澳台等地,各个省的信息的日期都一样,干脆用第一个北京的日期列表找索引)
    try:
        idx = data[0]["trend"]["updateDate"].index(date)
    except:
    	# 如果当天不存在(这里不是没有上报,而是如2月没有30号、31号的情况),那就用前1天或前2天的数据顶上
    	# 这里的算法确实没有考虑告诉用户该日期不合法,稍微粗糙一些
        try:
            date_list = date.split('.')
            date_list[1] = str(int(date_list[1]) - 1)
            idx = data[0]["trend"]["updateDate"].index(".".join(date_list))
        except:
            date_list = date.split('.')
            date_list[1] = str(int(date_list[1]) - 2)
            idx = data[0]["trend"]["updateDate"].index(".".join(date_list))

    # 
    for i in range(len(data)):
        if kind == "确诊":
            # 想要的日期下 确诊人数
            try:
                confirm = data[i]["trend"]["list"][0]["data"][idx]
            except:
                old_date_idx = BinarySearch(data[i]["trend"]["list"][0]["data"], int(float(date) * 100))
                confirm = data[i]["trend"]["list"][0]["data"][old_date_idx]
            province_info.update({data[i]["name"]: confirm})

        if kind == "治愈":
            # 想要的日期下 治愈人数
            try:
                cured = data[i]["trend"]["list"][1]["data"][idx]
            except:
                old_date_idx = BinarySearch(data[i]["trend"]["list"][1]["data"], int(float(date) * 100))
                cured = data[i]["trend"]["list"][1]["data"][old_date_idx]
            province_info.update({data[i]["name"]: cured})

        if kind == "死亡":
            # 想要的日期下 死亡人数
            try:
                death = data[i]["trend"]["list"][2]["data"][idx]
            except:
                old_date_idx = BinarySearch(data[i]["trend"]["list"][2]["data"], int(float(date) * 100))
                death = data[i]["trend"]["list"][2]["data"][old_date_idx]
            province_info.update({data[i]["name"]: death})

        if kind == "新增":
            # 想要的日期下 新增确诊人数
            try:
                newConfirm = data[i]["trend"]["list"][3]["data"][idx]
            except:
                newConfirm = 0
            province_info.update({data[i]["name"]: newConfirm})

    return province_info
3、写一个初始化pyecharts地图函数
def map_init(date=None, kind="新增"):
    """
    初始化map并返回,被display和lunbo引用
    :param date:    日期,默认为None
    :return:
    """
    # maptype='china' 只显示全国直辖市和省级
    map_ = Map()
    map_.set_global_opts(
        title_opts=opts.TitleOpts(title=f"2020{date}中国疫情{kind}地图"),
        visualmap_opts=opts.VisualMapOpts(max_=3600, is_piecewise=True,
                                          pieces=[
                                              {"max": 5000, "min": 1001, "label": ">1000", "color": "#8A0808"},
                                              {"max": 1000, "min": 500, "label": "500-1000", "color": "#B40404"},
                                              {"max": 499, "min": 100, "label": "100-499", "color": "#DF0101"},
                                              {"max": 99, "min": 10, "label": "10-99", "color": "#F78181"},
                                              {"max": 9, "min": 1, "label": "1-9", "color": "#F5A9A9"},
                                              {"max": 0, "min": 0, "label": "0", "color": "#FFFFFF"},
                                          ], ),  # 最大数据范围,分段
    )
    return map_
4、绘制各省份的 确诊/死亡/治愈/新增 疫情地图

显示函数是:

def display(province_distribution, date, kind="新增"):
    """
    全国地图-非轮播图
    :param kind:
    :param province_distribution:    省和直辖市
    :param date:
    :return:
    """

    map_ = map_init(date=date)

    map_.add(f"2020{date}中国疫情{kind}地图", data_pair=list(province_distribution.items()), maptype="china", is_roam=True)
    map_.render(f'2020{date}中国疫情地图.html')

调用函数为:

date = "7.29"
kind = "新增"

# 获取全国各省份数据(种类可选有:确诊/死亡/治愈/新增)
province_distribution = getSpecial(data, date, kind)
# 展示全国地图
display(province_distribution, date, kind)
5、绘制各省份的 确诊/死亡/治愈/新增 疫情轮播地图

下面代码中加上了定到当前日期的功能,意味着你何时运行代码,就会不仅重新爬取数据,还会随着时间重新制作到当前时间的轮播图(下面写的是10天为步长,你可以修改)

def lunbo(data, kind="新增"):
    """
    全国地图-轮播图
    :param data:    同上
    :param kind:
    :return:
    """
    # maptype='china' 只显示全国直辖市和省级
    # 制作轮播
    timeline = Timeline()

    # map_list = []
    from datetime import datetime
    # 定到当月
    for month in range(2, datetime.now().month + 1):
        # 如果当月刚开始(还没到10天呢),
        for day in range(1, 31 if (month != datetime.now().month) else datetime.now().day, 10):
            nowDate = f"{month}.{day}"
            map_ = map_init(date=nowDate)
            province_distribution = getSpecial(data, nowDate, kind)
            map_.add(f"2020{month}{day}日中国疫情{kind}地图", data_pair=list(province_distribution.items()), maptype="china",
                     is_roam=True)
            timeline.add(map_, f"{month}{day}日")

	# 自动播放,播放延迟1s
    timeline.add_schema(is_auto_play=True, play_interval=1000)
    timeline.render("轮播.html")

调用函数为:

lunbo(data)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值