10 KiB
玩偶聚合 Spider 设计
日期: 2026-04-20
目标
在当前 py/ Spider 仓库中新增一个“玩偶聚合”源,提供以下能力:
- 以站点为一级分类展示聚合站。
- 每个站点在分类页内继续使用原站分类和筛选项。
- 搜索时并发请求多个站点,并将同片结果聚合为单条记录。
- 聚合详情页合并多个站点的网盘分享线路。
playerContent不展开网盘剧集,只透传分享链接。
明确不做:
- 独立管理后台。
- 监控页面。
- 常驻定时域名巡检任务。
- 在 Spider 内调用网盘驱动展开剧集列表。
现状与约束
当前仓库是单文件 Python Spider 集合,统一继承 base/spider.py 中的 Spider 基类,测试使用 unittest 和 unittest.mock。现有仓库已接受以下模式:
homeContent返回class和可选filters。categoryContent使用extend解析筛选参数。detailContent可以返回网盘分享链接组成的vod_play_from/vod_play_url。playerContent可以对网盘链接做原样透传。- 返回列表结果时不包含
pagecount。
因此,新 Spider 必须遵守当前仓库接口和测试风格,而不是照搬原始 Node/Fastify 插件结构。
方案选择
采用“配置驱动的单 Spider 聚合层”方案:
- 新增单文件
玩偶聚合.py。 - 文件内部包含站点配置、通用抓取逻辑、聚合编排逻辑。
- 对差异较大的站点保留少量站点钩子,避免把所有逻辑写成纯硬编码分支。
不采用“每站点一个适配器文件”的方案,原因是当前仓库以单文件 Spider 为主,这种拆分会引入额外组织成本;也不采用“全部 if/else 硬编码”的方案,原因是后续修站难度会快速上升。
模块职责
玩偶聚合.py 内部拆成三层职责:
1. 站点配置层
维护聚合站点定义,包括:
- 站点 ID 和中文名。
- 域名列表,按优先顺序排列。
- 分类 URL 模板。
- 搜索 URL 模板。
- 列表、搜索、详情解析用选择器或 XPath 规则。
- 原站默认分类。
- 可选的本地筛选配置文件映射。
- 站点优先级。
2. 通用采集层
负责:
- 请求 HTML。
- 域名失败切换。
- 列表卡片解析。
- 搜索卡片解析。
- 详情页元数据提取。
- 网盘分享链接识别与分组。
- 聚合 ID 编解码辅助。
3. 聚合编排层
负责:
- 首页按站点输出分类和筛选结构。
- 分类请求路由到指定站点。
- 搜索并发拉取多站结果。
- 基于名称和年份做结果聚合。
- 聚合详情拉取多站详情并合并线路。
playerContent透传网盘链接。
Spider 对外行为
homeContent
首页使用“站点优先”模式:
class中每个条目代表一个聚合站点。type_id使用site_<site_id>格式。type_name使用站点中文名。
每个站点的 filters 至少包含:
categoryId分组,对应原站分类。
若该站有可落地的本地筛选配置,则继续追加该站支持的:
areayearclassby或sort- 其他与模板兼容的筛选字段
这样,使用方在 UI 上会先选站点,再选该站原始分类和筛选项。
categoryContent
tid 必须是 site_<site_id>。
处理逻辑:
- 从
tid提取目标站点。 - 从
extend中读取categoryId。 - 读取该站支持的附加筛选项。
- 按该站模板拼分类 URL。
- 请求 HTML,解析列表卡片。
- 返回当前页结果。
当 extend 未提供 categoryId 时,默认使用该站首个分类。
searchContent
搜索默认启用聚合模式:
- 对所有站点并发发起搜索请求。
- 每个站点单独设置超时,超时只影响该站。
- 解析得到站内搜索卡片列表。
- 基于名称归一化和年份辅助规则进行跨站聚合。
- 选择优先级最高的站点结果作为聚合主信息。
- 生成聚合
vod_id并返回聚合后的列表。
聚合结果默认不再把同片不同站拆成多条返回。
detailContent
支持两类 ID:
- 单站详情 ID。
- 聚合详情 ID。
单站详情:
- 请求对应站点详情页。
- 提取片名、海报、年份、导演、演员、简介。
- 提取并识别所有网盘分享链接。
- 生成
vod_play_from和vod_play_url。
聚合详情:
- 解码聚合 ID 中包含的站点条目。
- 按站点优先级依次请求多个站点详情。
- 跳过失败站点和无网盘站点。
- 合并多个站点的网盘线路并输出。
详情页不展开网盘剧集,不调用外部盘驱动。
playerContent
仅负责透传常见网盘分享链接。
支持:
pan.baidu.compan.quark.cndrive.uc.cnalipan.comaliyundrive.compan.xunlei.com115.com123pan.comcloud.189.cn或等价天翼域名yun.139.com或等价移动云盘域名
当 flag 或 id 能识别为上述网盘分享链接时,返回:
{"parse": 0, "playUrl": "", "url": "<share-url>"}
无法识别时返回空 URL,不尝试站内播放页解析。
数据模型设计
单站结果 ID
分类页中的普通条目使用:
site:<site_id>:<detail_path>
示例:
site:wanou:/voddetail/12345.html
要求:
- 保留站点信息。
- 保留足够重建详情 URL 的短路径。
- 不直接存储整页 HTML 或冗长 JSON。
聚合结果 ID
搜索聚合结果使用:
agg:<base64_json>
JSON 负载为条目数组,每个条目至少包含:
sitepathnameyear
这样可以:
- 避免把多个站点路径用裸字符串硬拼到
vod_id里。 - 在详情阶段稳定恢复参与聚合的站点列表。
- 控制
vod_id长度和结构清晰度。
播放线路
vod_play_from 使用盘类型加来源站点命名,例如:
baidu#玩偶quark#木偶a123#蜡笔
vod_play_url 直接存分享链接:
百度合集$https://pan.baidu.com/s/...夸克资源$https://pan.quark.cn/s/...
同类型多站资源允许并存,以来源站区分。
搜索聚合规则
名称归一化
对片名做规范化,用于跨站聚合判断:
- 转小写。
- 去除空白和常见标点。
- 去除常见分辨率或来源尾巴,如
4K、HDR、2160P、1080P。 - 去除常见站点附加标签。
聚合判定
优先使用以下规则:
- 归一化片名完全相同,可聚合。
- 若双方年份都存在且不相同,则不能聚合。
- 若年份一致或其中一方缺失年份,允许聚合。
- 对明显不同的片名,即使部分包含,也不强行聚合。
本次实现不引入复杂模糊匹配算法,避免误合并;先用保守规则建立稳定版本。
主信息来源
聚合组内按站点优先级排序,优先级最高的记录决定:
vod_namevod_picvod_remarksvod_year
同时保留来源标签供详情阶段使用。
详情聚合规则
单站详情解析
每个站点详情页尽量提取:
- 标题
- 海报
- 年份
- 地区
- 类型
- 导演
- 演员
- 简介
- 网盘分享链接
如果该站只有网盘资源,没有站内剧集线路,也视为有效站点。
网盘识别
根据链接域名识别盘类型,优先以分享域名为准,而不是文案标签:
- 百度
- 夸克
- UC
- 阿里
- 迅雷
- 115
- 123
- 天翼
- 移动云盘
合并策略
聚合详情按站点优先级遍历多站结果:
- 失败站点直接跳过。
- 无网盘链接的站点直接跳过。
- 同一站内重复链接去重。
- 同一分享链接跨站重复时只保留一份。
vod_play_from顺序先按盘优先级,再按站点优先级。
主详情信息取第一个成功站点。
如果所有站点都没有可用网盘链接,则返回空播放线路。
域名容错
不做后台监控,只做请求时故障切换。
每个站点维护多个候选域名:
- 请求时按当前顺序逐个尝试。
- 某个域名成功后,将其提升到列表前部。
- 失败时继续尝试下一个域名。
- 全部失败则该站本次请求记为空结果或详情失败。
该策略适用于:
- 分类页。
- 搜索页。
- 详情页。
不会引入线程、定时器或额外 HTTP 管理接口。
站点筛选策略
优先从仓库本地配置文件加载可用筛选项;若某站缺少本地筛选配置,则仅提供:
- 分类
categoryId
分类分组必须按用户配置顺序输出,避免被 Python 字典顺序或后处理逻辑打乱。
对于筛选 URL,支持两种模式:
- 站点自定义模板。
- 通用 CMS 模板回退。
测试设计
为新 Spider 新增 tests/test_玩偶聚合.py,覆盖三层行为。
1. 纯函数与辅助方法
- 站点 ID 解析。
- 单站
vod_id编解码。 - 聚合
vod_id编解码。 - 片名归一化。
- 聚合判定规则。
- 网盘类型识别。
2. 单站解析与 URL 构建
homeContent输出站点分类和筛选结构。- 分类 URL 根据
extend正确拼接。 - 搜索 URL 根据关键字正确构建。
- 单站列表卡片正确解析。
- 单站详情正确抽取网盘链接。
- 域名切换在首域失败后能使用备用域。
3. 聚合行为
- 多站搜索结果合并为单条。
- 年份冲突结果不合并。
- 聚合详情合并多个站点线路。
- 聚合详情对重复分享链接去重。
playerContent透传 quark / baidu / uc / aliyun / xunlei 等常见盘链接。
所有测试使用内嵌 HTML 或 mock response,不访问真实网络。
文件变更计划
预计后续实现阶段将修改或新增:
- 新增
py/玩偶聚合.py - 新增
py/tests/test_玩偶聚合.py - 如有必要,新增本地筛选配置文件,但优先复用已有
筛选目录资源
本设计阶段只新增本 spec 文件。
风险与处理
1. 站点结构不完全一致
处理方式:
- 使用站点配置驱动。
- 仅为少量差异保留钩子函数。
2. 搜索误聚合
处理方式:
- 初版采用保守聚合规则。
- 以完全归一化片名匹配为主,年份冲突即拆开。
3. 聚合 ID 过长
处理方式:
- 使用精简 JSON 负载。
- 仅保存详情恢复必需字段。
4. 备用域名经常失效
处理方式:
- 保持请求时故障切换。
- 不引入复杂监控模块。
实施结论
后续实现应严格围绕以下范围展开:
- Python 单文件聚合 Spider。
- 站点优先首页结构。
- 搜索默认聚合。
- 详情合并网盘分享线路。
playerContent只透传分享链接。
超出上述范围的监控后台、定时巡检、管理 API 和网盘剧集展开,均不在本次任务中。