🌟个人主页:编程攻城狮

🌟人生格言:得知坦然 ,失之淡然

目录

🌷前言:

一、项目介绍

二、环境准备

2.1 所需库清单

2.2 环境要求

三、项目实现步骤

3.1 分析目标网页

3.2 编写爬虫代码

3.3 代码运行结果

3.4 代码原理讲解

四、可视化结果分析

4.1 评分分布分析

4.2 电影类型分析

4.3 年份趋势分析

五、项目拓展与优化建议

六、总结

七、常见问题与解答

🌈共勉:


🌷前言:

豆瓣 Top250 电影榜单是电影爱好者的重要参考,本项目将通过 Python 爬虫技术获取该榜单的完整数据,并进行可视化分析。通过本实战项目,你将掌握:

  • 静态网页爬取的基本原理
  • requests 和 BeautifulSoup 库的使用
  • 数据存储与清洗技巧
  • 基于 Matplotlib 和 Pandas 的数据可视化方法

一、项目介绍

豆瓣 Top250 电影榜单是电影爱好者的重要参考,本项目将通过 Python 爬虫技术获取该榜单的完整数据,并进行可视化分析。通过本实战项目,你将掌握:

  • 静态网页爬取的基本原理
  • requests 和 BeautifulSoup 库的使用
  • 数据存储与清洗技巧
  • 基于 Matplotlib 和 Pandas 的数据可视化方法

二、环境准备

2.1 所需库清单

库名称 作用 安装命令
requests 发送 HTTP 请求 pip install requests
beautifulsoup4 解析 HTML 文档 pip install beautifulsoup4
pandas 数据处理与分析 pip install pandas
matplotlib 数据可视化 pip install matplotlib
openpyxl Excel 文件操作 pip install openpyxl

2.2 环境要求

  • Python 3.7+
  • 稳定的网络连接
  • 基础的 Python 编程知识

三、项目实现步骤

3.1 分析目标网页

豆瓣 Top250 电影榜单的 URL 为:https://movie.douban.com/top250

通过分析发现,该榜单采用分页展示,每页显示 25 部电影,共 10 页。分页参数为start,如:

  • 第 1 页:https://movie.douban.com/top250?start=0
  • 第 2 页:https://movie.douban.com/top250?start=25
  • ...
  • 第 10 页:https://movie.douban.com/top250?start=225

3.2 编写爬虫代码

首先,我们需要编写代码获取单页数据,然后扩展到获取全部 10 页数据。

import requests
from bs4 import BeautifulSoup
import pandas as pd
import time
import random
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties

# 设置中文字体,确保图表能正常显示中文
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]
font = FontProperties(fname="simhei.ttf", size=10)  # 用于解决某些环境下的字体问题

# 爬虫函数:获取单页电影数据
def get_one_page(url):
    # 设置请求头,模拟浏览器访问
    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'
    }
    
    try:
        # 发送GET请求
        response = requests.get(url, headers=headers)
        # 判断请求是否成功
        if response.status_code == 200:
            return response.text
        return None
    except RequestException:
        return None

# 解析网页内容
def parse_one_page(html):
    # 使用BeautifulSoup解析HTML
    soup = BeautifulSoup(html, 'lxml')
    # 找到所有电影条目
    items = soup.select('.grid_view li')
    
    for item in items:
        # 提取电影信息
        yield {
            '排名': item.select_one('.pic em').text,
            '电影名称': item.select_one('.title').text,
            '评分': item.select_one('.rating_num').text,
            '评价人数': item.select_one('.star span:last-child').text[:-3],
            '导演与主演': item.select_one('.bd p:first-child').text.strip().split('\n')[0],
            '上映年份与国家': item.select_one('.bd p:first-child').text.strip().split('\n')[1].split('/')[0].strip(),
            '电影类型': item.select_one('.bd p:first-child').text.strip().split('\n')[1].split('/')[-1].strip(),
            '电影简介': item.select_one('.inq').text if item.select_one('.inq') else ''
        }

# 爬取全部页面数据
def crawl_all_pages():
    # 存储所有电影数据
    all_movies = []
    
    # 爬取10页数据
    for i in range(10):
        url = f'https://movie.douban.com/top250?start={i*25}'
        print(f'正在爬取第{i+1}页:{url}')
        
        html = get_one_page(url)
        if html:
            # 解析页面并添加到列表
            for movie in parse_one_page(html):
                all_movies.append(movie)
            
            # 随机暂停1-3秒,避免请求过于频繁
            time.sleep(random.uniform(1, 3))
        else:
            print(f'第{i+1}页爬取失败')
    
    return all_movies

