docs: add yisou spider design

This commit is contained in:
Harold
2026-04-20 15:25:08 +08:00
parent 038d790d53
commit 41637357a5
@@ -0,0 +1,314 @@
# 奕搜 Python 爬虫设计
## 目标
在当前 Python 仓库中新增一个符合 `base.spider.Spider` 接口的奕搜站点爬虫,覆盖以下能力:
- 首页分类
- 分类列表
- 搜索
- 详情解析
- 网盘透传播放
实现以用户提供的 JS 版本为行为参考,但最终产物遵循当前仓库的单文件 Spider 约定,并对齐仓库中现有网盘类规则的输出格式。
## 范围
本次实现包含:
- 新增独立脚本,文件名为 `奕搜.py`
- 使用单一站点主域:`https://ysso.cc`
- 支持 `home/category/detail/search/player` 主链路
- 首页返回固定分类
- 详情页提取影片元数据和网盘分享链接
- `playerContent` 对分享链接做原样透传
- 为新增行为补齐 `unittest`
本次实现不包含:
- 参考 JS 中的 `panUrls` 返回格式复刻
- 站内播放线路解析
- 网盘驱动匹配、提取码自动补链或网盘二次解析
- 浏览器执行、反爬绕过或多域名探活
- 修改 `base/` 公共层
## 方案选择
采用仓库现有的“单站点单文件 + 单测”方案:
- 对外保持 `Spider` 接口兼容
- 对内拆分为 URL 组装、文本清洗、标题备注提取、列表解析、详情页元信息提取和网盘分组几个 helper
- 保留参考 JS 的核心页面解析行为,但输出改为仓库现有 Spider 可直接消费的 `vod_play_from` / `vod_play_url`
不直接照搬参考 JS 返回 `panUrls` 的原因是:
- 当前 Python 仓库上层消费的是标准播放线路字段
- 仓库里已有网盘透传型 Spider 可以直接复用输出约定
- 本次目标是把网页上的网盘资源稳定映射到现有播放器接口,而不是维持 JS 私有数据结构
## 模块边界
新增脚本只在站点文件内部维护逻辑,不修改 `base/`
脚本内部职责拆分如下:
- `init`
- 初始化主域、请求头和固定分类
- `homeContent`
- 返回固定 `class`
- `homeVideoContent`
- 返回空列表
- `categoryContent`
- 请求分类页并解析卡片列表
- `searchContent`
- 请求搜索页并解析卡片列表
- `detailContent`
- 请求详情页,提取影片元数据与网盘分享链接
- `playerContent`
- 对网盘分享链接或 `push://` 地址做原样透传
- 私有辅助函数
- 补全绝对 URL
- 清洗标题文本
- 从标题中提取备注
- 解析列表卡片
- 解析详情元信息
- 识别网盘类型并构造播放分组
## Host 与请求策略
本次只实现单域:
- `https://ysso.cc`
请求统一通过 `self.fetch` 发起,固定请求头至少包含:
- `User-Agent`
- `Referer`
请求原则:
- HTML 请求超时固定为 10 秒
- 请求失败时返回空 HTML 或空结果,不抛出未处理异常
- 不引入额外缓存、重试或 JS 执行环境
## 分类设计
首页分类固定为:
- `dy -> 电影`
- `dsj -> 电视剧`
- `zy -> 综艺`
- `dm -> 动漫`
- `jlp -> 纪录片`
- `dj -> 短剧`
`homeContent` 返回:
- `class`
不返回筛选配置,因为参考实现没有分类筛选结构。
`homeVideoContent` 直接返回:
- `{"list": []}`
## 列表与搜索设计
分类页 URL
- `/<classId>.html?page=<page>`
搜索 URL
- `/search.html?keyword=<urlencoded keyword>&page=<page>`
分类页和搜索页共用同一个卡片解析器,目标结构为 `.list-boxes`
卡片字段提取规则:
- `vod_id`
- 优先取 `a.text_title_p[href]`
- 如果缺失则回退 `.left_ly a[href]`
- 输出站点短路径,不暴露完整详情 URL
- `vod_name`
- 使用标题文本清理 `[]` 标签后的结果
- `vod_pic`
-`img.image_left[src]` 并补全成绝对地址
- `vod_remarks`
- 优先从标题中的 `[]` 标签提取
- 若无可用备注,则回退 `.list-actions span`
标题备注提取顺序与参考 JS 保持一致:
1. 更新集数,如 `[更12]` 转成 `更新至12集`
2. 评分,如 `[8.5分]` 转成 `评分:8.5`
3. 年份,如 `[2025]` 转成 `首播:2025`
分页返回字段:
- `page`
- `limit`
- `total`
- `list`
为了符合仓库当前约定,分类和搜索结果不返回 `pagecount`
## 短 ID 设计
为了遵循仓库里的短 ID 规则,不对外暴露完整详情页 URL。
列表与搜索阶段拿到的详情链接如果为站内 URL,则统一压缩为站点相对路径,例如:
- `/resource/12345`
`detailContent` 接收到相对路径后再补成完整详情 URL。
如果上层传入的是完整 URL,也兼容直接处理,但 Spider 自身产出仍以短路径为主。
## 详情页设计
详情页输出单个视频对象,字段至少包含:
- `vod_id`
- `vod_name`
- `vod_pic`
- `vod_remarks`
- `vod_director`
- `vod_actor`
- `vod_content`
- `vod_play_from`
- `vod_play_url`
元信息提取规则:
- 标题
- `h1.articl_title`
- 标题中的 `[]` 标签会先用于生成 `vod_remarks`,再从标题中剥离
- 封面
- `.tc-box.article-box img` 首张图
- 导演与编剧
- 遍历 `#info > span`
- 命中“导演”或“编剧”标签时,读取 `.attrs a`
- 去重后以 `, ` 拼接到 `vod_director`
- 主演与演员
- 命中“主演”或“演员”标签时,读取 `.attrs a`
- 去重后以 `, ` 拼接到 `vod_actor`
- 简介
- 遍历正文中长度明显大于标签名的段落
- 取首个有效长文本并压缩空白
提取码策略:
- 从整页文本中匹配 `提取码[:]XXXX`
- 若命中,则追加到 `vod_remarks`
- 不把提取码写回网盘链接,不做自动拼装
## 网盘资源设计
详情页只保留网盘分享资源,不保留站内播放线路。
网盘链接提取策略:
- 遍历详情页中所有 `a[target="_blank"][href]`
- 仅保留 `http/https` 绝对地址
- 按分享链接去重,避免同链接多次输出
网盘类型识别范围:
- `baidu`
- `pan.baidu.com`
- `quark`
- `pan.quark.cn`
- `uc`
- `drive.uc.cn`
- `aliyun`
- `alipan.com`
- `aliyundrive.com`
- `xunlei`
- `pan.xunlei.com`
输出策略:
- 能识别盘类型时,按盘类型分组输出
- 每个分组的单条资源格式为 `<盘名>$<分享链接>`
- 同一分组内多条资源用 `#` 连接
- 多个分组之间用 `$$$` 连接
- `vod_play_from``vod_play_url` 的分组顺序保持一致
盘类型排序优先级:
1. `baidu`
2. `quark`
3. `uc`
4. `aliyun`
5. `xunlei`
如果详情页存在外链但都不属于上述已识别网盘:
- 使用单一兜底线路名 `奕搜`
- 对应 `vod_play_url``1$push://<url>#2$push://<url>...`
如果详情页不存在任何可用外链:
- `vod_play_from = 奕搜`
- `vod_play_url = ""`
这样可以保持与仓库里现有网盘透传规则一致,并且明确表达“本 Spider 只提供网盘分享链接透传”。
## 播放设计
`playerContent(flag, id, vipFlags)` 不做二次解析,只负责规范化透传:
- 如果 `id``push://` 开头
- 去掉前缀后返回真实分享链接
- 如果 `id` 已经是 `http/https` 分享链接
- 直接原样返回
- 其他情况
- 也原样返回,不额外猜测和改写
返回结构:
- `parse = 0`
- `url = <透传后的值>`
不附加鉴权头,不做 `jx` 回退。
## 错误处理
- 分类页、搜索页请求失败时返回空列表
- 详情页请求失败时返回 `{"list": []}`
- 单个网盘链接识别失败时跳过盘类型识别,但不影响其他链接
- 标题、图片、导演、主演、简介等字段缺失时返回空字符串
## 测试设计
测试覆盖以下行为:
1. `homeContent`
- 断言固定分类完整且顺序正确
2. 列表解析
- 断言能从 `.list-boxes` 解析短路径 `vod_id`、清洗后的标题、图片和备注
- 断言备注提取优先级符合参考 JS
3. `categoryContent`
- 断言分类页 URL 正确
- 断言返回字段不包含 `pagecount`
4. `searchContent`
- 断言空关键词返回空列表
- 断言搜索 URL 包含 URL 编码后的关键词
5. `detailContent`
- 断言能提取标题、图片、导演、主演、简介和提取码
- 断言详情页只输出网盘透传线路
- 断言网盘链接按盘类型分组、去重和排序
- 断言未识别外链时回退到 `push://` 兜底线路
6. `playerContent`
- 断言 `push://` 去壳透传
- 断言普通网盘分享链接原样透传
## 验收标准
- `homeContent/categoryContent/detailContent/searchContent/playerContent` 均返回符合当前项目习惯的数据结构
- 列表和搜索结果只输出站点短路径 `vod_id`
- 标题备注提取和标题清洗与参考 JS 的优先级一致
- 详情页只输出网盘分享线路,不保留站内播放线路
- `playerContent` 对网盘链接仅做原样透传
- 新增 `unittest` 能稳定覆盖主要解析分支