博BG大游客更新requestsbs4爬取丁香园feiyan实时数

 新闻资讯     |      2022-09-09 14:50

BG大游博客更新

requests+bs4爬取丁香园飞燕实时数据

Selenium爬取腾讯新闻飞燕页面实时数据

BG大游于 2020 年 4 月 1 日更新

腾讯新闻的飞燕数据接口一直在变化。前几天,url中的foreignList = '#39;失去了。查看页面代码后发现有一个专门提供全局数据的接口:

国外数据:url = 'https://view.inews.qq.com/g2/getOnsInfo?name=disease_foreign'

BG大游具体操作类似,这里不再赘述。但是昨天发现这个界面爬取的数据没有再更新,很多国家的数据都停留在3月30日。但是腾讯新闻界面的数据已经更新了,所以仔细看了一下发现腾讯新闻实时界面是连接app的js界面。想解析一下,看看里面长什么样,只是爬取页面的内容,好久没解析了。跑去看丁香园的界面,发现比腾讯的方便,于是转而爬取丁香园的实时数据。直接抓取页面内容。具体操作稍后更新~

前言

2020年的开启犹如人间炼狱,各种不好的事情频频发生。从1月份开始,估计大家每天都在关注着疫情的发展。我不会在微博上谈论各种尴尬的事情。这里写的是我做事的时候用python爬取腾讯的疫情数据。本文参考:

BG大游利用Python爬取新冠肺炎疫情实时数据,Pyecharts绘制2019-nCoV疫情地图

国际数据抓取

由于上述参考博客已经详细介绍了国内的数据爬取,这里不再介绍国内的数据爬取。

BG大游在上面的博客中,其实是有爬取涉及国际数据的,但是爬完之后发现上面博客的url下爬取的国际数据并不是腾讯新闻显示的实时数据,于是去了自己看。腾讯新闻网页,再次爬取。

本文抓取包括中国在内的国际数据(数据按国家抓取)。爬取的时候发现需要从两个不同的url分别爬取国内和国外的数据新浪新闻提供json数据,才能得到腾讯的实时更新数据:

国内数据:url = 'https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5'
国外数据:url = 'https://view.inews.qq.com/g2/getOnsInfo?name=disease_other'

以上两个链接爬取的数据,其实有国内和国外的数据新浪新闻提供json数据,但有一个是国内实时更新的数据。目前尚不清楚何时存储外国数据。另一个链接是国外实时更新的数据,国内的数据会有一点延迟。

加载包

import requests
import json
import time
import os
import pandas as pd

这里先介绍一下pandas处理的代码,会更直接,更容易理解。但是由于服务器的一些配置原因,pandas 一直报错,所以后面就不用pandas 重写了。

国内疫情数据

首先是国内疫情数据:

path = 'xxx/xxx/xxx' # 这里该路径

博BG大游客更新requestsbs4爬取丁香园feiyan实时数

os.chdir(path) history_df = pd.read_csv('xx.csv') # 历史数据读入, 历史数据自备 data_list = [] # 用于存放更新的数据 ###################### # 中国更新数据爬取 # 获取数据 url = 'https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5' reponse = requests.get(url=url).json() # 从网页加载 data = json.loads(reponse['data']) # 返回数据字典

我们查看数据的内容,参考博客这里使用areeTree,但是这里我们没有使用这部分数据,只使用chinaTotal中的confirm、hea和dead,lastUpdateTime是显示的最后更新时间腾讯新闻。

博BG大游客更新requestsbs4爬取丁香园feiyan实时数

接下来我们继续新浪新闻提供json数据,因为要实现持续更新,每天只保持更新一条记录,所以这里我们需要从前面读取的历史数据中清除当天的数据:

# 提取所需数据
china_dict = {} # 用于存储中国更新的数据
date = time.strptime(data['lastUpdateTime'], "%Y-%m-%d %H:%M:%S")
date = time.strftime("%Y/%m/%d", date) # 提取更新日期 
# 将历史数据中包含更新日期的数据清除,确保每天只保存一条数据
history_df['date'] = time.strftime("%Y/%m/%d", time.strptime(history_df['date'], "%Y/%m/%d"))
history_df = history_df.drop(list(history_df[history_df['date'].isin([date])].index))
list(history_df[history_df['date'].isin([str(date)])].index)

这里要注意时间格式的统一,因为原来的csv被误修改或者需要手动修改的时候新浪新闻提供json数据,读入的时间列的格式会不一致。保存当天更新的多条数据。如果您需要保存特定于秒的数据,您也可以根据需要更改代码。

下面会提取中国的实时数据并添加到data_list中:

china_dict['date'] = date

博BG大游客更新requestsbs4爬取丁香园feiyan实时数

china_dict['time'] = dateTime china_dict['place'] = '中国' china_dict['confirmed_num'] = data['chinaTotal']['confirm'] china_dict['die_num'] = data['chinaTotal']['dead'] china_dict['cure_num'] = data['chinaTotal']['heal'] data_list.append(china_dict)

国外数据爬取

流程和之前国内的数据爬取基本一样,就是改url:

#####################################
# 国际数据
# 获取数据
url = 'https://view.inews.qq.com/g2/getOnsInfo?name=disease_other'
reponse = requests.get(url=url).json() # 从网页加载
data = json.loads(reponse['data']) # 返回数据字典

这时候,我们来看看数据是什么样子的:

博BG大游客更新requestsbs4爬取丁香园feiyan实时数

里面还包含一些新闻和其他的东西,看你是否需要自己爬。我们需要的外国数据在foreignList中。让我们看看 foreignList 长什么样子:

里面有海外国家的数据,我们点进去查看字典结构,比如韩国:

博BG大游客更新requestsbs4爬取丁香园feiyan实时数

我们可以发现在韩国也有一个Children结构,里面存储了韩国具体的区域数据。然而新浪新闻提供json数据,并非所有国家都如此具体。目前,只有中国、日本和韩国拥有彼此特定的数据。我们是来爬取国家数据的,所以只需要爬name,confirm,dead,heal,其他的需求也可以自己爬:

foreignList = data['foreignList'] # 返回国际更新数据
for i in range(len(foreignList)):
    place_dict = {}
    place_dict['date'] = date
    place_dict['place'] = foreignList[i]['name']
    place_dict['confirmed_num'] = foreignList[i]['confirm']

博BG大游客更新requestsbs4爬取丁香园feiyan实时数

place_dict['die_num'] = foreignList[i]['dead'] place_dict['cure_num'] = foreignList[i]['heal'] data_list.append(place_dict)

不断更新数据

然后我们把历史数据和爬取的数据合并,继续保存为原始的csv文件:

# 将更新数据存为所需的dataframe
data_list = pd.DataFrame(data_list)
data_list = data_list[["date", "place", "confirmed_num", "die_num", "cure_num"]]
# 合并历史与更新数据,保存
df_out = history_df.append(data_list)
df_out.to_csv('xxx.csv', index = False, encoding = 'utf_8_sig')

这里设置encoding = 'utf_8_sig',解决中文乱码问题。至此,数据爬取和持续更新的实现就完成了。如果没有 pandas 处理,下一步该怎么做。

不要用 pandas 处理数据

在使用pandas进行处理的时候,我们可以简单的使用DataFrame的结构,这样就可以很方便的进行一些信息的暴露、合并等操作。但是如果你急着用它,而服务器上还没有配置环境,你该怎么办呢?下面介绍如何直接使用列表进行操作。以下代码直接粘贴,无需重复:

import requests
import json
import time
import os
import csv
######### 路径在这里修改
path = 'xxx'
os.chdir(path)
# 历史数据读入

博BG大游客更新requestsbs4爬取丁香园feiyan实时数

history_list = [] with open('xxx.csv', 'r', encoding = 'utf_8_sig') as f: csvReader = csv.reader(f) for row in csvReader: history_list.append(row) data_list = [] # 用于存放更新的数据 ###################### # 中国更新数据爬取 # 获取数据 url = 'https://view.inews.qq.com/g2/getOnsInfo?name=disease_h5' reponse = requests.get(url=url).json() # 从网页加载 data = json.loads(reponse['data']) # 返回数据字典 # 提取所需数据 china_dict = {} # 用于存储中国更新的数据 date = time.strptime(data['lastUpdateTime'], "%Y-%m-%d %H:%M:%S") date = time.strftime("%Y/%m/%d", date) # 提取更新日期 # 将历史数据中包含更新日期的数据清除,确保每天只保存一条数据 data_list.append(history_list[0]) for row in history_list[1:]: row[0] = time.strptime(row[0], "%Y/%m/%d") row[0] = time.strftime("%Y/%m/%d", row[0]) row[1] = '' if date not in row: data_list.append(row)

BG大游博BG大游客更新requestsbs4爬取丁香园feiyan实时数

china_dict['date'] = date china_dict['place'] = '中国' china_dict['confirmed_num'] = data['chinaTotal']['confirm'] china_dict['die_num'] = data['chinaTotal']['dead'] china_dict['cure_num'] = data['chinaTotal']['heal'] data_list.append([china_dict['date'], china_dict['place'], china_dict['confirmed_num'], china_dict['die_num'], china_dict['cure_num']]) ##################################### # 国际数据 # 获取数据 url = 'https://view.inews.qq.com/g2/getOnsInfo?name=disease_other' reponse = requests.get(url=url).json() # 从网页加载 data = json.loads(reponse['data']) # 返回数据字典 foreignList = data['foreignList'] # 返回国际更新数据 for i in range(len(foreignList)): place_dict = {} place_dict['date'] = date place_dict['place'] = foreignList[i]['name'] place_dict['confirmed_num'] = foreignList[i]['confirm'] place_dict['die_num'] = foreignList[i]['dead'] place_dict['cure_num'] = foreignList[i]['heal'] data_list.append([place_dict['date'], place_dict['place'], place_dict['confirmed_num'], place_dict['die_num'], place_dict['cure_num']]) # 保存数据 with open('xxx.csv', 'w', newline = "", encoding = 'utf_8_sig') as f: csvwriter = csv.writer(f) csvwriter.writerows(data_list)