🌟个人主页:编程攻城狮

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

目录

🌷前言:

一、项目介绍

二、环境准备

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
openpyxlExcel 文件操作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 垂直技术社区,欢迎活跃、内容共建。

更多推荐