爬蟲實戰+數據分析:全國消費支出分析及未來預測

来源:https://www.cnblogs.com/guoxiaoyu/p/18084015
-Advertisement-
Play Games

完美收官,本文是爬蟲實戰的最後一章了,所以儘管本文著重呈現爬蟲實戰,但其中有一大部分內容專註於數據分析。爬蟲只是整個過程的起點,其主要目的之一就是為後續數據分析等工作做好準備。通過對爬取的數據進行精確的清洗和分析,可以揭示其中隱藏的規律和趨勢,為決策提供有力支持。因此,爬蟲實戰並不僅僅是技術的展示,... ...


在本篇文章中,爬蟲的講解不僅僅局限於爬蟲本身,還會引申至另一個重要領域:數據分析。對我們而言,爬蟲的核心價值實際上在於獲取數據,一旦獲得了數據,接下來必然是要加以利用。數據分析便是其中關鍵一環,因此在爬蟲的講解之後,我們將會稍作涉及與數據分析相關的知識要點。

今天主要任務是爬取全國消費數據,然後根據過去十年的數據進行深入分析,以便進行未來兩年的消費預測。廢話不多說,讓我們直接開始吧。

全國消費數據

要獲取全國的消費數據,最好前往國家數據統計局進行查詢。因此,在使用爬蟲時,應當謹慎操作,避免對伺服器造成負荷過大的影響。在成功獲取數據後,應當及時保存,而不是過度頻繁地請求數據,以免導致伺服器癱瘓。在開始分析頁面之前,先確認所需的全國消費數據是否已被提供,然後按照常規操作,在頁面下方進行搜索,以確定數據展示形式是靜態頁面還是通過ajax請求獲取的。

image

為什麼在這裡我搜索的是數字而非文字?這是因為該請求返回到瀏覽器時處於亂碼狀態,因此為了演示,我選擇了數字作為示例,效果是一樣的。一旦找到請求,處理起來就很簡單了,我們只需複製URL,前往線上網站進行處理,然後將代碼複製出來即可。如果線上網站有不清楚的地方,可以參考前幾章的文章。

數據抓取

直接看下爬蟲代碼:

import requests
import re

strdata_code_map = {}
wdcode_name_map = {}
def get_data():
    global strdata_code_map,wdcode_name_map
    headers = {
        'Accept': 'application/json, text/javascript, */*; q=0.01',
        'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
        'Connection': 'keep-alive',
        'Cookie': 'wzws_sessionid=oGX46GqAMTIzLjE3Mi40OS4yMDKBZDk0YTI3gmZjNWVlMQ==; u=6; experience=show; JSESSIONID=bANUmkmAc_F_FOy-dM-8VqxHEea-dpa39By6stbh14v9_aYXN7HM!1314454129',
        'Referer': 'https://data.stats.gov.cn/easyquery.htm?cn=C01',
        'Sec-Fetch-Dest': 'empty',
        'Sec-Fetch-Mode': 'cors',
        'Sec-Fetch-Site': 'same-origin',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0',
        'X-Requested-With': 'XMLHttpRequest',
        'sec-ch-ua': '"Chromium";v="122", "Not(A:Brand";v="24", "Microsoft Edge";v="122"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"Windows"',
    }

    params = {
        'm': 'QueryData',
        'dbcode': 'hgnd',
        'rowcode': 'zb',
        'colcode': 'sj',
        'wds': '[]',
        'dfwds': '[{"wdcode":"zb","valuecode":"A0A04"}]',
        'k1': '1710816989823',
        'h': '1',
    }

    response = requests.get('https://data.stats.gov.cn/easyquery.htm', params=params,   headers=headers, verify=False)
    # 解析JSON數據
    response_data = response.json()
    
    # 提取datanodes中的strdata和code映射數據列表
    datanodes = response_data['returndata']['datanodes']
    for node in datanodes:
        input_str = node['code']
        match = re.search(r'\.(\w+)_sj\.(\d+)', input_str)

        if match:
            part1 = match.group(1)  # A0A0401
            part2 = match.group(2)  # 2023
            if 'year' not in strdata_code_map:
                strdata_code_map['year'] = []
            if part2 not in strdata_code_map['year']:
                strdata_code_map['year'].append(part2) 
            if part1 not in strdata_code_map:
                strdata_code_map[part1] = []
            strdata_code_map[part1].append(node['data']['strdata'])
    print(strdata_code_map)
    # 提取wdnodes中code和name映射列表
    wdnodes = response_data['returndata']['wdnodes']
    wdcode_name_map = {node['code']: node['name'] for node in wdnodes[0]['nodes']}
    print(wdcode_name_map)

