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

来源: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 Framework 4.8 開發的深度學習模型部署測試平臺,提供了YOLO框架的主流系列模型,包括YOLOv8~v9,以及其系列下的Det、Seg、Pose、Obb、Cls等應用場景,同時支持圖像與視頻檢測。模型部署引擎使用的是OpenVINO™、TensorRT、ONNX runti... ...
  • 十年沉澱,重啟開發之路 十年前,我沉浸在開發的海洋中,每日與代碼為伍,與演算法共舞。那時的我,滿懷激情,對技術的追求近乎狂熱。然而,隨著歲月的流逝,生活的忙碌逐漸占據了我的大部分時間,讓我無暇顧及技術的沉澱與積累。 十年間,我經歷了職業生涯的起伏和變遷。從初出茅廬的菜鳥到逐漸嶄露頭角的開發者,我見證了 ...
  • C# 是一種簡單、現代、面向對象和類型安全的編程語言。.NET 是由 Microsoft 創建的開發平臺,平臺包含了語言規範、工具、運行,支持開發各種應用,如Web、移動、桌面等。.NET框架有多個實現,如.NET Framework、.NET Core(及後續的.NET 5+版本),以及社區版本M... ...
  • 前言 本文介紹瞭如何使用三菱提供的MX Component插件實現對三菱PLC軟元件數據的讀寫,記錄了使用電腦模擬,模擬PLC,直至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1. PLC開發編程環境GX Works2,GX Works2下載鏈接 https:// ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • 1、jQuery介紹 jQuery是什麼 jQuery是一個快速、簡潔的JavaScript框架,是繼Prototype之後又一個優秀的JavaScript代碼庫(或JavaScript框架)。jQuery設計的宗旨是“write Less,Do More”,即倡導寫更少的代碼,做更多的事情。它封裝 ...
  • 前言 之前的文章把js引擎(aardio封裝庫) 微軟開源的js引擎(ChakraCore))寫好了,這篇文章整點js代碼來測一下bug。測試網站:https://fanyi.youdao.com/index.html#/ 逆向思路 逆向思路可以看有道翻譯js逆向(MD5加密,AES加密)附完整源碼 ...
  • 引言 現代的操作系統(Windows,Linux,Mac OS)等都可以同時打開多個軟體(任務),這些軟體在我們的感知上是同時運行的,例如我們可以一邊瀏覽網頁,一邊聽音樂。而CPU執行代碼同一時間只能執行一條,但即使我們的電腦是單核CPU也可以同時運行多個任務,如下圖所示,這是因為我們的 CPU 的 ...
  • 掌握使用Python進行文本英文統計的基本方法,並瞭解如何進一步優化和擴展這些方法,以應對更複雜的文本分析任務。 ...
  • 背景 Redis多數據源常見的場景: 分區數據處理:當數據量增長時,單個Redis實例可能無法處理所有的數據。通過使用多個Redis數據源,可以將數據分區存儲在不同的實例中,使得數據處理更加高效。 多租戶應用程式:對於多租戶應用程式,每個租戶可以擁有自己的Redis數據源,以確保數據隔離和安全性。 ...