python爬取當日疫情信息並存儲爲json文件

 

信息來源: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_texturl_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()

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章