對于經常寫爬蟲的技術來說了,可視化大大的提高工作效率,可以讓獲取的數據更直觀的展示在面前,下面我將通過具體實操給大家展示下多種可視化具體教程,希望能都幫助大家。
下面是一個完整的Python爬蟲和數據可視化解決方案,我們將爬取豆瓣電影Top250數據并進行多種可視化展示。
import requests
from bs4 import BeautifulSoup
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.font_manager import FontProperties
import time
import random
from wordcloud import WordCloud
import jieba
from collections import Counter# 設置中文字體
font = FontProperties(fname=r"simhei.ttf", size=12)
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用來正常顯示中文標簽
plt.rcParams['axes.unicode_minus'] = False # 用來正常顯示負號# 爬取豆瓣電影Top250數據
def scrape_douban_top250():base_url = "https://movie.douban.com/top250"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'}movies = []for start in range(0, 250, 25):url = f"{base_url}?start={start}"try:response = requests.get(url, headers=headers)response.raise_for_status()soup = BeautifulSoup(response.text, 'html.parser')items = soup.find_all('div', class_='item')for item in items:# 排名rank = item.find('em').text# 標題title = item.find('span', class_='title').text# 信息info = item.find('div', class_='bd').p.text.strip().split('\n')[0].strip()# 評分rating = item.find('span', class_='rating_num').text# 評價人數num_ratings = item.find('div', class_='star').find_all('span')[-1].text[:-3]# 簡介quote_tag = item.find('span', class_='inq')quote = quote_tag.text if quote_tag else ""# 提取年份和地區info_parts = info.split('/')year = info_parts[0].strip()[-4:] # 提取年份region = info_parts[1].strip() if len(info_parts) > 1 else "未知"movies.append({'排名': int(rank),'標題': title,'年份': int(year) if year.isdigit() else 0,'地區': region,'評分': float(rating),'評價人數': int(num_ratings.replace(',', '')) if num_ratings else 0,'簡介': quote})# 隨機延時,避免請求過快time.sleep(random.uniform(1, 2))except Exception as e:print(f"爬取第 {start//25 + 1} 頁時出錯: {e}")return movies# 數據可視化
def visualize_movie_data(df):# 1. 創建畫布plt.figure(figsize=(18, 12))plt.suptitle('豆瓣電影Top250數據分析', fontsize=20, fontweight='bold', fontproperties=font)# 2. 評分分布直方圖plt.subplot(2, 3, 1)sns.histplot(df['評分'], bins=20, kde=True, color='skyblue')plt.title('電影評分分布', fontproperties=font)plt.xlabel('評分', fontproperties=font)plt.ylabel('電影數量', fontproperties=font)plt.axvline(df['評分'].mean(), color='red', linestyle='dashed', linewidth=1)plt.text(df['評分'].mean()+0.05, 20, f'平均分: {df["評分"].mean():.2f}', color='red')# 3. 評分與年份的關系plt.subplot(2, 3, 2)sns.scatterplot(x='年份', y='評分', data=df, hue='評分', palette='coolwarm', size='評價人數', sizes=(20, 200))plt.title('評分與年份的關系', fontproperties=font)plt.xlabel('年份', fontproperties=font)plt.ylabel('評分', fontproperties=font)plt.xticks(rotation=45)# 4. 各地區電影數量plt.subplot(2, 3, 3)region_counts = df['地區'].value_counts().head(8)colors = plt.cm.Paired(np.linspace(0, 1, len(region_counts)))region_counts.plot(kind='pie', autopct='%1.1f%%', colors=colors, shadow=True, startangle=90)plt.title('各地區電影占比', fontproperties=font)plt.ylabel('')# 5. 評分TOP10電影plt.subplot(2, 3, 4)top10 = df.sort_values('評分', ascending=False).head(10)sns.barplot(x='評分', y='標題', data=top10, palette='viridis')plt.title('評分TOP10電影', fontproperties=font)plt.xlabel('評分', fontproperties=font)plt.ylabel('電影標題', fontproperties=font)for i, v in enumerate(top10['評分']):plt.text(v - 0.4, i, str(v), color='white', va='center', fontweight='bold')# 6. 評價人數TOP10電影plt.subplot(2, 3, 5)top10_popular = df.sort_values('評價人數', ascending=False).head(10)sns.barplot(x='評價人數', y='標題', data=top10_popular, palette='magma')plt.title('評價人數TOP10電影', fontproperties=font)plt.xlabel('評價人數', fontproperties=font)plt.ylabel('電影標題', fontproperties=font)# 7. 年份分布plt.subplot(2, 3, 6)sns.countplot(x='年份', data=df, order=df['年份'].value_counts().index.sort_values(), palette='Set2')plt.title('電影年份分布', fontproperties=font)plt.xlabel('年份', fontproperties=font)plt.ylabel('數量', fontproperties=font)plt.xticks(rotation=90)plt.tight_layout(rect=[0, 0, 1, 0.96])plt.savefig('movie_analysis.png', dpi=300)plt.show()# 8. 詞云圖 - 電影標題關鍵詞all_titles = ' '.join(df['標題'])word_list = jieba.cut(all_titles)word_count = Counter(word_list)# 過濾單字詞filtered_words = {word: count for word, count in word_count.items() if len(word) > 1 and word not in ['電影', '豆瓣']}wc = WordCloud(font_path='simhei.ttf',background_color='white',max_words=200,width=1000,height=700).generate_from_frequencies(filtered_words)plt.figure(figsize=(12, 8))plt.imshow(wc, interpolation='bilinear')plt.title('電影標題關鍵詞詞云', fontsize=16, fontproperties=font)plt.axis('off')plt.savefig('movie_wordcloud.png', dpi=300)plt.show()# 主函數
def main():print("開始爬取豆瓣電影Top250數據...")movies = scrape_douban_top250()print(f"成功爬取 {len(movies)} 部電影數據")# 創建DataFramedf = pd.DataFrame(movies)# 保存到CSVdf.to_csv('douban_top250.csv', index=False, encoding='utf_8_sig')print("數據已保存到 douban_top250.csv")# 數據可視化print("開始數據可視化...")visualize_movie_data(df)print("可視化完成,結果已保存為 movie_analysis.png 和 movie_wordcloud.png")if __name__ == "__main__":main()
代碼功能說明
1. 數據爬取部分
- 使用requests庫爬取豆瓣電影Top250的10個頁面
- 使用BeautifulSoup解析HTML
- 提取每部電影的排名、標題、年份、地區、評分、評價人數和簡介
- 添加隨機延時避免請求過快被封禁
2. 數據可視化部分
創建了7個可視化圖表和1個詞云圖:
- 評分分布直方圖:展示電影評分的分布情況,包含平均分參考線
- 評分與年份關系散點圖:展示電影評分隨年份的變化趨勢
- 地區分布餅圖:展示電影的地區分布比例
- 評分TOP10電影:展示評分最高的10部電影
- 評價人數TOP10電影:展示評價人數最多的10部電影
- 年份分布圖:展示電影在不同年份的數量分布
- 電影標題關鍵詞詞云:展示電影標題中出現頻率最高的關鍵詞
3. 數據保存
- 將爬取的數據保存為CSV文件(douban_top250.csv)
- 將可視化結果保存為PNG圖片
運行要求
- 安裝必要的Python庫:
pip install requests beautifulsoup4 pandas matplotlib seaborn jieba wordcloud
- 需要中文字體支持:
- 代碼中使用了"simhei.ttf"(黑體),請確保系統中存在該字體
- 或者替換為其他支持中文的字體文件路徑
注意事項
-
網絡爬蟲可能受到網站反爬策略的限制,如果爬取失敗,請嘗試:
- 增加請求頭中的User-Agent信息
- 增加請求之間的延時
- 使用代理IP
-
本代碼僅用于學習目的,請尊重網站的數據使用政策
運行此代碼后,我們將獲得一個包含爬取數據的CSV文件和多張高質量的可視化圖表圖片,總體來說數據展示的還是挺直觀的,如有任何問題可以留言討論。