【爬虫逆向】Python逆向采集猫眼电影票房数据
'# 【爬虫逆向】Python逆向采集猫眼电影票房数据
一、背景与问题
在电影行业数据分析领域,猫眼电影作为国内领先的影院售票平台,其发布的票房数据具有重要参考价值。但该平台对数据采集设置了多重反爬虫机制,常规的requests库无法直接获取。本文将深入解析猫眼电影数据接口的逆向分析过程,重点探讨如何通过代码实现数据采集。
二、基本原理
猫眼电影的数据接口通常采用以下特征:
- 接口地址常包含动态参数(如
/movie/后接电影ID) - 请求参数包含加密字段(如
token) - 使用Cookie维持会话
- 可能存在IP封禁机制
通过Chrome开发者工具分析发现,其核心接口为https://m.maoyan.com/ajax/movieList,该接口返回包含电影票房、评分等关键信息的JSON数据。但直接访问该接口时会发现响应内容包含错误提示,表明需要正确构造请求参数。
三、环境准备
# 安装必要依赖
pip install requests beautifulsoup4import requests
from bs4 import BeautifulSoup
import time
import hashlib四、核心实现
1. 爬虫流程分析
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',
'Referer': 'https://m.maoyan.com/'
}2. 加密参数生成
通过逆向分析发现,token参数采用md5(时间戳+随机字符串)算法生成:
def get_token():
timestamp = str(int(time.time()))
random_str = 'maoyan' # 逆向分析得到的固定字符串
return hashlib.md5((timestamp + random_str).encode()).hexdigest()3. 请求参数构造
def get_params():
token = get_token()
return {
'token': token,
'cityId': '1', # 城市ID,1代表北京
'type': '1', # 电影类型,1代表正在上映
'page': '1', # 页码
'city': '北京' # 城市名称
}4. 请求发送与响应处理
def fetch_movie_data():
url = 'https://m.maoyan.com/ajax/movieList'
params = get_params()
response = requests.get(url, params=params, headers=headers)
if response.status_code == 200:
return response.json()
else:
print(f"请求失败,状态码:{response.status_code}")
return None五、完整案例
1. 完整爬虫流程
def main():
data = fetch_movie_data()
if data and data.get('success'):
movies = data['data']['movies']
for movie in movies:
print(f"电影名称:{movie['name']}")
print(f"票房:{movie['totalBox} 万元")
print(f"评分:{movie['score']}")
print("-" * 50)2. 数据存储
import json
def save_to_file(data, filename='movies.json'):
with open(filename, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=4)3. 完整运行示例
if __name__ == '__main__':
data = fetch_movie_data()
if data and data.get('success'):
save_to_file(data)
main()六、源码解析
1. 加密算法分析
逆向分析发现,token参数生成过程如下:
def get_token():
timestamp = str(int(time.time()))
random_str = 'maoyan'
return hashlib.md5((timestamp + random_str).encode()).hexdigest()关键点:
- 时间戳使用当前秒级时间
- 固定字符串
maoyan是逆向分析得到的 - 使用MD5算法进行加密
2. 请求参数构造
def get_params():
token = get_token()
return {
'token': token,
'cityId': '1',
'type': '1',
'page': '1',
'city': '北京'
}参数说明:
cityId对应城市ID,1为北京type为1表示正在上映的电影page为分页参数,1表示第一页city为城市名称,用于校验
七、进阶使用
1. 多城市数据采集
def get_city_id(city_name):
# 逆向分析得到的城市映射关系
city_map = {
'北京': '1',
'上海': '2',
'广州': '3',
# ...其他城市
}
return city_map.get(city_name, '1')2. 分页处理
def get_all_pages(city='北京'):
city_id = get_city_id(city)
all_data = []
for page in range(1, 11): # 获取前10页数据
params = {
'token': get_token(),
'cityId': city_id,
'type': '1',
'page': str(page),
'city': city
}
response = requests.get(url, params=params, headers=headers)
if response.status_code == 200:
all_data.extend(response.json().get('data', {}).get('movies', []))
return all_data八、性能与工程实践
1. 并发请求优化
from concurrent.futures import ThreadPoolExecutor
def get_all_pages_concurrent(city='北京'):
city_id = get_city_id(city)
results = []
with ThreadPoolExecutor(max_workers=5) as executor:
futures = [executor.submit(fetch_page, city_id, page) for page in range(1, 11)]
for future in futures:
results.extend(future.result())
return results
def fetch_page(city_id, page):
params = {
'token': get_token(),
'cityId': city_id,
'type': '1',
'page': str(page),
'city': '北京'
}
response = requests.get(url, params=params, headers=headers)
if response.status_code == 200:
return response.json().get('data', {}).get('movies', [])
return []2. 缓存机制
import redis
def get_cached_token():
r = redis.Redis(host='localhost', port=6379, db=0)
token = r.get('maoyan_token')
if not token:
token = get_token()
r.setex('maoyan_token', 3600, token) # 缓存1小时
return token九、常见问题与踩坑
1. 常见错误
错误示例:
def get_token():
return 'fixed_token' # 固定值问题分析:
- 时间戳未更新导致token失效
- 未使用MD5算法
- 未包含固定字符串
maoyan
解决方案:
- 使用动态时间戳
- 正确实现MD5加密
- 添加固定字符串
2. 请求头缺失
错误示例:
response = requests.get(url, params=params)问题分析:
- 缺少
User-Agent和Referer头 - 导致服务器拒绝请求
解决方案:
- 补充必要请求头
- 可模拟浏览器访问
3. IP封禁问题
解决方案:
- 使用代理IP池
- 设置请求间隔
- 使用Selenium模拟浏览器
十、最佳实践
- 参数生成:确保时间戳和固定字符串的正确性
- 异常处理:添加重试机制和超时控制
- 数据存储:使用JSON或数据库存储原始数据
- 日志记录:记录请求参数和响应结果
- 法律合规:遵守《计算机软件保护条例》等法律法规
十一、总结
本文通过逆向分析猫眼电影数据接口,深入探讨了Python爬虫的实现方法。重点分析了加密参数生成机制、请求头配置、分页处理等关键技术点,提供了完整的代码示例和实践方案。在实际应用中,需要根据具体需求选择合适的技术方案,同时注意法律风险和安全防护。对于需要大量数据采集的场景,建议结合代理IP池、并发处理等技术提升效率,但也要注意避免对目标服务器造成过大负担。
评论已关闭