這段代碼解析了返回的JSON數據,提取了datanodes中的數據節點和wdnodes中的維度節點信息。對於數據節點,通過正則表達式提取了每個節點的code屬性,解析出數據節點對應的strdata和code映射關係,並將這些信息存儲到strdata_code_map字典中。對於維度節點,將每個節點的code和name屬性映射關係存儲到wdcode_name_map字典中。

數據分析

拿到數據後,我們立即對其進行數據分析。一般來說,在數據分析項目中,我們會首先利用Pandas庫載入數據,進行數據清洗和處理,然後使用Matplotlib庫進行數據可視化,以便更深入地理解數據並有效展示結果。

不多說,直接看下代碼:

import pandas as pd
import matplotlib.pyplot as plt

def get_now_plt():
    data = {
        'year': ['2023', '2022', '2021', '2020', '2019', '2018', '2017', '2016', '2015', '2014'],
        'A0A0401': ['26796', '24538', '24100', '21210', '21559', '19853', '18322', '17111', '15712', '14491'],
        'A0A0402': ['9.0', '-0.2', '12.6', '-4.0', '5.5', '6.2', '5.4', '6.8', '6.9', '7.5'],
        'A0A0403': ['12114', '10590', '10645', '9037', '9886', '8781', '7803', '7157', '6460', '5842'],
        'A0A0404': ['14.4', '-0.5', '17.8', '-8.6', '12.6', '12.5', '9.0', '10.8', '10.6', '11.4'],
        'A0A0405': ['7983', '7481', '7178', '6397', '6084', '5631', '5374', '5151', '4814', '4494'],
        'A0A0406': ['6.7', '4.2', '12.2', '5.1', '8.0', '4.8', '4.3', '7.0', '7.1', '8.9'],
        'A0A0407': ['1479', '1365', '1419', '1238', '1338', '1289', '1238', '1203', '1164', '1099'],
        'A0A0408': ['8.4', '-3.8', '14.6', '-7.5', '3.8', '4.1', '2.9', '3.3', '5.9', '7.0'],
        'A0A0409': ['6095', '5882', '5641', '5215', '5055', '4647', '4107', '3746', '3419', '3201'],
        'A0A040A': ['3.6', '4.3', '8.2', '3.2', '8.8', '13.1', '9.6', '9.6', '6.8', '6.7'],
        'A0A040B': ['1526', '1432', '1423', '1260', '1281', '1223', '1121', '1044', '951', '890'],
        'A0A040C': ['6.6', '0.6', '13.0', '-1.7', '4.8', '9.1', '7.4', '9.7', '6.9', '10.3'],
        'A0A040D': ['3652', '3195', '3156', '2762', '2862', '2675', '2499', '2338', '2087', '1869'],
        'A0A040E': ['14.3', '1.2', '14.3', '-3.5', '7.0', '7.1', '6.9', '12.0', '11.6', '14.9'],
        'A0A040F': ['2904', '2469', '2599', '2032', '2513', '2226', '2086', '1915', '1723', '1536'],
        'A0A040G': ['17.6', '-5.0', '27.9', '-19.1', '12.9', '6.7', '8.9', '11.2', '12.2', '9.9'],
        'A0A040H': ['2460', '2120', '2115', '1843', '1902', '1685', '1451', '1307', '1165', '1045'],
        'A0A040I': ['16.0', '0.2', '14.8', '-3.1', '12.9', '16.1', '11.0', '12.3', '11.5', '14.5'],
        'A0A040J': ['697', '595', '569', '462', '524', '477', '447', '406', '389', '358'],
        'A0A040K': ['17.1', '4.6', '23.2', '-11.8', '9.7', '6.8', '10.0', '4.4', '8.7', '10.3']
    }
    label = {
        'A0A0401': '居民人均消費支出',
        'A0A0402': '居民人均消費支出_比上年增長',
        'A0A0403': '居民人均服務性消費支出',
        'A0A0404': '居民人均服務性消費支出_比上年增長',
        'A0A0405': '居民人均食品煙酒支出',
        'A0A0406': '居民人均食品煙酒支出_比上年增長',
        'A0A0407': '居民人均衣著支出',
        'A0A0408': '居民人均衣著支出_比上年增長',
        'A0A0409': '居民人均居住支出',
        'A0A040A': '居民人均居住支出_比上年增長',
        'A0A040B': '居民人均生活用品及服務支出',
        'A0A040C': '居民人均生活用品及服務支出_比上年增長',
        'A0A040D': '居民人均交通通信支出',
        'A0A040E': '居民人均交通通信支出_比上年增長',
        'A0A040F': '居民人均教育文化娛樂支出',
        'A0A040G': '居民人均教育文化娛樂支出_比上年增長',
        'A0A040H': '居民人均醫療保健支出',
        'A0A040I': '居民人均醫療保健支出_比上年增長',
        'A0A040J': '居民人均其他用品及服務支出',
        'A0A040K': '居民人均其他用品及服務支出_比上年增長'
    }

    keys = list(data.keys())  # 獲取所有鍵並轉換為列表
    need_keys = []
    for i in range(1, len(keys), 2):
        need_keys.append(keys[i])
    # 數據
    years = data['year']

    # 繪製折線圖
    for key in range(0, len(need_keys), 2):
        plt.plot(years, [int(x) for x in data[need_keys[key]]], label=label[need_keys[key]], marker='o')

    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.xlabel('年份')
    plt.ylabel('消費支出(元)')
    plt.title('全國居民人均支出情況')
    plt.legend()
    plt.grid(True)
    plt.show()
    
