【Python】爬虫练习-爬取豆瓣网电影评论用户的观影习惯数据
'# 【Python】爬虫练习-爬取豆瓣网电影评论用户的观影习惯数据
一、背景与问题
在数据分析领域,爬取用户行为数据是理解用户画像的重要手段。以豆瓣电影评论数据为例,通过分析用户的观影评分、评论内容、观影时间等维度,可以构建用户画像模型,为推荐系统、市场策略等提供数据支持。
但实际开发中存在以下核心问题:
- 豆瓣的反爬机制(如IP封禁、验证码识别)
- 大数据量下的性能瓶颈
- 数据存储与清洗的工程问题
- 合法合规的边界界定
需要特别注意:本文示例仅用于技术研究和教学目的,实际生产环境使用时需严格遵守《中华人民共和国计算机信息网络国际联网安全保护管理办法》等法律法规,遵守豆瓣网的robots.txt协议。
二、基本原理
1. HTTP请求流程
爬虫核心是模拟浏览器发送HTTP请求,获取服务器返回的HTML文档。具体流程如下:
import requests
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
}
response = requests.get('https://movie.douban.com/subject/1292052/comments', headers=headers)
print(response.status_code)2. HTML解析机制
使用BeautifulSoup解析HTML结构,提取目标数据:
from bs4 import BeautifulSoup
soup = BeautifulSoup(response.text, 'html.parser')
comments = soup.select('.comment-content') # 选择评论内容3. 反爬机制应对
豆瓣采用多层反爬策略,包括:
- IP封禁(30秒内请求超过5次)
- User-Agent检测
- 验证码识别(部分页面)
- 动态加载内容(JavaScript渲染)
三、环境准备
pip install requests beautifulsoup4 fake_useragent pandas推荐使用虚拟环境进行开发,建议配置如下:
# 环境配置示例
import os
os.environ['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'四、核心实现
1. 请求参数构造
def get_comments(movie_id, start=0, count=20):
url = f'https://movie.douban.com/subject/{movie_id}/comments'
params = {
'start': start,
'limit': count,
'sort': 'new'
}
return requests.get(url, params=params, headers=headers)2. 数据解析逻辑
def parse_comments(html):
soup = BeautifulSoup(html, 'html.parser')
comments = []
for item in soup.select('.comment-item'):
user = item.select_one('.comment-header .name').text.strip()
rating = float(item.select_one('.rating')['class'][1][1:])
content = item.select_one('.comment-content').text.strip()
comments.append({
'user': user,
'rating': rating,
'content': content
})
return comments3. 分页处理逻辑
def fetch_all_comments(movie_id, max_pages=5):
all_comments = []
for page in range(max_pages):
response = get_comments(movie_id, start=page*20)
if response.status_code != 200:
break
all_comments.extend(parse_comments(response.text))
return all_comments五、完整案例
1. 实现完整的爬虫流程
import json
import time
import requests
from bs4 import BeautifulSoup
from fake_useragent import UserAgent
# 配置参数
headers = {
'User-Agent': UserAgent().random
}
movie_id = '1292052' # 《肖申克的救赎》电影ID
output_file = 'douban_comments.csv'
def main():
comments = fetch_all_comments(movie_id)
with open(output_file, 'w', encoding='utf-8') as f:
for comment in comments:
f.write(json.dumps(comment, ensure_ascii=False) + '\n')
print(f"共获取{len(comments)}条评论,已保存至{output_file}")
if __name__ == '__main__':
main()2. 数据清洗示例
import pandas as pd
# 读取数据
df = pd.read_csv('douban_comments.csv')
# 清洗数据
df['content'] = df['content'].str.replace('\n', ' ').str.strip()
df['rating'] = df['rating'].astype(float)
# 保存清洗后的数据
df.to_csv('douban_comments_clean.csv', index=False)六、源码解析
1. User-Agent动态生成
from fake_useragent import UserAgent
ua = UserAgent()
headers = {'User-Agent': ua.random}使用fake_useragent库动态生成随机User-Agent,避免被识别为爬虫。
2. 分页参数处理
params = {
'start': start,
'limit': count,
'sort': 'new'
}豆瓣API支持分页参数,start为起始位置,limit为每页数量。
3. 异常处理机制
try:
response = requests.get(url, params=params, headers=headers, timeout=10)
except requests.exceptions.RequestException as e:
print(f"请求异常: {e}")
return []添加异常捕获机制,避免程序因网络问题崩溃。
七、进阶使用
1. 使用代理IP池
import random
proxies = [
{'http': 'http://10.10.1.10:3128', 'https': 'http://10.10.1.10:1080'},
{'http': 'http://10.10.2.10:3128', 'https': 'http://10.10.2.10:1080'}
]
def get_comments(...):
proxy = random.choice(proxies)
return requests.get(..., proxies=proxy)2. 使用Selenium处理动态内容
from selenium import webdriver
driver = webdriver.Chrome()
driver.get('https://movie.douban.com/subject/1292052/comments')
comments = driver.find_elements_by_css_selector('.comment-content')3. 使用异步请求优化性能
import aiohttp
import asyncio
async def fetch(session, url):
async with session.get(url) as response:
return await response.text()
async def main():
async with aiohttp.ClientSession() as session:
tasks = [fetch(session, url) for _ in range(10)]
results = await asyncio.gather(*tasks)八、性能与工程实践
1. 性能优化策略
- 使用异步IO处理请求
- 配置线程池进行并发处理
添加请求间隔防止IP被封
import time def safe_request(func): def wrapper(*args, **kwargs): time.sleep(1) # 添加1秒间隔 return func(*args, **kwargs) return wrapper
2. 数据存储优化
- 使用数据库索引加速查询
- 对文本字段进行分词处理
- 建立数据缓存机制
3. 安全风险防控
- 避免大规模爬取
- 使用代理IP池
- 定期更换User-Agent
- 添加请求频率限制
九、常见问题与踩坑
1. 常见错误及解决办法
| 错误现象 | 原因分析 | 解决方案 |
|---|---|---|
| 403 Forbidden | User-Agent被识别 | 更换随机User-Agent |
| 503服务不可用 | 被限流 | 添加请求间隔 |
| 无法解析内容 | 页面结构变化 | 更新CSS选择器 |
| 验证码弹窗 | 需要人工验证 | 使用Selenium处理 |
2. 常见性能瓶颈
- 单线程请求导致速度慢
- 未处理异常导致程序崩溃
- 未进行数据清洗导致存储效率低
3. 常见安全风险
- IP被封禁
- 数据泄露
- 被反爬机制识别
- 违反服务条款
十、最佳实践
1. 推荐方案
- 使用异步IO提高并发能力
- 动态生成User-Agent和代理IP
- 添加请求频率限制
- 实现完整的异常处理机制
- 使用缓存减少重复请求
2. 使用场景
- 研究用户行为模式
- 构建推荐系统数据
- 进行市场趋势分析
- 生成用户画像报告
3. 不推荐场景
- 大规模数据采集
- 频繁访问同一接口
- 未处理反爬机制
- 违反服务条款
十一、总结
通过本次实践,我们深入探讨了爬取豆瓣电影评论数据的技术实现,涵盖了从请求发送到数据处理的完整流程。在实际开发中,需要综合考虑反爬机制、性能优化、安全风险等多方面因素。
对于技术开发者,建议:
- 优先使用异步IO提升性能
- 动态生成请求参数避免被识别
- 完善异常处理机制
- 遵守法律法规和平台规则
- 使用缓存和分页机制优化资源利用
在实际项目中,根据具体需求选择合适的方案,既要保证数据质量,又要避免法律风险。通过合理的技术选型和工程实践,可以有效实现爬虫系统的稳定运行。
评论已关闭