Python爬取疫情数据并预测及其可视化

摘  要

进几年,疫情袭击了我们所有人的生活。面对生活中突如其来的灾难,每个人都在心里说:“生活竟变得如此。”在短暂的萧条之后,人们意识到,无论生活多么艰难,生活都必须继续。然而,随着互联网的不断发展,计算机行业的许多员工不再满足于他们无法控制的目标,搜索引擎也不够清晰。网络爬虫是根据程序员设置的规则获取网络信息的程序或脚本,它的优点是不仅可以从网络上捕获和保存整个页面,另外,有很高的定制性。根据需要以能得到的数据形式限制爬虫类,除去不需要的部分,维持信息的效率。本文采用爬虫、AR模型以及pyrcharts技术,实现从百度上取疫情数据,并将数据用于训练模型,最后将模型的预测结果可视化展示

关键词: pycharm html 爬虫 数据分析可视化

章  绪  论

1.1 项目背景

随着时间的推移,信息已经成为一种重要的资源。大数据技术、互联网技术和数据库的不断发展和完善,大数据分析和提取提供了强有力的支持。随着节后返乡日期的临近,如何安全有序地掌握职工返乡的真实情况,有效规避二次传播风险,这已成为地方政府和企业的难题,是疫情初期建立起来的一套疫情防控管理体系,使人们及时掌握个人防疫信息资料、防疫资料的收集和使用,施工人员可以在任何时间、任何地点迅速报告有关预防个人传染病的信息。为提高数据存储和查询效率,促进疫情防控,防止疫情蔓延,本文章就是针对今年新冠肺炎疫情进行数据采集,并对获取的数据进行分析以及对未来七天的增长做出预测

1.2 开发环境与工

对于这次新冠肺炎疫情的采集与分析要用到数据的采集、清洗、处理、存储以及数据的可视化图表的展示,还包括一些Python爬虫技术、数据清洗处理技术、可视化分析技术,本项目使用的主要开发工具有Python,Pycharm,html超文本语言,第三方库 pandas、json、request以及pyecharts

1.3 python语法知识

全课设用python编译,因此必须熟悉python的语法。

1.4 python+html编程

为了使得课设的运行结果更加形象化,需生成html网页使得数据可视化。

1.5 网络爬虫技术

一般来说爬虫的流程包括以下几点:首先使用 Requests 发送网络请求,请求是由python 实现的非常简单的HTTP库。建议爬虫程序首先使用请求导入请求 requests 模块:import requests 然后获取响应内容,再解析内容被存储以用于进一步处理,最后保存数据,总的来说,通用网络爬虫的结构分为页面分析模块、页面滚动模块、URL列表、链接过滤模块、页面数据库和初始URL集。Pandas模块:import pandas as pd

Pandaspanda是一个Python数据分析包。Pandas是一个基于numpy的工具,旨在解决数据分析任务。Pandas提供了一个工具,将许多软件库和一些标准化数据模型结合起来,并有效地处理大型数据集。并且,它还提供了许多功能和方法可以迅速和简单地处理数据。主要作用是对Python数据进行开发。最初,它是用来分析财务数据的。因此,panda对时间序列分析有很好的支持,panda中还提供了数据面板类型,数据结构包括一个一维数组序列和一个二维数据集,可以转换和存储数据,并将列表转换为数据。

pandas是基于Numpy库的,可以说,pandas 库就是为数据分析而生的。

BeautifulSoup 模块:from bs4 import BeautifulSoup

Beautifusoup 提供了python的导航管理、研究、分析树修正等简单功能。简单来说,Beautiful dSoup可以作为工具箱来看。因为分析文件提供给程序员的数据非常简单,所以一般的用户不需要写代码,可以制作相对完整的程序。

系统将输入文档自动转换为Unicon代码,并将输出文档转换为UTF-8代码。现在需要说明原来的代码。作为优秀的Python-lxml和httml6lib分析器,漂亮的SOM为不同用户提供灵活的alibi或强力的速度战略。

1.6 可视化技术

数据显示是一种直观的、图形化的EM图形的形式表示。预览可以帮助我们更准确地发现数据背后的问题,更清晰地共享,实时关注数据变化。通过图形界面,企业可以直观地感知各种数据,为企业提供正确、及时的决策机制,提取和分析数据背后的价值和意义,提供有效的指导和参考。这个美国的项目主要是用几个EM钱包代码,清楚地显示了数据的变化。Information Viewer项目必须经过数据挖掘、数据处理、图形选择、可视化设计、可用性测试等过程。在数据显示过程中,DOS的主要设计包括需求分析、数据处理、图形选择、可视化设计、可用性测试等。设计师必须深入分析用户的真实需求,在数据显示阶段,设计师必须展示数据和分析的有效结果。在这个阶段,设计者必须设计用户评估组织,收集和分析用户测试的结果,并将其整合到需求优化的点上,并不断迭代优化显示。

第二章  课设实现过程

