How to use Python to make the epidemic data into a line chart changes, following Part I "on the novel coronavirus pneumonia outbreak traced to visualize data collection, processing" supplement

This article is the second supplementary articles on the blog, the students do not know the original link here collected on novel coronavirus pneumonia outbreak traced to visualize data processing
The final renderings

Here Insert Picture Description
Some careful small partner told me after reading the blog post, although the data did grab a lot, but still missing a very important data - Daily epidemic trend data
First of all, thank you for your kindness and reminders encourage me! Thank you for your compliment to be able to look at my article!

In fact, grab the data and methods on the blog post mentioned is the same, read the small partners on when to refresh their memories pair of
Data Preparation: To grab the data, the natural need to find a data source has data, then find chant

So discovered Netease news provides a source of such data

url:https://news.163.com/special/epidemic/

Here Insert Picture Description

Open dry!
Data Collection: Part I and like to use Google's own browser developer tools for packet capture
Acquisition process: Part I and as open developer tools capture button, F5 to refresh the view packet, search the corresponding data
As shown, I direct searches for the first 93 data (but should pay attention to "the number of new diagnosed," because you look at the data, "the cumulative number of confirmed" in the can that "the number of new diagnosed" is adjacent to two the difference between a "cumulative number of confirmed" if the direct search, "the number of new diagnosed," then we are looking for may not be able to search for data packets, because "the number of new diagnosed" data can be completely calculated)

Here Insert Picture Description
但是在排查这些数据包发现,这些数据包太多了,很难找到。没关系,我们换一个数据,搜索“累计确诊人数”里的数据看看,以1975为例,发现只有一个搜索结果,如图
Here Insert Picture Description
查看其Response可以得知,这正是我们要找的数据包。
Here Insert Picture Description
刚开始我以为这是条json数据,心想这个json的成员名和之前的成员名都是一样的,可以直接套之前的代码了。可但我瞪大眼睛仔细看了看,这个成员们是没有引号括起来的,顿时一脸懵逼。(本人学识尚浅,还不清楚这个类型是什么,希望懂的小伙伴能够帮助在下,指点一二。)

但是处理这些数据我们可以通过截取字符串的方式将它处理掉。

之后我们看其Headers,提交方式为Get,而且凑巧的是,这个URL正是我们的数据源(我们不需要提交任何参数了)
Here Insert Picture Description

至此,数据采集完毕,进入代码环节。
数据处理:
由于这一次不需要处理json数据,所以我们只需要导入三个模块,然后写出返回Response的函数框架
  1. requests模块 (用于网页访问)
  2. re模块 (用于正则表达式,处理数据时需要)
  3. openpyxl (用于将数据生成excel表格)
import re
import requests
import openpyxl
url=r"https://news.163.com/special/epidemic/"#数据来源 网易
def GetHtmlText(url):
    kv = {'user-agent': 'Mozilla/5.0'}#用于修改头部信息,破除其网站对应的反爬虫机制
    try:
        res=requests.get(url,timeout =30,headers = kv)
        res.raise_for_status()
        res.encoding=res.apparent_encoding
        return res.text
    except:
        return "Error"

此处的代码与之前有些不同,这里的requests.get()语句接受了一条headers的参数,之所以这样做是因为有一些网站有反爬虫机制的,Python在使用requests爬取资源时,其头部信息headers中为:
Here Insert Picture Description
其User-Agent字段的信息为python-requests/2.22.0,所以一些反爬虫机制就会通过一信息使你的访问变得错误,导致数据爬取失败。(这就相当于你想要偷别人家东西时,向别人大喊我是小偷,不抓你抓谁)这时我们就可以通过修改User-Agent字段的信息将自己伪装起来,其中Mozilla/5.0是一个标准的浏览器身份标识字段。(小偷:“我是良民啊!”,于是主人将信将疑的让你溜了)
但网易新闻并未设置这样的机制,写这个只是因为最近学到了这个知识,一方面是让自己巩固知识,一方面也是想顺便提醒大家。

