信息來源:https://ncov.dxy.cn/ncovh5/view/pneumonia
一.爬取目標網站,將所有國內數據存儲在json文件內,命名爲當前日期。
步驟:
1)請求目標網站。
2)獲取響應的html頁面。
3)利用正則表達式在獲取的頁面查找相應內容,並進行數據清洗。
4)將讀取內容存儲爲json文件。
(一)請求目標網站和獲取響應頁面
import requests
# 網頁路徑
url = 'https://ncov.dxy.cn/ncovh5/view/pneumonia'
# 請求頭
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36'
}
response = requests.get(url, headers=headers)
print(response.status_code) # 打印狀態碼
# 更推薦使用response.content.deocde()的方式獲取響應的html頁面
url_text = response.content.decode()
(二)定位需要提取的內容
(1)尋找需要提取的信息所在位置
右鍵查看網頁源代碼,需要提取的部分如下:
(2)利用正則表達式查找(使用re.search()函數):
上一步爬取返回的html頁面爲url_text,url_content爲要提取的部分,則:
# re.search():掃描字符串以查找正則表達式模式產生匹配項的第一個位置 ,然後返回相應的match對象。
"""
# re.search(pattern, string, flags=0)函數源碼:
def search(pattern, string, flags=0):
# Scan through string looking for a match to the pattern,
# returning a match object, or None if no match was found.
return _compile(pattern, flags).search(string)
"""
# 在字符串a中,包含換行符\n,在這種情況下:如果不使用re.S參數,則只在每一行內進行匹配。
# 而使用re.S參數以後,正則表達式會將這個字符串作爲一個整體,在整體中進行匹配。
url_content = re.search(r'window.getAreaStat = (.*?)}]}catch', url_text, re.S)
texts = url_content.group() # 獲取匹配正則表達式的整體結果
(三)對提取的內容進行數據清洗,保留下需要的內容。
上一步提取的texts值如下(1),若要能存儲爲json文件,則需要去掉頭部和尾部不符合格式的內容。這裏使用字符串的replace方法。處理完數據內容如(2)。
content = texts.replace('window.getAreaStat = ', '').replace('}catch', '') # 去除多餘的字符
(1)處理前:
window.getAreaStat =
[
{"provinceName": "香港"...},
// ...
]
}catch
(2)處理後:
[
{
"provinceName": "香港"
// ...
}
// ...
]
(四)將數據存入到json文件中。
在上一步成功將數據轉爲符合json格式的文件後,即可將數據存入json文件中。這裏將數據存入當前目錄的data目錄下,並命名爲當前日期.json。當然,操作時候應該加上try catch語句進行異常捕獲。
import datetime
today = datetime.date.today().strftime('%Y%m%d') # 獲取當前日期
json_data = json.loads(content) # 用於將content數據轉成dict。
with open('data/' + today + '.json', 'w', encoding='UTF-8') as f:
json.dump(json_data, f, ensure_ascii=False)
完整獲取國內各省數據並保存到json數據的代碼:
import json
import re
import requests
import datetime
# 網頁路徑
url = 'https://ncov.dxy.cn/ncovh5/view/pneumonia'
# 請求頭
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36'
}
today = datetime.date.today().strftime('%Y%m%d')
def get_dxy_data():
"""
爬取丁香園實時統計數據,保存到data目錄下,以當前日期作爲文件名,存JSON文件
步驟:
1)請求目標網站,可打印狀態碼查看訪問狀態。
2)獲取響應的html頁面。
3)利用正則表達式在獲取的頁面查找相應內容,並進行數據清洗。
4)將讀取內容存儲爲json文件。
"""
response = requests.get(url, headers=headers) # request.get()用於請求目標網站
print(response.status_code) # 打印狀態碼
try:
url_text = response.content.decode() # 更推薦使用response.content.deocde()的方式獲取響應的html頁面
# print(url_text)
# re.search():掃描字符串以查找正則表達式模式產生匹配項的第一個位置 ,然後返回相應的match對象。
url_content = re.search(r'window.getAreaStat = (.*?)}]}catch', url_text, re.S)
# 在字符串a中,包含換行符\n,在這種情況下:如果不使用re.S參數,則只在每一行內進行匹配。
# 而使用re.S參數以後,正則表達式會將這個字符串作爲一個整體,在整體中進行匹配。
texts = url_content.group() # 獲取匹配正則表達式的整體結果
"""
整體結果如下:則需要將'window.getAreaStat = '和'}catch'去掉纔是標準的json格式。
window.getAreaStat =
[
{"provinceName": "香港"...},
// ...
]
}catch
轉換結果:
[
{
"provinceName": "香港"
// ...
}
// ...
]
"""
content = texts.replace('window.getAreaStat = ', '').replace('}catch', '') # 去除多餘的字符
json_data = json.loads(content)
with open('data/' + today + '.json', 'w', encoding='UTF-8') as f:
json.dump(json_data, f, ensure_ascii=False)
except:
print('<Response [%s]>' % response.status_code)
存儲完打開20200406.json,發現疫情統計信息並沒有存在該文件中,而是存在該json文件中的statisticsData屬性內。
二.獲取各個省份歷史統計數據,保存到data目錄下,存JSON文件
步驟:
1)讀取之前保存的json文件。
2)創建一個空字典statistics_data用於接收各省份數據。
3)將所需要的數據存儲在statistics_data.json文件
(一)以讀模式打開之前保存的json文件,加載json數組。
with open('data/' + today + '.json', 'r', encoding='UTF-8') as file:
json_array = json.loads(file.read())
(二)創建一個空字典statistics_data用於接收各省份數據。
首先需要知道我們要提取的數據,每個省的統計信息,這些並沒有直接存儲在之前的json文件中。
(1)觀察之前保存後的json數據如下:其中不同省份的statisticsData屬性分別對應一個不同的json文件。因此可通過json數組['statisticsData']來提取對應的json文件路徑作爲請求。
代碼:請求省份對應的json文件。
statistics_data = {}
for province in json_array:
response = requests.get(province['statisticsData'])
# 如"https://file1.dxycdn.com/2020/0223/331/3398299755968040033-135.json"
(2)隨便選擇一個statisticsData對應的json文件路徑放到瀏覽器下載,打開json文件如下。發現對應省內的數據都保存到下載的json文件的data屬性下。因此可以通過json數組['data']來提取對應省的所有數據。我們提取20200406.json文件中的"provinceName"作爲statistics_data字典中的鍵,而data內容作爲對應於provinceName的值。
代碼:將各省份及其對應的疫情數據存儲到statistics_data字典中,省份名稱作爲鍵,省內疫情數據作爲值。
statistics_data = {}
for province in json_array:
response = requests.get(province['statisticsData'])
# "https://file1.dxycdn.com/2020/0223/331/3398299755968040033-135.json"
try:
statistics_data[province['provinceShortName']] = json.loads(response.content.decode())['data']
except:
print('<Response [%s]> for url: [%s]' % (response.status_code,province['statisticsData']))
(三)將所需要的數據存儲在statistics_data.json文件
with open("data/statistics_data.json", "w", encoding='UTF-8') as f:
json.dump(statistics_data, f, ensure_ascii=False)
完整的獲取統計數據並存入json文件的代碼:
import json
import re
import requests
import datetime
# 網頁路徑
url = 'https://ncov.dxy.cn/ncovh5/view/pneumonia'
# 請求頭
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36'
}
today = datetime.date.today().strftime('%Y%m%d')
def get_statistics_data():
"""
獲取各個省份歷史統計數據,保存到data目錄下,存JSON文件
步驟:
1)讀取之前保存的json文件
2)創建一個空字典statistics_data用於接收
3)將所需要的數據存儲在statistics_data.json文件
"""
with open('data/' + today + '.json', 'r', encoding='UTF-8') as file:
json_array = json.loads(file.read())
statistics_data = {}
for province in json_array:
response = requests.get(province['statisticsData'], headers=headers) # "https://file1.dxycdn.com/2020/0223/331/3398299755968040033-135.json"
try:
statistics_data[province['provinceShortName']] = json.loads(response.content.decode())['data']
except:
print('<Response [%s]> for url: [%s]' % (response.status_code, province['statisticsData']))
with open("data/statistics_data.json", "w", encoding='UTF-8') as f:
json.dump(statistics_data, f, ensure_ascii=False)
執行完以上兩個方法則可在data下生成兩個json文件,分別存放全國疫情數據和統計信息。
本節完整代碼實現如下:
import json
import re
import requests
import datetime
# 網頁路徑
url = 'https://ncov.dxy.cn/ncovh5/view/pneumonia'
# 請求頭
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36'
}
today = datetime.date.today().strftime('%Y%m%d')
def get_dxy_data():
"""
爬取丁香園實時統計數據,保存到data目錄下,以當前日期作爲文件名,存JSON文件
步驟:
1)請求目標網站,可打印狀態碼查看訪問狀態。
2)獲取響應的html頁面。
3)利用正則表達式在獲取的頁面查找相應內容,並進行數據清洗。
4)將讀取內容存儲爲json文件。
"""
response = requests.get(url, headers=headers) # request.get()用於請求目標網站
print(response.status_code) # 打印狀態碼
try:
url_text = response.content.decode() # 更推薦使用response.content.deocde()的方式獲取響應的html頁面
# print(url_text)
# re.search():掃描字符串以查找正則表達式模式產生匹配項的第一個位置 ,然後返回相應的match對象。
url_content = re.search(r'window.getAreaStat = (.*?)}]}catch', url_text, re.S)
# 在字符串a中,包含換行符\n,在這種情況下:如果不使用re.S參數,則只在每一行內進行匹配。
# 而使用re.S參數以後,正則表達式會將這個字符串作爲一個整體,在整體中進行匹配。
texts = url_content.group() # 獲取匹配正則表達式的整體結果
"""
整體結果如下:則需要將'window.getAreaStat = '和'}catch'去掉纔是標準的json格式。
window.getAreaStat =
[
{"provinceName": "香港"...},
// ...
]
}catch
轉換結果:
[
{
"provinceName": "香港"
// ...
}
// ...
]
"""
content = texts.replace('window.getAreaStat = ', '').replace('}catch', '') # 去除多餘的字符
json_data = json.loads(content)
with open('data/' + today + '.json', 'w', encoding='UTF-8') as f:
json.dump(json_data, f, ensure_ascii=False)
except:
print('<Response [%s]>' % response.status_code)
def get_statistics_data():
"""
獲取各個省份歷史統計數據,保存到data目錄下,存JSON文件
步驟:
1)讀取之前保存的json文件
2)創建一個空字典statistics_data用於接收
3)將所需要的數據存儲在statistics_data.json文件
"""
with open('data/' + today + '.json', 'r', encoding='UTF-8') as file:
json_array = json.loads(file.read())
statistics_data = {}
for province in json_array:
response = requests.get(province['statisticsData'],
headers=headers) # "https://file1.dxycdn.com/2020/0223/331/3398299755968040033-135.json"
try:
statistics_data[province['provinceShortName']] = json.loads(response.content.decode())['data']
except:
print('<Response [%s]> for url: [%s]' % (response.status_code, province['statisticsData']))
with open("data/statistics_data.json", "w", encoding='UTF-8') as f:
json.dump(statistics_data, f, ensure_ascii=False)
if __name__ == '__main__':
get_dxy_data()
get_statistics_data()