2.1 课设功能实现

自新冠肺炎(covid-19)疫情爆发以来,这场疫情几乎影响了每个人的生活,为了对疫情做数据分析,需要采集疫情的数据,本篇案例就基于python爬虫进行数据采集以及数据预测

首先我们需要找到合适的数据源,卫健委和各媒体每天都会报道新冠肺炎的疫情数据,如下图所示,因此我们可以考虑将这些网页作为数据源。

我们考虑将网络平台作为数据源,以网易的疫情播报平台为例,如下图所示可以看到它的数据内容非常丰富,不仅包括国内的数据,且作为大平台,公信度也比较高。因此我们选择网易的疫情实时动态播报平台作为数据源

我们基于网易的实时播报平台寻找数据,由于它是一个实时的动态平台,因此数据一般在Network标签下可以找到,以Chrome浏览器为例展示寻找数据步骤们抓取全国各省的实时数据,在areaTree键值对中,存放着各地的实时数据,areaTree是一个列表,每一个元素都是一个地区的数据,每一个元素的children是各省份的数据。 我们首先找到中国各省的实时数据逐个拆解数据,我们已经了解children为下一地级数据,我们只分析到省单位,因此各省的children数据不采集;extData为空值,也不采集,最后具体采集方法如下:

不需要采集的数据:children、extData。 需要采集的数据:由于数据中today和total嵌套着字典,因此不能直接获取,对于id、lastUpdateTime、name、可以直接取出为一个数据,today为一个数据,total为一个数据,最后三个数据合并为一个数据。

最后,用相关的数学模型以及爬取到的数据来预测未来七天的感染人数,将其写入HTML文本中,生成网页,将数据可视化并作出网页大屏展示。将结果显示的更加直白明显。

 2.2 html界面

2.3.可视化相应功能

制作可视化大屏展示,需要安装工具是基于flask实现的,所以需要安装flask,将代码写入可视化大屏模板下可运行,本文将全国各省疫情数据导入得出结论。

程序代码


import requests

import pyecharts.options as opts
from pyecharts.globals import ThemeType
from pyecharts.commons.utils import JsCode
from pyecharts.charts import Timeline, Grid, Bar, Map, Pie, Line
import datetime
from typing import List

from urllib import parse
from statsmodels.tsa.arima.model import ARIMA
url = "https://api.inews.qq.com/newsqa/v1/query/inner/publish/modules/list?modules=chinaDayList,chinaDayAddList,nowConfirmStatis,provinceCompare"
headers = {
    "Referer": "https://news.qq.com/",
    "Host": "api.inews.qq.com",
    "Origin": "https://news.qq.com",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36"
}
response = requests.post(url, headers=headers)
datas = eval(response.text)
datas = datas['data']['provinceCompare']
key = list(datas.keys())
provinceAdd = {}
for i in key:
    temp = []
    urls = "https://api.inews.qq.com/newsqa/v1/query/pubished/daily/list?province=%s&"
    URL = urls % (parse.quote(i))
    responseProvince = eval(requests.post(URL, headers=headers).text)[
        'data'][-30:-1]
    for j in responseProvince:
        temp.append(int(j['confirm_add']))
    provinceAdd[i] = temp
def AR(data):
    result = []
    for i in range(7):
        model = ARIMA(data, order=[2, 0, 1])
        model_fit = model.fit()
        yhat = round(model_fit.predict(len(data), len(data))[0])
        data.append(yhat)
        del data[0]
        result.append(yhat)
    return result
result = {}
for i in key:
    data = provinceAdd[i]
    result[i] = AR(data)
total_num = []
DATA = []
for i in range(7):
    temp = {}
    dates = datetime.date.today()+datetime.timedelta(days=i)
    temp["time"] = ("%s年%s月%s日" % (dates.year, dates.month, dates.day))
    temp['data'] = []
    num = 0
    for j in key:
        num = num+result[j][i]
    total_num.append(num)
    for j in key:
        temp_data = {}
        temp_data["name"] = j
        temp_data["value"] = [result[j][i], round(result[j][i]/num, 4), j]
        temp['data'].append(temp_data)
    DATA.append(temp)
time_list = [
    ("%s年%s月%s日" % ((datetime.date.today()+datetime.timedelta(days=d)).year, (datetime.date.today()+datetime.timedelta(days=d)).month, (datetime.date.today()+datetime.timedelta(days=d)).day)) for d in range(7)]