get_now_plt()

為了保持代碼的流暢性,我先複製了數據並定義了兩個字典項,分別是label和data。字典label用於存儲每種數據類型的中文標簽,而字典data包含了各年份的不同消費支出數據,比如居民人均消費支出、居民人均服務性消費支出等。接著,我使用matplotlib.pyplot庫來繪製折線圖。在繪製過程中,我遍歷了need_keys列表,為每種數據類型繪製相應的折線圖,並添加了標簽和數據點。

image

當處理數據時,請確保註意到,如果需要顯示中文字元,您可能需要使用以下語句來設置字體以避免亂碼:plt.rcParams['font.sans-serif'] = ['SimHei']。此外,請註意我存儲的數據是按倒序排列的。

未來預測

當我們擁有近10年的數據時,實際上可以利用這些數據進行預測。在這方面有許多方法可供選擇,今天我們將探討ARIMA模型。ARIMA代表自回歸(Autoregressive, AR)、差分(Integrated, I)和移動平均(Moving Average, MA)這三種技術的結合,是一種用於時間序列預測的統計模型。通過ARIMA模型,我們可以捕捉時間序列數據中的趨勢、季節性變化和周期性變化。

在本章中,我們僅僅是提供了一些基礎信息,希望能夠引發你的興趣,具體的內容將在後續的章節中詳細展開。因此,接下來可以直接查看代碼部分:

import requests
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.arima.model import ARIMA
import re

