利用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ù)量(萬(wàn)名)和機(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ù)量(萬(wàn)名)'])
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ù)量(萬(wàn)名)', color=color)
ax1.plot(dates, individual_investors, color=color, label='個(gè)人投資者數(shù)量(萬(wàn)名)', 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-04
pycharm連接虛擬機(jī)的實(shí)現(xiàn)步驟
本文主要介紹了pycharm連接虛擬機(jī)的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-12-12
python 動(dòng)態(tài)遷移solr數(shù)據(jù)過程解析
這篇文章主要介紹了python 動(dòng)態(tài)遷移solr數(shù)據(jù)過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09
Python中xml和dict格式轉(zhuǎn)換的示例代碼
最近在做APP的接口,遇到XML格式的請(qǐng)求數(shù)據(jù),費(fèi)了很大勁來(lái)解決,下面小編給大家分享下Python中xml和dict格式轉(zhuǎn)換問題,感興趣的朋友跟隨小編一起看看吧2019-11-11
python開啟攝像頭以及深度學(xué)習(xí)實(shí)現(xiàn)目標(biāo)檢測(cè)方法
今天小編就為大家分享一篇python開啟攝像頭以及深度學(xué)習(xí)實(shí)現(xiàn)目標(biāo)檢測(cè)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2018-08-08
python-圖片流傳輸?shù)乃悸芳笆纠?url轉(zhuǎn)換二維碼)
這篇文章主要介紹了python-圖片流傳輸?shù)乃悸芳笆纠?url轉(zhuǎn)換二維碼),幫助大家更好的理解和使用python,感興趣的朋友可以了解下2020-12-12
MacBook m1芯片采用miniforge安裝python3.9的方法示例
這篇文章主要介紹了MacBook m1芯片采用miniforge安裝python3.9的方法示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04

