1. 项目概述:豆瓣电影Top 250爬虫实战
最近在整理电影片单时,发现手动记录豆瓣Top 250效率太低。作为Python开发者,自然想到用爬虫技术自动化这个流程。这个项目核心是通过Python实现豆瓣电影数据的结构化采集,并生成可直接分析的CSV文件。整个过程涉及请求模拟、页面解析、反爬应对和数据持久化等关键技术点,对爬虫初学者来说是个非常典型的综合练习。
实测完整代码不到100行,但涵盖了网页抓取的全流程。最终输出的CSV包含电影排名、名称、评分、评价人数、经典台词等关键字段,可直接用于数据分析或个性化推荐系统的基础数据。下面我会详细拆解每个环节的技术实现和避坑要点。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心需求与技术方案
2.1 目标数据拆解
豆瓣Top 250页面(https://movie.douban.com/top250)每页展示25部电影,共10页。每部电影需要采集:
- 基础信息:排名、中文名、外文名、评分、评价人数
- 详情数据:导演、主演、类型、制片国家、上映年份
- 特色内容:经典台词(页面底部引用部分)
2.2 技术选型分析
python复制# 基础工具栈
import requests # 网络请求
from bs4 import BeautifulSoup # HTML解析
import csv # 数据导出
import time # 请求间隔控制
import random # 随机延迟
选择Requests而非urllib的原因在于:
- API设计更人性化(session保持、自动编码转换)
- 社区活跃度高(遇到问题容易找到解决方案)
- 对HTTPS支持更完善
BeautifulSoup相比PyQuery的优势:
- 对不完整HTML容错性更好
- 支持多种解析器(本项目用lxml)
- 更符合Python风格的链式调用
3. 反爬策略应对方案
3.1 豆瓣反爬机制实测
测试发现连续请求超过20次会触发验证码,主要防御措施:
- User-Agent检测(必须模拟浏览器)
- 请求频率限制(需设置2-5秒随机间隔)
- Cookie验证(需维持会话)
3.2 完整请求头配置
python复制headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Referer': 'https://movie.douban.com/',
'Connection': 'keep-alive'
}
# 代理IP池示例(可选)
proxies = {
'http': 'http://proxy.example.com:8080',
'https': 'https://proxy.example.com:8080'
}
重要提示:不要使用公开免费代理,豆瓣会封禁常见代理IP段
4. 页面解析关键技术实现
4.1 HTML结构分析
每部电影在源码中对应一个item类div,关键数据位置:
- 排名:
em标签内容 - 标题:
title类span - 评分:
rating_num类span - 评价人数:
star类span中的span文本
4.2 BeautifulSoup定位示例
python复制def parse_movie(item):
title = item.find('span', class_='title').text
rating = item.find('span', class_='rating_num').text
people = item.find('div', class_='star').find_all('span')[-1].text
people = people.replace('人评价', '')
# 处理外文名(可能不存在)
other_title = item.find('span', class_='other')
other_title = other_title.text if other_title else ''
return {
'title': title,
'other_title': other_title.strip(),
'rating': float(rating),
'people': int(people)
}
5. 分页抓取完整流程
5.1 分页URL规律
豆瓣采用start参数控制分页:
code复制第1页:?start=0
第2页:?start=25
...
第10页:?start=225
5.2 带延迟的遍历实现
python复制def crawl_all_pages():
base_url = "https://movie.douban.com/top250"
movies = []
for start in range(0, 250, 25):
url = f"{base_url}?start={start}"
print(f"正在抓取:{url}")
response = requests.get(url, headers=headers)
soup = BeautifulSoup(response.text, 'lxml')
items = soup.find_all('div', class_='item')
for item in items:
movies.append(parse_movie(item))
# 随机延迟避免封禁
time.sleep(random.uniform(2, 5))
return movies
6. CSV导出最佳实践
6.1 中文编码处理
使用utf-8-sig编码解决Excel打开乱码问题:
python复制def save_to_csv(movies, filename):
with open(filename, 'w', newline='', encoding='utf-8-sig') as f:
writer = csv.DictWriter(f, fieldnames=movies[0].keys())
writer.writeheader()
writer.writerows(movies)
6.2 字段顺序优化
调整字段顺序提升可读性:
python复制fieldnames = [
'排名',
'中文名',
'外文名',
'评分',
'评价人数',
'导演',
'主演',
'年份',
'类型',
'国家',
'经典台词'
]
7. 常见问题与解决方案
7.1 请求被拒绝(403错误)
可能原因及对策:
- User-Agent被识别为爬虫 → 更换为最新浏览器UA
- IP被临时封禁 → 暂停1小时后重试
- 缺少必要请求头 → 补全Referer等字段
7.2 数据提取不全
典型定位错误:
- 未考虑多空格情况:
' '.join(text.split()) - 未处理缺失字段:增加
if element else ''判断 - 类名变更:使用contains选择器
soup.select("[class*=title]")
7.3 CSV打开乱码
三种解决方案:
- 使用
utf-8-sig编码(推荐) - 用文本编辑器转码为GBK
- Excel数据导入向导选择编码
8. 项目扩展方向
8.1 数据可视化分析
python复制import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv('douban_top250.csv')
df.plot(kind='scatter', x='评价人数', y='评分')
plt.show()
8.2 自动更新机制
- 每周定时运行(APScheduler)
- 增量更新检测(比较现有排名)
- 自动邮件发送(smtplib)
8.3 数据库存储
改用SQLite持久化:
python复制import sqlite3
conn = sqlite3.connect('movies.db')
df.to_sql('douban_top250', conn, if_exists='replace')
9. 法律与道德注意事项
- 严格遵守豆瓣robots.txt规定
- 检查
/robots.txt发现未禁止/top250
- 检查
- 控制请求频率(≥2秒/次)
- 仅用于个人学习用途
- 不在商业项目中直接使用采集数据
实测建议:白天工作时间请求成功率更高,晚间可能触发更严格的风控
10. 完整代码结构
python复制# -*- coding: utf-8 -*-
"""
豆瓣Top250爬虫
功能:
1. 自动翻页采集
2. 结构化数据提取
3. CSV导出(支持Excel)
"""
import requests
from bs4 import BeautifulSoup
import csv
import time
import random
# 配置区
HEADERS = {...} # 前述请求头
OUTPUT_FILE = 'douban_top250.csv'
def main():
movies = crawl_all_pages()
save_to_csv(movies, OUTPUT_FILE)
print(f"数据已保存到 {OUTPUT_FILE}")
if __name__ == '__main__':
main()
这个项目最值得关注的三个技术点:
- 动态页面结构的稳健解析方法
- 生产级爬虫的异常处理策略
- 中文环境下的数据持久化方案
实际部署时建议添加日志记录(logging模块)和断点续爬功能(记录已抓取页码)。对于大规模采集需求,可以考虑结合Scrapy框架实现分布式爬取,但要注意控制对目标服务器的压力。