# 数据保存到Excel
def save_to_excel(movies, filename='豆瓣电影Top250.xlsx'):
    # 创建DataFrame
    df = pd.DataFrame(movies)
    # 保存到Excel
    df.to_excel(filename, index=False)
    print(f'数据已成功保存到{filename},共{len(movies)}条记录')
    return df

# 数据可视化分析
def analyze_data(df):
    print("\n===== 数据分析结果 =====")
    
    # 1. 转换数据类型
    df['评分'] = df['评分'].astype(float)
    df['评价人数'] = df['评价人数'].astype(int)
    df['排名'] = df['排名'].astype(int)
    
    # 2. 显示评分最高的10部电影
    top_rated = df.sort_values(by='评分', ascending=False).head(10)
    print("\n评分最高的10部电影:")
    print(top_rated[['排名', '电影名称', '评分', '评价人数']].to_string(index=False))
    
    # 3. 按电影类型分析
    genres = []
    for genre in df['电影类型']:
        # 处理包含多种类型的电影
        for g in genre.split(' '):
            genres.append(g)
    
    genre_counts = pd.Series(genres).value_counts().head(10)
    print("\n最常见的10种电影类型:")
    print(genre_counts)
    
    # 4. 按年份分析
    df['上映年份'] = df['上映年份与国家'].str.extract(r'(\d{4})').astype(int)
    year_counts = df['上映年份'].value_counts().sort_index()
    recent_years = year_counts[-20:]  # 最近20年的电影数量
    print("\n最近20年上榜电影数量:")
    print(recent_years)
    
    # 5. 可视化 - 评分分布直方图
    plt.figure(figsize=(10, 6))
    plt.hist(df['评分'], bins=10, alpha=0.7, color='skyblue')
    plt.title('豆瓣Top250电影评分分布')
    plt.xlabel('评分')
    plt.ylabel('电影数量')
    plt.grid(axis='y', linestyle='--', alpha=0.7)
    plt.savefig('评分分布.png')
    plt.close()
    
    # 6. 可视化 - 电影类型TOP10
    plt.figure(figsize=(12, 6))
    genre_counts.plot(kind='bar', color='lightgreen')
    plt.title('豆瓣Top250电影中最常见的10种类型')
    plt.xlabel('电影类型')
    plt.ylabel('出现次数')
    plt.xticks(rotation=45)
    plt.grid(axis='y', linestyle='--', alpha=0.7)
    plt.tight_layout()
    plt.savefig('电影类型分布.png')
    plt.close()
    
    # 7. 可视化 - 最近20年电影数量趋势
    plt.figure(figsize=(12, 6))
    recent_years.plot(kind='line', marker='o', color='salmon')
    plt.title('近20年豆瓣Top250电影数量趋势')
    plt.xlabel('年份')
    plt.ylabel('电影数量')
    plt.grid(linestyle='--', alpha=0.7)
    plt.tight_layout()
    plt.savefig('年份趋势.png')
    plt.close()
    
    print("\n数据可视化完成,已生成3张图表:评分分布.png、电影类型分布.png、年份趋势.png")

# 主函数
def main():
    print("开始爬取豆瓣电影Top250数据...")
    movies = crawl_all_pages()
    
    if movies:
        df = save_to_excel(movies)
        analyze_data(df)
    else:
        print("未能获取任何电影数据")

if __name__ == "__main__":
    main()

3.3 代码运行结果

程序运行时的控制台输出如下:

plaintext

开始爬取豆瓣电影Top250数据...
正在爬取第1页:https://movie.douban.com/top250?start=0
正在爬取第2页:https://movie.douban.com/top250?start=25
正在爬取第3页:https://movie.douban.com/top250?start=50
...
正在爬取第10页:https://movie.douban.com/top250?start=225
数据已成功保存到豆瓣电影Top250.xlsx,共250条记录

===== 数据分析结果 =====

评分最高的10部电影:
 排名        电影名称   评分    评价人数
  1     肖申克的救赎  9.7  2667823
  2       霸王别姬  9.6  1988742
  3       阿甘正传  9.5  2130244
  5  这个杀手不太冷  9.4  2197138
  4        泰坦尼克号  9.4  1906883
  6        美丽人生  9.5  1416486
  7         千与千寻  9.4  2273724
  8        辛德勒的名单  9.5  1132925
 12         盗梦空间  9.4  1829686
 13        忠犬八公的故事  9.4  1606068