def get_feature_plt():
    
    # 數據
    data = {
        'year': [2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023],
        'A0A0403': [5842, 6460, 7157, 7803, 8781, 9886, 9037, 10645, 10590, 12114],
        'A0A0405': [4494, 4814, 5151, 5374, 5631, 6084, 6397, 7178, 7481, 7983],
        'A0A0407': [1099, 1164, 1203, 1238, 1289, 1338, 1238, 1419, 1365, 1479],
        'A0A0409': [3201, 3419, 3746, 4107, 4647, 5055, 5215, 5641, 5882, 6095],
        'A0A040B': [890, 951, 1044, 1121, 1223, 1281, 1260, 1423, 1432, 1526],
        'A0A040D': [1869, 2087, 2338, 2499, 2675, 2862, 2762, 3156, 3195, 3652],
        'A0A040F': [1536, 1723, 1915, 2086, 2226, 2513, 2032, 2599, 2469, 2904],
        'A0A040H': [1045, 1165, 1307, 1451, 1685, 1902, 1843, 2115, 2120, 2460],
        'A0A040J': [358, 389, 406, 447, 477, 524, 462, 569, 595, 697],
    }
    label = {
        'A0A0401': '居民人均消費支出',
        'A0A0402': '居民人均消費支出_比上年增長',
        'A0A0403': '居民人均服務性消費支出',
        'A0A0404': '居民人均服務性消費支出_比上年增長',
        'A0A0405': '居民人均食品煙酒支出',
        'A0A0406': '居民人均食品煙酒支出_比上年增長',
        'A0A0407': '居民人均衣著支出',
        'A0A0408': '居民人均衣著支出_比上年增長',
        'A0A0409': '居民人均居住支出',
        'A0A040A': '居民人均居住支出_比上年增長',
        'A0A040B': '居民人均生活用品及服務支出',
        'A0A040C': '居民人均生活用品及服務支出_比上年增長',
        'A0A040D': '居民人均交通通信支出',
        'A0A040E': '居民人均交通通信支出_比上年增長',
        'A0A040F': '居民人均教育文化娛樂支出',
        'A0A040G': '居民人均教育文化娛樂支出_比上年增長',
        'A0A040H': '居民人均醫療保健支出',
        'A0A040I': '居民人均醫療保健支出_比上年增長',
        'A0A040J': '居民人均其他用品及服務支出',
        'A0A040K': '居民人均其他用品及服務支出_比上年增長'
    }

    df = pd.DataFrame(data)
    df.set_index('year', inplace=True)
    need_keys = list(data.keys())  # 獲取所有鍵並轉換為列表
    for i in range(1, len(need_keys), 3):
        # 擬合ARIMA模型
        model = ARIMA(df[need_keys[i]], order=(1, 1, 1))  # 根據數據特點選擇合適的order
        model_fit = model.fit()

        # 進行未來預測
        future_years = [2024,2025]  # 假設預測未來兩年
        forecast = model_fit.forecast(steps=len(future_years))

        # 可視化預測結果
        plt.plot(df.index, df[need_keys[i]], label=label[need_keys[i]])
        plt.plot(future_years, forecast, label='預測'+label[need_keys[i]], linestyle='--', marker='o')
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.xlabel('年份')
    plt.ylabel('消費支出(元)')
    plt.title('未來兩年預測消費支出')
    plt.legend()
    plt.grid(True)
    plt.show()

在進行優化處理時,首先將暫存的數據轉換為Pandas的DataFrame格式,並將年份設為索引。接著,從數據中提取所需的鍵名,對每三個鍵進行ARIMA模型的擬合和預測,隨後通過可視化展示了消費支出隨時間變化的趨勢圖,並呈現了未來兩年的預測數據。

image

總結

完美收官,本文是爬蟲實戰的最後一章了,所以儘管本文著重呈現爬蟲實戰,但其中有一大部分內容專註於數據分析。爬蟲只是整個過程的起點,其主要目的之一就是為後續數據分析等工作做好準備。通過對爬取的數據進行精確的清洗和分析,可以揭示其中隱藏的規律和趨勢,為決策提供有力支持。因此,爬蟲實戰並不僅僅是技術的展示,更是對數據價值的挖掘和充分利用。

還有一點需要特別強調的是,絕對不能利用這種方式從中謀取個人利益,比如搭建爬蟲網站等手段,這些行為是違法的。我想再次強調,在進行爬蟲操作時一定要遵守相關法律法規,儘量以學習為主,切勿觸犯法律。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...