Python 爬虫入门实战:爬取豆瓣电影 Top 250

1. 项目简介

本项目是一个面向初学者的 Python 爬虫实战项目,目标是爬取豆瓣电影 Top 250 榜单的数据,并将其保存为结构化的 CSV 文件。通过这个项目,你将学习到:

  • 如何使用 requests 库发送 HTTP 请求获取网页内容。
  • 如何使用 BeautifulSoup 库解析 HTML 并提取所需数据。
  • 如何应对简单的反爬机制(如请求头设置)。
  • 如何将爬取的数据进行清洗并保存到本地文件。

2. 环境准备

在开始之前,请确保你的电脑上已经安装了 Python(建议版本 3.7 或以上)。我们将使用 pip 来安装必要的第三方库。

打开终端或命令行,执行以下命令:

bash 复制代码
pip install requests beautifulsoup4

安装完成后,可以创建一个新的 Python 文件,例如 douban_spider.py

3. 分析目标网页

首先,我们需要分析豆瓣电影 Top 250 页面的结构,以确定如何定位我们需要的数据。

  1. 打开浏览器,访问 豆瓣电影 Top 250
  2. F12 打开开发者工具,使用"检查元素"功能。
  3. 观察页面,我们发现每部电影信息都包含在一个 class="item"div 标签中。
  4. 我们需要提取的信息通常包括:
    • 电影排名
    • 电影名称
    • 评分
    • 评价人数
    • 经典台词(引语)

4. 编写爬虫代码

下面我们将分步骤编写完整的爬虫代码。

4.1 导入库与定义基础变量

python 复制代码
import requests
from bs4 import BeautifulSoup
import csv
import time

# 目标URL
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'
}

# 用于存储所有电影信息的列表
all_movies = []

4.2 实现单页数据抓取函数

我们需要一个函数来处理单个页面的抓取和解析。

python 复制代码
def scrape_page(url):
    """抓取并解析单个页面"""
    try:
        response = requests.get(url, headers=headers)
        response.raise_for_status()  # 检查请求是否成功
        response.encoding = 'utf-8'  # 设置编码
        soup = BeautifulSoup(response.text, 'html.parser')
        return soup
    except requests.RequestException as e:
        print(f"请求页面失败: {url}, 错误: {e}")
        return None

4.3 实现数据解析函数

这个函数从解析好的 soup 对象中提取我们需要的数据。

这里是比较重要的一点,如果你们对于html网页结构不熟悉的话,可以设计一个代码以及一个专用与解析网页的智能体去生成代码,以此来防止解析时出现一些空结构。

python 复制代码
def parse_movies(soup):
    """从页面中解析电影信息"""
    movie_items = soup.find_all('div', class_='item')
    page_movies = []

    for item in movie_items:
        # 电影排名
        rank = item.find('em').get_text() if item.find('em') else 'N/A'

        # 电影标题 (取第一个 title 属性)
        title_tag = item.find('span', class_='title')
        title = title_tag.get_text() if title_tag else 'N/A'

        # 评分
        rating_tag = item.find('span', class_='rating_num')
        rating = rating_tag.get_text() if rating_tag else 'N/A'

        # 评价人数 ------ 修复:先判断 star 容器是否存在
        star_div = item.find('div', class_='star')
        if star_div:
            span_list = star_div.find_all('span')
            if span_list:
                comment_text = span_list[-1].get_text()
                comment = comment_text[:-3]  # 去掉"人评价"
            else:
                comment = '0'
        else:
            comment = '0'

        # 经典台词(引语),可能不存在
        quote_tag = item.find('span', class_='inq')
        quote = quote_tag.get_text() if quote_tag else ''

        movie_info = {
            '排名': rank,
            '标题': title,
            '评分': rating,
            '评价人数': comment,
            '引语': quote
        }
        page_movies.append(movie_info)
        # 打印进度
        print(f"已抓取: {rank} {title}")

    return page_movies