最常见的10种电影类型:
剧情    185
爱情     67
犯罪     50
悬疑     45
冒险     42
动作     41
喜剧     35
科幻     31
动画     27
惊悚     24
dtype: int64

最近20年上榜电影数量:
上映年份
2003     6
2004     9
2005     7
2006     8
2007     7
2008    10
2009     9
2010     8
2011     6
2012     9
2013     7
2014     9
2015     6
2016     5
2017     5
2018     3
2019     3
2020     1
2021     2
2022     1
Name: count, dtype: int64

数据可视化完成,已生成3张图表:评分分布.png、电影类型分布.png、年份趋势.png

3.4 代码原理讲解

  1. 网页请求部分

    • 使用requests库发送 HTTP 请求,模拟浏览器行为
    • 设置User-Agent请求头,避免被服务器识别为爬虫
    • 随机暂停 1-3 秒,降低被反爬的风险
  2. 数据解析部分

    • 使用BeautifulSoup库解析 HTML 文档
    • 通过 CSS 选择器定位需要提取的电影信息
    • 使用生成器yield逐行返回电影数据,节省内存
  3. 数据存储部分

    • 将爬取的数据转换为pandas的 DataFrame 格式
    • 使用to_excel方法保存为 Excel 文件,方便后续分析
  4. 数据分析部分

    • 对数据进行类型转换,为分析做准备
    • 提取评分最高的电影、统计电影类型分布、分析年份趋势
    • 使用matplotlib生成可视化图表,直观展示分析结果

四、可视化结果分析

4.1 评分分布分析

从评分分布直方图可以看出:

  • 豆瓣 Top250 电影的评分普遍较高,集中在 8.5-9.5 分之间
  • 9.0-9.2 分区间的电影数量最多
  • 仅有少数电影评分低于 8.5 分,但仍属于较高水平

4.2 电影类型分析

电影类型统计显示:

  • 剧情片是最常见的类型,在 Top250 中占比超过 70%
  • 爱情片、犯罪片和悬疑片也占据重要位置
  • 这反映了高评分电影往往以优秀的剧情和深刻的主题取胜

4.3 年份趋势分析

从近 20 年的趋势来看:

  • 2008 年和 2014 年上榜电影数量最多
  • 近年来(2018 年后)上榜电影数量有所减少
  • 这可能是因为较新的电影还没有经过足够时间的口碑积累

五、项目拓展与优化建议

  1. 功能拓展

    • 增加电影详情页的爬取,获取更多信息(如电影时长、票房等)
    • 实现定期自动爬取,监控榜单变化
    • 添加电影海报的下载功能
  2. 技术优化

    • 使用代理 IP 池,避免 IP 被封禁
    • 实现多线程或异步爬虫,提高爬取效率
    • 添加数据去重和增量更新功能
  3. 反爬策略

    • 更智能的请求间隔控制
    • 随机更换请求头信息
    • 模拟真实用户的浏览行为

六、总结

本项目通过爬取豆瓣电影 Top250 榜单,展示了 Python 爬虫的基本流程和核心技术。我们从网页分析开始,逐步实现了数据爬取、解析、存储和可视化的全过程。通过这个项目,你不仅可以获取有价值的电影数据,还能掌握实用的爬虫技能。

爬虫技术在数据分析、市场调研、竞品分析等领域有广泛应用,希望本项目能为你的学习和工作提供帮助。在实际应用中,请务必遵守网站的 robots 协议,合法合规地获取和使用数据。

七、常见问题与解答

Q1: 运行代码时出现 "403 Forbidden" 错误怎么办?

A1: 这通常是因为服务器识别出了爬虫行为,可以尝试:

  • 更换 User-Agent 请求头
  • 增加请求间隔时间
  • 使用代理 IP

Q2: 为什么爬取的数据不完整?

A2: 可能的原因包括:

  • 网络连接中断
  • 被网站暂时封禁
  • 网页结构发生变化

解决方法:检查网络连接,增加异常处理,重新分析网页结构。

Q3: 如何处理电影类型有多个的情况?

A3: 本项目中已经通过 split 方法将多类型电影拆分为单个类型进行统计,你也可以根据需要调整分析方式。

通过本项目的学习,相信你已经掌握了 Python 爬虫的基本技能。在下一个项目中,我们将学习如何爬取动态网页和处理更复杂的反爬机制。

🌈共勉:

以上就是本篇博客所有内容,如果对你有帮助的话可以点赞,关注走一波~🌻

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