數據源選擇
將新聞媒體的播報平臺作爲數據源,以網易的疫情播報平臺爲例,如下圖所示可以看到它的數據內容非常豐富,不僅包括國內的數據還包括國外的數據,且作爲大平臺,公信度也比較高。因此我們選擇網易的疫情實時動態播報平臺作爲數據源,其地址如下:https://wp.m.163.com/163/page/news/virus_report/index.html?nw=1&anw=1
我們基於網易的實時播報平臺尋找數據,由於它是一個實時的動態平臺,因此數據一般在Network標籤下可以找到,以Chrome瀏覽器爲例展示尋找數據步驟:
- 訪問網易實時疫情播報平臺
- 在頁面任意位置右鍵點擊檢查
- 進入Network標籤下的XHR,此時可能會提示刷新,按下“Ctrl+R”即可
在網頁的檢查頁面內,左下角紅框所示的部分是我們找到的數據源,基於這些地址進行爬取,我們獲取數據的目標是全國,世界各國以及全國各省的實時以及歷史數據。
初步探索
通過比對,我們發現在第二個地址中存放着關於疫情的數據,因此我們先對這個地址進行爬蟲。接下來找到其地址,點擊headers後進行查看,在url中?後邊爲參數,可以不用設置,因此我們需要請求的地址爲:https://c.m.163.com/ug/api/wuhan/app/data/list-total ,並且可以看到請求方法爲get,同時查看自己瀏覽器的user-agent,使用requests請求時,設置user-agent僞裝瀏覽器。
接下來開始請求,首先導入使用的包,使用request進行網頁請求,使用pandas保存數據。
同時設置請求頭,僞裝爲瀏覽器使用requests發起請求,查看請求狀態。
import requests
import pandas as pd
import time
pd.set_option('max_rows',500)
url = "https://c.m.163.com/ug/api/wuhan/app/data/list-total" # 定義要訪問的地址
r = requests.get(url,headers={'user-agent': '填寫自己的user-agent'}) # 使用requests發起請求
print(r.status_code) # 查看請求狀態
print(type(r.text))
print(len(r.text))
可以看到返回後的內容是一個幾十萬長度的字符串,由於字符串格式不方便進行分析,並且在網頁預覽中發現數據爲類似字典的json格式,所以我們將其轉爲json格式。
import json
data_json = json.loads(r.text)
type(data_json)
data_json.keys()
可以看出在data中存放着我們需要的數據,因此我們取出數據。
data = data_json['data'] # 取出json中的數據
data.keys()
數據中總共有四個鍵,每個鍵存儲着不同的內容:
接下來分別獲取實時數據和歷史數據。
直接上代碼了,具體不懂可以評論討論。
import requests
import pandas as pd
import time
import json
# 將提取數據的方法封裝爲函數
def get_data(data, info_list):
info = pd.DataFrame(data)[info_list] # 主要信息
today_data = pd.DataFrame([i['today'] for i in data]) # 提取today的數據
today_data.______ = ['today_' + i for i in today_data.columns] # 修改列名 columns
total_data = pd.DataFrame([i['total'] for i in data]) # 提取total的數據
total_data.______ = ['total_' + i for i in total_data.columns] # 修改列名 columns
return pd.concat([info, total_data, today_data], axis=1) # info、today和total橫向合併最終得到彙總的數據
def save_data(data,name): # 定義保存數據方法
file_name = name+'_'+time.strftime('%Y_%m_%d',time.localtime(time.time()))+'.csv'
data.to_csv(file_name,index=None,encoding='utf_8_sig')
print(file_name+' 保存成功!')
def main():
pd.set_option('max_rows',500)
url = "https://c.m.163.com/ug/api/wuhan/app/data/list-total"
headers = {'user-agent': '這裏隨便寫入一個user-agent'}
r = requests.get(url,headers=headers)
# print(r.status_code)
# print(type(r.text))
# print(len(r.text))
data_json = json.loads(r.text)
type(data_json)
data_json.keys()
data = data_json['data'] # 取出json中的數據
# 中國各省的實時數據爬取
data_province = data['areaTree'][2]['children']
today_province = get_data(data_province,['id','lastUpdateTime','name'])
save_data(today_province, 'today_province')
# 世界各國實時數據爬取
areaTree = data['areaTree'] # 取出areaTree
today_world = get_data(areaTree, ['id', 'lastUpdateTime', 'name'])
today_world.head()
# 中國歷史數據爬取
chinaDayList = data['chinaDayList']
alltime_China = get_data(chinaDayList, ['date', 'lastUpdateTime'])
save_data(alltime_China, 'alltime_China')
# 中國各省歷史數據爬取
start = time.time()
for province_id in province_dict: # 遍歷各省編號
try:
# 按照省編號訪問每個省的數據地址,並獲取json數據
url_1 = 'https://c.m.163.com/ug/api/wuhan/app/data/list-by-area-code?areaCode=' + province_id
r = requests.get(url_1, headers=headers)
data_json = json.loads(r.text)
# 提取各省數據,然後寫入各省名稱
province_data = get_data(data_json['data']['list'], ['date'])
province_data['name'] = province_dict[province_id]
# 合併數據
if province_id == '420000':
alltime_province = province_data
else:
alltime_province = pd.DataFrame([alltime_province, province_data])
print('-' * 20, province_dict[province_id], '成功',
province_data.shape, alltime_province.shape,
',累計耗時:', round(time.time() - start), '-' * 20)
# 設置延遲等待
time.sleep(10)
except:
print('-' * 20, province_dict[province_id], 'wrong', '-' * 20)
alltime_province.info()
save_data(alltime_province, 'alltime_province')
# 世界各國曆史數據爬取
country_dict = {key: value for key, value in zip(today_world['id'], today_world['name'])}
start = time.time()
for country_id in country_dict: # 遍歷每個國家的編號
try:
# 按照編號訪問每個國家的數據地址,並獲取json數據
url_2 = 'https://c.m.163.com/ug/api/wuhan/app/data/list-by-area-code?areaCode=' + country_id
r = requests.get(url_2, headers=headers)
json_data = json.loads(r.text)
# 生成每個國家的數據
country_data = get_data(json_data['data']['list'], ['date'])
country_data['name'] = country_dict[country_id]
# 數據疊加
if country_id == '9577772':
alltime_world = country_data
else:
alltime_world = pd.DataFrame([alltime_world, country_data])
print('-' * 20, country_dict[country_id], '成功', country_data.shape, alltime_world.shape,
',累計耗時:', round(time.time() - start), '-' * 20)
time.sleep(10)
except:
print('-' * 20, country_dict[country_id], 'wrong', '-' * 20)
print(alltime_world.shape)
save_data(alltime_world, 'alltime_world')
main()
聲明:本博客內容爲學習酷客上相關案例後所做總結。