4.3 实现翻页与主循环

豆瓣 Top 250 有 10 页,我们需要循环处理每一页。

python 复制代码
def main():
    for page in range(0, 10):  # 0-9 对应第1到第10页
        start = page * 25
        url = f'{base_url}?start={start}&filter='
        print(f"正在抓取第 {page + 1} 页: {url}")

        soup = scrape_page(url)
        if not soup:
            print(f"第 {page + 1} 页抓取失败,跳过。")
            continue

        movies = parse_movies(soup)
        all_movies.extend(movies)

        # 礼貌性延迟,避免请求过快
        time.sleep(2)

    print(f"所有页面抓取完成,共 {len(all_movies)} 条数据。")

4.4 实现数据保存函数

最后,我们将数据保存到 CSV 文件中。

python 复制代码
def save_to_csv(movies, filename='douban_top250.csv'):
    """将电影列表保存为CSV文件"""
    if not movies:
        print("没有数据可保存。")
        return

    # 定义CSV文件的列名
    fieldnames = ['排名', '标题', '评分', '评价人数', '引语']

    try:
        with open(filename, 'w', newline='', encoding='utf-8-sig') as csvfile:
            writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
            writer.writeheader()
            writer.writerows(movies)
        print(f"数据已成功保存到 {filename}")
    except IOError as e:
        print(f"保存文件时出错: {e}")

4.5 完整代码与执行

将以上所有部分组合起来,并添加程序入口。

python 复制代码
if __name__ == '__main__':
    main()
    save_to_csv(all_movies)

5. 运行与结果

  1. 将完整的代码保存到 douban_spider.py

  2. 在终端中运行该脚本:

    bash 复制代码
    python douban_spider.py
  3. 程序将开始爬取,并在控制台打印进度。爬取完成后,会在当前目录下生成一个名为 douban_top250.csv 的文件,你可以用 Excel 或文本编辑器打开查看数据。

6. 项目总结与扩展

恭喜!你已经完成了一个基础的网络爬虫项目。这个项目涵盖了爬虫的核心步骤:请求、解析、存储。

你可以尝试以下扩展练习来提升技能:

  1. 异常处理增强:为网络请求和文件操作添加更完善的异常处理。
  2. 数据清洗:清洗"评价人数"字段中的数字,并转换为整数类型。
  3. 存储到数据库 :尝试使用 sqlite3pymysql 将数据保存到数据库中。
  4. 爬取更多信息:尝试爬取每部电影的详情页链接,并进入详情页抓取导演、演员、类型等信息。
  5. 使用 Scrapy 框架:当项目变得复杂时,可以学习使用更专业的 Scrapy 框架来重写这个爬虫。

重要提醒 :爬虫应遵守网站的 robots.txt 协议,尊重网站版权,不要进行高频访问,避免对目标服务器造成压力。

相关推荐
爱写代码的倒霉蛋1 小时前
实现协程的三种方式
开发语言·python
崖边看雾2 小时前
记录Python学习——第一章环境安装下载(Windows)
windows·python·学习·pycharm
CS创新实验室2 小时前
NumPy数组的C风格和Fortran风格
c语言·开发语言·numpy
用户298698530142 小时前
Python 实现 Excel 到 ODS、XPS、PostScript 及 PDF/A-1b 的格式转换
后端·python·excel
本地化文档2 小时前
xlwings-docs-l10n
python·github·excel·gitcode·sphinx
逝水无殇3 小时前
C# 正则表达式详解
开发语言·后端·正则表达式·c#
朱永博3 小时前
使用Onnruntime实现Padim/Patchcore推理
开发语言·c#
前端H3 小时前
Biome & Rolldown:Rust 工具链接管前端基建
开发语言·前端·rust
天天进步20153 小时前
UI-TARS 源码解析 #4:UI-TARS 与传统 RPA 的区别:为什么它不是简单的坐标点击脚本?
开发语言