利用python抓取HTML頁(yè)面數(shù)據(jù)并作可視化數(shù)據(jù)分析
本文所展示的代碼是一個(gè)完整的數(shù)據(jù)采集、處理與可視化工具,主要用于從指定網(wǎng)站下載Excel文件,解析其中的數(shù)據(jù),并生成投資者數(shù)量的趨勢(shì)圖表。以下是代碼的主要功能模塊及其作用:
1.網(wǎng)頁(yè)數(shù)據(jù)獲取
使用fetch_html_page函數(shù)從目標(biāo)網(wǎng)站抓取HTML頁(yè)面內(nèi)容。
通過parse_html_for_excel_links解析HTML內(nèi)容,提取所有Excel文件鏈接。
利用parse_html_for_max_page解析最大分頁(yè)數(shù),確保能夠遍歷所有頁(yè)面。
2.文件下載與存儲(chǔ)
download_excel_file負(fù)責(zé)根據(jù)Excel文件的URL下載文件并保存到本地指定路徑。
download_excel_data實(shí)現(xiàn)批量下載功能,支持多頁(yè)數(shù)據(jù)的完整采集。
3.數(shù)據(jù)讀取與處理
read_excel_file使用pandas庫(kù)讀取Excel文件內(nèi)容。
process_excel_data將Excel數(shù)據(jù)轉(zhuǎn)換為字典格式,便于后續(xù)處理。
process_downloaded_files批量處理下載的Excel文件,提取關(guān)鍵數(shù)據(jù)并存儲(chǔ)為列表。
4.數(shù)據(jù)可視化
plot_investor_trends利用matplotlib繪制雙Y軸折線圖,展示個(gè)人投資者和機(jī)構(gòu)投資者的數(shù)量變化趨勢(shì)。
圖表包含日期、個(gè)人投資者數(shù)量(萬名)和機(jī)構(gòu)投資者數(shù)量(家),并通過不同顏色區(qū)分?jǐn)?shù)據(jù)系列。
整體流程
代碼從指定網(wǎng)站抓取數(shù)據(jù),自動(dòng)下載相關(guān)Excel文件。
解析Excel文件中的投資者數(shù)據(jù),并生成趨勢(shì)圖表以直觀展示數(shù)據(jù)變化。
import warnings import requests from bs4 import BeautifulSoup import pandas as pd import os import re import matplotlib # 設(shè)置matplotlib的字體配置,以支持中文顯示 matplotlib.rcParams['font.sans-serif'] = ['SimHei'] # 或者 ['Microsoft YaHei'] matplotlib.rcParams['axes.unicode_minus'] = False matplotlib.use('TkAgg') from matplotlib import pyplot as plt def fetch_html_page(url): """ 獲取HTML頁(yè)面內(nèi)容。 參數(shù): url (str): 目標(biāo)網(wǎng)頁(yè)的URL。 返回: str: 頁(yè)面的HTML內(nèi)容,如果請(qǐng)求失敗則返回None。 """ headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" } response = requests.get(url, headers=headers) if response.status_code == 200: print(f"成功獲取頁(yè)面: {url}") return response.text else: print(f"Error: {response.status_code}, {response.text}") return None def parse_html_for_excel_links(html_content): """ 解析HTML內(nèi)容中的Excel鏈接。 參數(shù): html_content (str): HTML頁(yè)面內(nèi)容。 返回: list: 包含所有找到的Excel文件鏈接的列表。 """ soup = BeautifulSoup(html_content, 'html.parser') excel_links = [] for a_tag in soup.find_all('a', href=True): href = a_tag.get('href') if href and href.endswith('.xlsx'): excel_links.append(href) return excel_links def parse_html_for_max_page(html_content): """ 解析HTML內(nèi)容以找到最大頁(yè)面數(shù)。 參數(shù): html_content (str): HTML頁(yè)面內(nèi)容。 返回: int: 最大頁(yè)面數(shù)。 """ soup = BeautifulSoup(html_content, 'html.parser') max_page = 1 for a_tag in soup.find_all('a', class_='pagingNormal'): onclick = a_tag.get('onclick') if onclick: match = re.search(r"'(/test/j/[^']+)'", onclick) if match: page_number = match.group(1).split('-')[-1].split('.')[0] max_page = max(max_page, int(page_number)) return max_page def download_excel_file(url, save_path): """ 下載Excel文件并保存到指定路徑。 參數(shù): url (str): Excel文件的URL。 save_path (str): 文件的保存路徑。 """ headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" } response = requests.get(url, headers=headers) if response.status_code == 200: with open(save_path, 'wb') as f: f.write(response.content) print(f"下載完成: {save_path}") else: print(f"Error: {response.status_code}, {response.text}") def download_excel_data(): """ 下載所有Excel數(shù)據(jù)文件。 """ base_url = 'https://test/index.html' # 替換為實(shí)際網(wǎng)頁(yè)地址 current_url = base_url page_number = 1 html_content = fetch_html_page(current_url) if not html_content: return max_page = parse_html_for_max_page(html_content) print(f"最大頁(yè)面數(shù): {max_page}") while page_number <= max_page: print(f"正在處理第 {page_number} 頁(yè): {current_url}") html_content = fetch_html_page(current_url) if not html_content: break excel_links = parse_html_for_excel_links(html_content) if not excel_links: print("未找到Excel鏈接。") break for link in excel_links: full_url = f"https://www.test.cn{link}" # 提取日期和文件名部分 file_path_parts = link.split('/') file_name = ('/'.join(file_path_parts[-3:-1]) + '/' + file_path_parts[-1]).replace('/', '-') save_path = os.path.join('downloads', file_name) os.makedirs(os.path.dirname(save_path), exist_ok=True) download_excel_file(full_url, save_path) if page_number < max_page: next_page_link = f"/test/d2bb5c19-{page_number + 1}.html" current_url = f"https://www.test.cn{next_page_link}" page_number += 1 else: print("沒有更多頁(yè)面。") break def read_excel_file(file_path): """ 讀取Excel文件內(nèi)容。 參數(shù): file_path (str): Excel文件的路徑。 返回: DataFrame: 讀取到的Excel文件內(nèi)容,如果讀取失敗則返回None。 """ try: with warnings.catch_warnings(): warnings.simplefilter("ignore", UserWarning) df = pd.read_excel(file_path, engine='openpyxl', header=None) return df except Exception as e: print(f"讀取Excel文件時(shí)出錯(cuò): {e}") return None def process_excel_data(df): """ 處理Excel數(shù)據(jù),將其轉(zhuǎn)換為字典格式。 參數(shù): df (DataFrame): Excel文件內(nèi)容。 返回: dict: 轉(zhuǎn)換后的字典數(shù)據(jù)。 """ if df is None: return {} # 處理合并單元格 # df = df.fillna(method='ffill').fillna(method='bfill') # 將數(shù)據(jù)轉(zhuǎn)換為字典 data_dict = {} current_section = None for index, row in df.iterrows(): if index == 1: # 第二行 key = row[1] if pd.isnull(key): key = df.iloc[1, 0] value = row[2] if pd.notnull(row[2]) else None data_dict[key] = value elif index > 1: if pd.notnull(row[0]): current_section = row[0] data_dict[current_section] = {} if pd.notnull(row[1]): key = row[1] value = row[2] if pd.notnull(row[2]) else None data_dict[current_section][key] = value return data_dict def process_downloaded_files(directory): """ 處理下載的Excel文件,提取數(shù)據(jù)。 參數(shù): directory (str): 存放下載文件的目錄路徑。 返回: list: 包含所有處理后的數(shù)據(jù)字典的列表。 """ data_list = [] for filename in os.listdir(directory): if filename.endswith('.xlsx'): file_path = os.path.join(directory, filename) df = read_excel_file(file_path) if df is not None: print(f"處理文件: {filename}") data_dict = process_excel_data(df) print(data_dict) # 打印處理后的字典 data_list.append(data_dict) return data_list def plot_investor_trends(data_list): """ 繪制投資者數(shù)量趨勢(shì)圖。 參數(shù): data_list (list): 包含投資者數(shù)據(jù)的列表。 """ # 提取時(shí)間值和投資者數(shù)量 dates = [] individual_investors = [] institutional_investors = [] for data_dict in data_list: date_str = data_dict['統(tǒng)計(jì)指標(biāo)'] date = pd.to_datetime(date_str) dates.append(date) individual_investors.append(data_dict['證券公司開展業(yè)務(wù)情況']['個(gè)人投資者數(shù)量(萬名)']) institutional_investors.append(data_dict['證券公司開展業(yè)務(wù)情況']['機(jī)構(gòu)投資者數(shù)量(家)']) # 創(chuàng)建折線圖 fig, ax1 = plt.subplots(figsize=(10, 6)) # 繪制個(gè)人投資者數(shù)量 color = 'tab:red' ax1.set_xlabel('日期') ax1.set_ylabel('個(gè)人投資者數(shù)量(萬名)', color=color) ax1.plot(dates, individual_investors, color=color, label='個(gè)人投資者數(shù)量(萬名)', marker='o') ax1.tick_params(axis='y', labelcolor=color) # 創(chuàng)建第二個(gè) Y 軸 ax2 = ax1.twinx() # 共享 X 軸 # 繪制機(jī)構(gòu)投資者數(shù)量 color = 'tab:blue' ax2.set_ylabel('機(jī)構(gòu)投資者數(shù)量(家)', color=color) ax2.plot(dates, institutional_investors, color=color, label='機(jī)構(gòu)投資者數(shù)量(家)', marker='o') ax2.tick_params(axis='y', labelcolor=color) # 設(shè)置標(biāo)題和圖例 fig.tight_layout() # 調(diào)整子圖參數(shù),防止標(biāo)簽重疊 plt.title('投資者數(shù)量趨勢(shì)') fig.legend(loc='upper left', bbox_to_anchor=(0.1, 0.9)) # 顯示圖形 plt.show() # 調(diào)用函數(shù)繪制投資者趨勢(shì)圖 plot_investor_trends(process_downloaded_files('downloads'))
到此這篇關(guān)于利用python抓取HTML頁(yè)面數(shù)據(jù)并作可視化數(shù)據(jù)分析的文章就介紹到這了,更多相關(guān)python抓取HTML頁(yè)面數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- python數(shù)據(jù)抓取3種方法總結(jié)
- Python中執(zhí)行JavaScript實(shí)現(xiàn)數(shù)據(jù)抓取的多種方法
- Python使用BeautifulSoup抓取和解析網(wǎng)頁(yè)數(shù)據(jù)的操作方法
- Python使用BeautifulSoup和Scrapy抓取網(wǎng)頁(yè)數(shù)據(jù)的具體教程
- 使用Python的requests庫(kù)進(jìn)行網(wǎng)頁(yè)數(shù)據(jù)抓取的詳細(xì)教程
- 利用Python抓取網(wǎng)頁(yè)數(shù)據(jù)的多種方式與示例詳解
相關(guān)文章
Python操作MongoDB數(shù)據(jù)庫(kù)PyMongo庫(kù)使用方法
這篇文章主要介紹了Python操作MongoDB數(shù)據(jù)庫(kù)PyMongo庫(kù)使用方法,本文講解了創(chuàng)建連接、連接數(shù)據(jù)庫(kù)、連接聚集、查看全部聚集名稱、查看聚集的一條記錄等操作方法,需要的朋友可以參考下2015-04-04pycharm連接虛擬機(jī)的實(shí)現(xiàn)步驟
本文主要介紹了pycharm連接虛擬機(jī)的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-12-12python 動(dòng)態(tài)遷移solr數(shù)據(jù)過程解析
這篇文章主要介紹了python 動(dòng)態(tài)遷移solr數(shù)據(jù)過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09Python中xml和dict格式轉(zhuǎn)換的示例代碼
最近在做APP的接口,遇到XML格式的請(qǐng)求數(shù)據(jù),費(fèi)了很大勁來解決,下面小編給大家分享下Python中xml和dict格式轉(zhuǎn)換問題,感興趣的朋友跟隨小編一起看看吧2019-11-11python開啟攝像頭以及深度學(xué)習(xí)實(shí)現(xiàn)目標(biāo)檢測(cè)方法
今天小編就為大家分享一篇python開啟攝像頭以及深度學(xué)習(xí)實(shí)現(xiàn)目標(biāo)檢測(cè)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-08-08python-圖片流傳輸?shù)乃悸芳笆纠?url轉(zhuǎn)換二維碼)
這篇文章主要介紹了python-圖片流傳輸?shù)乃悸芳笆纠?url轉(zhuǎn)換二維碼),幫助大家更好的理解和使用python,感興趣的朋友可以了解下2020-12-12MacBook m1芯片采用miniforge安裝python3.9的方法示例
這篇文章主要介紹了MacBook m1芯片采用miniforge安裝python3.9的方法示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04