继续我们的代码

由于不清楚之前那个类似于json的数据是什么,不知道如何解析,所以我只想到了一个笨方法,用提取中间文本的方式,提取出这些数据。函数如下:

def GetTextCenter(Text,TextLeft,TextRight):#取出中间文本
    L = Text.find(TextLeft) + len(TextLeft)
    Text = Text[L:]
    R = Text.find(TextRight)
    return Text[:R]
原理:Python对字符串的find操作,可以找出需要查找字符的索引位置,而字符串是可以索引值来进行截取的,我们利用这些知识,就可以实现提取中间文本了
开始我们的字符串数据处理环节

首先利用之前我们定义的函数框架来Get一下我们的URL,将其获取的信息打印出来。

Html=GetHtmlText(url)
print(Html)

找到我们需要的数据
Here Insert Picture Description
先把中括号中的内容提取出来,这样我们就可以利用我们定义的GetTextCenter函数来获取初步我们需要的信息了。

Html_data=GetTextCenter(Html,r"window.data_by_date = [",r","+"\n"+r"]")

然后我们print一下Html_data,看其数据
Here Insert Picture Description
(看到这个我真想把data,confirm等全都加一个双引号)
虽然它不是json数据,但是我们也可以一样先用正则提取出每一条花括号的内容

Data_list=re.findall(r"{[^}]+}",Html_data)

数据即将处理完成,我们还需要处理一点小细节,你看这个confirm_added: 93,显然,这是第一个日期增加的数据,之后的每个日期,应该都是利用其他数据相减得出的结果。(印证了之前的猜想),现在我们要做的工作是将这个confirm_added: 93连同它之前的逗号都删去。
我们不妨定义一个函数,找到这个这个与众不同的字符串列表所在的位置,就直接命名为找不同吧

def Find_Different(list):
    for i in range(0,len(list)):
        n = list[i].find(r", confirm_added")
        if (n != -1):
            return [i,n]#由于需要返回两个数据,所以在此返回一个列表,i表示列表的索引,n表示出现该字符串的首位置

然后根据这个位置,将其多余的部分截取掉。

value = Find_Different(Data_list)
Data_list[value[0]] = Data_list[value[0]][:value[1]] + "}"  #截取字符串

接着我们遍历一遍Data_list,看看有没有变化

for each in Data_list:
    print(each)

可见已经成功了
Here Insert Picture Description

接下来的工作就是将这些字段的数据提取出来了

这里可以像之前一样,直接声明列表来储存数据,也可以像这样,用一个类来储存

class item:
    def __init__(self):
        self.data=list()
        self.confirm=list()
        self.suspect=list()
        self.heal=list()
        self.dead=list()
Data_Box = item()
for i in range(0,len(Data_list)):#将数据提取出来
    Data_Box.data.append(GetTextCenter(Data_list[i],r'{date: "',r'",'))#获取日期
    Data_Box.confirm.append(GetTextCenter(Data_list[i],r"confirm: ",r", "))#获取确诊人数
    Data_Box.suspect.append(GetTextCenter(Data_list[i],r"suspect: ",r", "))#获取疑似人数
    Data_Box.heal.append(GetTextCenter(Data_list[i],r"heal: ",r", "))#获取治愈人数
    Data_Box.dead.append(GetTextCenter(Data_list[i],r"dead: ",r"}"))#获取死亡人数
最后,将数据保存至Excel中
for i in range(0,len(Data_list)):
    ws.cell(i + 2, 1, Data_Box.data[i].replace(".","\\"))
    ws.cell(i + 2, 2, int(Data_Box.confirm[i]))
    ws.cell(i + 2, 3, int(Data_Box.suspect[i]))
    ws.cell(i + 2, 4, int(Data_Box.heal[i]))
    ws.cell(i + 2, 5, int(Data_Box.dead[i]))
wb.save("date_data.xlsx")
至此,数据处理阶段结束

将数据可视化

由于在上一篇博客中,有说明如何将数据导入FineBI可视化平台中,所以本次跳过这些步骤,直接以创建折线图为例。

