猫眼检索返回内容混杂影片、演出、广告推广条目,很多常规方案只做简单请求,缺少分类过滤和异常兼容。本文以业务分层思路封装检索逻辑,优先区分影片类型,统一输出字段,适配后续批量同步、详情联动场景。重点处理签名校验、会话保持、无效条目剔除,规避字体加密带来的数据错乱问题。 这套方案和普通抓取教程的区别,是增加类型过滤判断,避免混进演出、票务推广数据。移动端数据服务返回结构更简洁,相比 PC 端可以避开大部分静态页面字体加密干扰。session 复用头部信息,减少频繁新建连接带来的拦截风险。 落地阶段有几个高频卡点。第一,请求头不能随意简化,移动端 UA 与 Referer 缺失极易返回空数据;第二,平台有访问频次管控,连续翻页建议设置 0.6s 以上间隔,高频请求容易触发校验;第三,评分字段存在字体加密场景,拿到后不要直接入库使用,仅作为展示参考;第四,分页判断不要硬写循环次数,根据返回 total 动态终止,减少无效请求。 检索拿到 item_id 之后,可以直接传入影片详情拉取逻辑,形成完整的数据链路。长期同步场景,建议以 item_id 作为唯一标识做去重,减少重复存储。该封装轻量化,适合中小规模影片快照采集,兼顾返回稳定性和数据纯净度
import requests
import time
class MaoyanSearchFetch:
def __init__(self):
self.session = requests.Session()
self.base_url = "https://m.maoyan.com/search/ajaxSearch"
self.headers = {
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1",
"Referer": "https://m.maoyan.com/",
"Accept": "application/json"
}
def fetch_search_list(self, keyword, page=1, limit=10):
params = {
"kw": keyword,
"offset": (page - 1) * limit,
"limit": limit
}
try:
resp = self.session.get(self.base_url, params=params, headers=self.headers, timeout=10)
resp.raise_for_status()
res_data = resp.json()
result_list = []
items = res_data.get("data", {}).get("list", [])
for item in items:
# 只保留影片,过滤演出、广告类数据
if item.get("type") != 1:
continue
row = {
"item_id": item.get("id"),
"title": item.get("nm"),
"poster": item.get("img"),
"score": item.get("sc"),
"release_time": item.get("rt"),
"category": item.get("cat"),
"area": item.get("src")
}
result_list.append(row)
return {
"code": res_data.get("code"),
"total": res_data.get("data", {}).get("total"),
"list": result_list
}
except Exception as err:
print(f"检索异常:{err}")
return None
if __name__ == "__main__":
spider = MaoyanSearchFetch()
ret = spider.fetch_search_list(keyword="流浪地球", page=1, limit=10)
if ret:
for info in ret["list"]:
print(info)