maxNum = 300
minNum = 0
def get_year_chart(year: str):
    map_data = [
        [[x["name"], x["value"]] for x in d["data"]] for d in DATA if d["time"] == year
    ][0]
    min_data, max_data = (minNum, maxNum)
    data_mark: List = []
    i = 0
    for x in time_list:
        if x == year:
            data_mark.append(total_num[i])
        else:
            data_mark.append("")
        i = i + 1
    map_chart = (
        Map()
        .add(
            series_name="",
            data_pair=map_data,
            zoom=1,
            center=[119.5, 34.5],
            is_map_symbol_show=False,
            itemstyle_opts={
                "normal": {"areaColor": "#323c48", "borderColor": "#404a59"},
                "emphasis": {
                    "label": {"show": Timeline},
                    "areaColor": "rgba(255,255,255, 0.5)",
                },
            },
        )
        .set_global_opts(
            title_opts=opts.TitleOpts(
                title="预测" + str(year) + "全国分地区新冠患病人数",
                subtitle="",
                pos_left="center",
                pos_top="top",
                title_textstyle_opts=opts.TextStyleOpts(
                    font_size=25, color="rgba(255,255,255, 0.9)"
                ),
            ),
            tooltip_opts=opts.TooltipOpts(
                is_show=True,
                formatter=JsCode(
                    """function(params) {
                    if ('value' in params.data) {
                        return params.data.value[2] + ': ' + params.data.value[0];
                    }
                }"""
                ),
            ),
            visualmap_opts=opts.VisualMapOpts(
                is_calculable=True,
                dimension=0,
                pos_left="30",
                pos_top="center",
                range_text=["High", "Low"],
                range_color=["lightskyblue", "yellow", "orangered"],
                textstyle_opts=opts.TextStyleOpts(color="#ddd"),
                min_=min_data,
                max_=max_data,
            ),
        )
    )
    line_chart = (
        Line()
        .add_xaxis(time_list)
        .add_yaxis("", total_num)
        .add_yaxis(
            "",
            data_mark,
            markpoint_opts=opts.MarkPointOpts(
                data=[opts.MarkPointItem(type_="max")]),
        )
        .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
        .set_global_opts(
            title_opts=opts.TitleOpts(
                title="预测"+str(datetime.date.today())+"~"+str(datetime.timedelta(days=6))+"号全国新冠患者人数", pos_left="72%", pos_top="5%"
            )
        )
    )
    bar_x_data = [x[0] for x in map_data]
    bar_y_data = [{"name": x[0], "value": x[1][0]} for x in map_data]
    bar = (
        Bar()
        .add_xaxis(xaxis_data=bar_x_data)
        .add_yaxis(
            series_name="",
            y_axis=bar_y_data,
            label_opts=opts.LabelOpts(
                is_show=True, position="right", formatter="{b} : {c}"
            ),
        )
        .reversal_axis()
        .set_global_opts(
            xaxis_opts=opts.AxisOpts(
                max_=maxNum, axislabel_opts=opts.LabelOpts(is_show=False)
            ),
            yaxis_opts=opts.AxisOpts(
                axislabel_opts=opts.LabelOpts(is_show=False)),
            tooltip_opts=opts.TooltipOpts(is_show=False),
            visualmap_opts=opts.VisualMapOpts(
                is_calculable=True,
                dimension=0,
                pos_left="10",
                pos_top="top",
                range_text=["High", "Low"],
                range_color=["lightskyblue", "yellow", "orangered"],
                textstyle_opts=opts.TextStyleOpts(color="#ddd"),
                min_=min_data,
                max_=max_data,
            ),
        )
    )
    pie_data = [[x[0], x[1][0]] for x in map_data]
    pie = (
        Pie()
        .add(
            series_name="",
            data_pair=pie_data,
            radius=["15%", "35%"],
            center=["80%", "82%"],
            itemstyle_opts=opts.ItemStyleOpts(
                border_width=1, border_color="rgba(0,0,0,0.3)"
            ),
        )
        .set_global_opts(
            tooltip_opts=opts.TooltipOpts(is_show=True, formatter="{b} {d}%"),
            legend_opts=opts.LegendOpts(is_show=False),
        )
    )
    grid_chart = (
        Grid()
        .add(
            bar,
            grid_opts=opts.GridOpts(
                pos_left="10", pos_right="45%", pos_top="50%", pos_bottom="5"
            ),
        )
        .add(
            line_chart,
            grid_opts=opts.GridOpts(
                pos_left="65%", pos_right="80", pos_top="10%", pos_bottom="50%"
            ),
        )
        .add(pie, grid_opts=opts.GridOpts(pos_left="45%", pos_top="60%"))
        .add(map_chart, grid_opts=opts.GridOpts())
    )
    return grid_chart
if __name__ == "__main__":
    timeline = Timeline(
        init_opts=opts.InitOpts(
            width="1800px", height="900px", theme=ThemeType.DARK)
    )
    for y in time_list:
        g = get_year_chart(year=y)
        timeline.add(g, time_point=str(y))
    timeline.add_schema(
        orient="vertical",
        is_auto_play=True,
        is_inverse=True,
        play_interval=5000,
        pos_left="null",
        pos_right="5",
        pos_top="20",
        pos_bottom="20",
        width="60",
        label_opts=opts.LabelOpts(is_show=True, color="#fff"),
    )
    timeline.render("预测结果.html")

猜你喜欢

转载自blog.csdn.net/m0_54570435/article/details/130399951