准备工作

  1. 导入刚刚生成的Excel数据
  2. 新建一个仪表板
  3. 添加组件
  4. 在“我的自助数据集”中选中刚刚导入的Excel数据后,点击确定

创建折线图

首先我们将“日期”拖入横轴
Here Insert Picture Description
然后点击“确诊”、“死亡”、“疑似”、“治愈”后,将其拖入纵轴
Here Insert Picture Description
可以看到图表类型中,多系列折线图区域已经亮起
Here Insert Picture Description
选中它
折线图出现了
Here Insert Picture Description

至此,折线图已经制作完毕,你可能还有一些个性化处理的需求,这可以自己去探索,具体细节不再详述,这里给出设置个性化的方式,左侧可以调整其说明上的内容,点击右侧的框中的小方块可以调整其折线图中线的颜色

Here Insert Picture Description

Python代码

import re
import requests
import openpyxl
url = r"https://news.163.com/special/epidemic/"#数据来源 网易
def GetHtmlText(url):
    kv = {'user-agent': 'Mozilla/5.0'}#用于修改头部信息,破除其网站对应的反爬虫机制
    try:
        res=requests.get(url,timeout =30,headers = kv)
        res.raise_for_status()
        res.encoding=res.apparent_encoding
        return res.text
    except:
        return "Error"
def GetTextCenter(Text,TextLeft,TextRight):#取出中间文本
    L = Text.find(TextLeft) + len(TextLeft)
    Text = Text[L:]
    R = Text.find(TextRight)
    return Text[:R]
Html=GetHtmlText(url)
Html_data=GetTextCenter(Html,r"window.data_by_date = [",r","+"\n"+r"]")
Data_list=re.findall(r"{[^}]+}",Html_data)
def Find_Different(list):
    for i in range(0,len(list)):
        n = list[i].find(r", confirm_added")
        if (n != -1):
            return [i,n]#由于需要返回两个数据,所以在此返回一个列表,i表示列表的索引,n表示出现该字符串的首位置
value = Find_Different(Data_list)
Data_list[value[0]]=Data_list[value[0]][:value[1]]+"}"#截取字符串
for each in Data_list:
    print(each)
class item:
    def __init__(self):
        self.data=list()
        self.confirm=list()
        self.suspect=list()
        self.heal=list()
        self.dead=list()
Data_Box=item()
for i in range(0,len(Data_list)):#将数据提取出来
    Data_Box.data.append(GetTextCenter(Data_list[i],r'{date: "',r'",'))#获取日期
    Data_Box.confirm.append(GetTextCenter(Data_list[i],r"confirm: ",r", "))#获取确诊人数
    Data_Box.suspect.append(GetTextCenter(Data_list[i],r"suspect: ",r", "))#获取疑似人数
    Data_Box.heal.append(GetTextCenter(Data_list[i],r"heal: ",r", "))#获取治愈人数
    Data_Box.dead.append(GetTextCenter(Data_list[i],r"dead: ",r"}"))#获取死亡人数
#数据Excel化
wb = openpyxl.Workbook()#建立Excel工作簿
ws = wb.active#获取工作表
ws.cell(1,1,"日期")
ws.cell(1,2,"确诊人数")
ws.cell(1,3,"疑似人数")
ws.cell(1,4,"治愈人数")
ws.cell(1,5,"死亡人数")
for i in range(0,len(Data_list)):
    ws.cell(i + 2, 1, Data_Box.data[i].replace(".","\\"))
    ws.cell(i + 2, 2, int(Data_Box.confirm[i]))
    ws.cell(i + 2, 3, int(Data_Box.suspect[i]))
    ws.cell(i + 2, 4, int(Data_Box.heal[i]))
    ws.cell(i + 2, 5, int(Data_Box.dead[i]))
wb.save("date_data.xlsx")
发布了11 篇原创文章 · 获赞 21 · 访问量 3181

Guess you like

Origin blog.csdn.net/WildSky_/article/details/104108507