docs: add ddys spider design
This commit is contained in:
@@ -0,0 +1,304 @@
|
||||
# 低端影视 Python 爬虫设计
|
||||
|
||||
## 目标
|
||||
|
||||
在当前 Python 仓库中新增一个符合 `base.spider.Spider` 接口的低端影视站点爬虫,覆盖以下能力:
|
||||
|
||||
- 首页分类与筛选
|
||||
- 分类列表
|
||||
- 搜索
|
||||
- 详情解析
|
||||
- 播放解析
|
||||
|
||||
实现基于站点 HTML 页面结构,不引入服务端路由层,不修改 `base/` 公共层,并且保留详情页中的网盘分享链接。
|
||||
|
||||
## 范围
|
||||
|
||||
本次实现包含:
|
||||
|
||||
- 新增独立脚本,文件名为 `低端影视.py`
|
||||
- 使用单一站点主域:`https://ddys.io`
|
||||
- 支持 `home/category/detail/search/player` 主链路
|
||||
- 首页返回固定分类与静态筛选配置
|
||||
- 详情页同时输出站内播放线路和网盘分享线路
|
||||
- `playerContent` 对站内线路返回直链,对网盘线路直接透传分享链接
|
||||
|
||||
本次实现不包含:
|
||||
|
||||
- 参考 JS 中的 Fastify 路由封装
|
||||
- 网盘驱动匹配、网盘二次解析、网盘播放鉴权
|
||||
- 浏览器自动化或 JS 执行环境
|
||||
- 多域名探活与自动切换
|
||||
- 登录态、Cookie 常驻维护、站点反爬绕过
|
||||
|
||||
## 方案选择
|
||||
|
||||
采用仓库现有的“单站点单文件 + 单测”方案:
|
||||
|
||||
- 对外保持 `Spider` 接口兼容
|
||||
- 对内拆分为请求封装、列表解析、详情解析、播放器提取几个 helper
|
||||
- 保留参考实现的核心行为,但只实现当前 Python 仓库真正需要的 Spider 逻辑
|
||||
|
||||
不直接照搬参考 JS 服务端包装层的原因是:
|
||||
|
||||
- 当前仓库只消费 Spider 接口,不消费站内 HTTP API
|
||||
- Python 版已有成熟模式,新增站点应遵循既有结构
|
||||
- 这次重点是 HTML 解析与数据整形,不是路由或中间件封装
|
||||
|
||||
## 模块边界
|
||||
|
||||
新增脚本只在站点文件内部维护逻辑,不修改 `base/`。
|
||||
|
||||
脚本内部职责拆分如下:
|
||||
|
||||
- `init`
|
||||
- 初始化主域、请求头、固定分类、筛选项与分页参数
|
||||
- `homeContent`
|
||||
- 返回固定 `class` 与 `filters`
|
||||
- `homeVideoContent`
|
||||
- 返回空列表,不额外做首页推荐抓取
|
||||
- `categoryContent`
|
||||
- 根据分类、筛选和分页拼出 URL,请求 HTML 并解析卡片
|
||||
- `detailContent`
|
||||
- 请求详情页,提取影片元数据、普通播放线路和网盘线路
|
||||
- `searchContent`
|
||||
- 通过站内搜索接口 POST 关键词并解析结果卡片
|
||||
- `playerContent`
|
||||
- 对普通线路返回最终 URL,对网盘线路直接返回分享链接
|
||||
- 私有辅助函数
|
||||
- 补全相对地址
|
||||
- 清理文本
|
||||
- 模板化分类筛选路径
|
||||
- 解析卡片列表
|
||||
- 解析详情元信息
|
||||
- 解析普通播放源
|
||||
- 解析并保留网盘分享链接
|
||||
|
||||
## Host 与请求策略
|
||||
|
||||
本次只实现单域:
|
||||
|
||||
- `https://ddys.io`
|
||||
|
||||
请求统一通过 `self.fetch` / `self.post` 发起,固定请求头至少包含:
|
||||
|
||||
- `User-Agent`
|
||||
- `Referer`
|
||||
|
||||
搜索接口额外补充:
|
||||
|
||||
- `Content-Type: application/x-www-form-urlencoded`
|
||||
|
||||
请求原则:
|
||||
|
||||
- HTML 请求超时固定为 10 秒
|
||||
- 请求失败时返回空 HTML 或空结果,不抛出未处理异常
|
||||
- 不引入 gzip/base64 之外的额外协议适配
|
||||
|
||||
## 分类与筛选设计
|
||||
|
||||
首页分类固定为:
|
||||
|
||||
- `series -> 剧集`
|
||||
- `movie -> 电影`
|
||||
- `variety -> 综艺`
|
||||
- `anime -> 动漫`
|
||||
|
||||
筛选配置直接内置到脚本中,字段与参考实现保持一致:
|
||||
|
||||
- `class`
|
||||
- `area`
|
||||
- `year`
|
||||
- `by`
|
||||
|
||||
筛选 URL 规则采用模板拼接:
|
||||
|
||||
- `{{fl.by}}{{fl.cateId}}{{fl.class}}{{fl.area}}{{fl.year}}/page/fypage`
|
||||
|
||||
规则说明:
|
||||
|
||||
- `cateId` 来自当前分类默认配置
|
||||
- `class/area/year/by` 来自传入的 `extend`
|
||||
- 当第一页且存在可选分页模板时,输出第一页真实路径
|
||||
- 当页无结果时返回当前页,避免上层无限翻页
|
||||
|
||||
`homeContent` 返回:
|
||||
|
||||
- `class`
|
||||
- `filters`
|
||||
|
||||
不返回首页推荐列表。
|
||||
|
||||
## 列表与搜索设计
|
||||
|
||||
分类页解析对象为新版卡片:
|
||||
|
||||
- 外层选择器:`.movie-card`
|
||||
- 标题:`h3`
|
||||
- 图片:`img[src]`
|
||||
- 备注:`.poster-badge`
|
||||
- 链接:内部 `a[href]`
|
||||
|
||||
输出统一卡片结构:
|
||||
|
||||
- `vod_id`
|
||||
- `vod_name`
|
||||
- `vod_pic`
|
||||
- `vod_remarks`
|
||||
|
||||
搜索接口使用:
|
||||
|
||||
- `POST /search`
|
||||
|
||||
请求体:
|
||||
|
||||
- `q=<关键词>`
|
||||
|
||||
搜索结果优先解析第一个结果区块中的 `.movie-card`,如果站点结构缺失,再回退到通用卡片解析器。
|
||||
|
||||
分页策略采用保守估计:
|
||||
|
||||
- 分类页 `limit` 固定为 24
|
||||
- 当页有结果时,`pagecount = page + 1`
|
||||
- 当页无结果时,`pagecount = page`
|
||||
- 搜索同样按“有结果则可翻下一页”的保守逻辑返回
|
||||
|
||||
## 详情页设计
|
||||
|
||||
详情页仅适配新版页面结构。
|
||||
|
||||
元信息提取范围:
|
||||
|
||||
- 标题:主标题与可选副标题
|
||||
- 封面:首张主海报图
|
||||
- 年份、地区、类型
|
||||
- 导演、主演
|
||||
- 剧情简介
|
||||
|
||||
详情输出字段至少包含:
|
||||
|
||||
- `vod_id`
|
||||
- `vod_name`
|
||||
- `vod_pic`
|
||||
- `vod_content`
|
||||
- `vod_remarks`
|
||||
- `vod_year`
|
||||
- `vod_area`
|
||||
- `vod_class`
|
||||
- `vod_director`
|
||||
- `vod_actor`
|
||||
- `vod_play_from`
|
||||
- `vod_play_url`
|
||||
|
||||
播放来源分为两组:
|
||||
|
||||
1. 普通站内线路
|
||||
- 来自页面中的 `switchSource(...)` 按钮
|
||||
- 线路名使用按钮文本
|
||||
- 单线路只有一个 URL 时输出 `全集$<url>`
|
||||
- 多集线路按 `名称$URL#名称$URL` 组织
|
||||
2. 网盘线路
|
||||
- 来自 `.download-type-content` 模块中的按钮
|
||||
- 从 `atob('...')` 中解码出真实分享链接
|
||||
- 每个支持的网盘分组单独作为一条线路
|
||||
|
||||
网盘线路识别范围:
|
||||
|
||||
- `quark`
|
||||
- `xunlei`
|
||||
- `baidu`
|
||||
|
||||
网盘线路保留策略:
|
||||
|
||||
- 只保留分享链接,不做驱动匹配
|
||||
- 分享链接直接写入 `vod_play_url`
|
||||
- `vod_play_from` 使用网盘名,如 `quark`、`xunlei`、`baidu`
|
||||
|
||||
如果某种来源没有数据,则不保留空占位;最终只返回实际存在的线路。
|
||||
|
||||
## 播放设计
|
||||
|
||||
`playerContent(flag, id, vipFlags)` 按来源分流:
|
||||
|
||||
### 普通站内线路
|
||||
|
||||
- 如果 `id` 不是绝对地址,则补全为站点完整 URL
|
||||
- 返回:
|
||||
- `parse = 0`
|
||||
- `jx = 0`
|
||||
- `url = 完整播放链接`
|
||||
- `header = 基础请求头`
|
||||
|
||||
### 网盘线路
|
||||
|
||||
当 `flag` 命中以下关键字时视为网盘线路:
|
||||
|
||||
- `baidu`
|
||||
- `quark`
|
||||
- `xunlei`
|
||||
|
||||
对网盘线路不做二次解析,直接透传分享链接:
|
||||
|
||||
- `parse = 0`
|
||||
- `jx = 0`
|
||||
- `url = 原始分享链接`
|
||||
- `header = {}`
|
||||
|
||||
这样可以保证上层仍能识别和消费网盘资源,不会因为 Spider 侧强行解析而丢失链接。
|
||||
|
||||
## 解析与兼容性策略
|
||||
|
||||
为了降低页面结构波动影响,实现上采用“选择器优先、正则兜底”的策略:
|
||||
|
||||
- 列表与搜索主走 XPath
|
||||
- 详情页按钮参数用正则提取
|
||||
- 网盘链接通过 `atob('...')` 片段做 base64 解码
|
||||
|
||||
文本处理原则:
|
||||
|
||||
- 缺失字段返回空字符串
|
||||
- 标题、备注、简介统一做空白折叠
|
||||
- 图片和详情链接统一补全为绝对地址
|
||||
|
||||
## 错误处理
|
||||
|
||||
实现遵循“失败可回退、最终返回空结果而非抛异常”的原则:
|
||||
|
||||
- 页面请求失败时返回空结果
|
||||
- 单条线路解析失败时跳过该线路,继续解析其他线路
|
||||
- 网盘链接解码失败时跳过当前网盘项,不影响普通线路输出
|
||||
- 搜索页或详情页局部字段缺失时,保留其余可解析字段
|
||||
|
||||
## 测试设计
|
||||
|
||||
采用测试优先方式实现,先补单测,再写生产代码。
|
||||
|
||||
测试重点放在纯解析逻辑和结果结构,不依赖真实网络:
|
||||
|
||||
1. 首页内容
|
||||
- 断言固定分类和筛选项按预期输出
|
||||
2. 分类列表
|
||||
- 断言 URL 构造与卡片解析正确
|
||||
3. 搜索
|
||||
- 断言 POST 请求参数正确
|
||||
- 断言搜索结果卡片可解析
|
||||
4. 详情
|
||||
- 断言能同时提取普通线路和网盘线路
|
||||
- 断言 `vod_play_from` / `vod_play_url` 正确分组
|
||||
5. 播放
|
||||
- 断言普通线路返回完整直链
|
||||
- 断言网盘线路直接透传分享链接
|
||||
|
||||
测试文件命名:
|
||||
|
||||
- `tests/test_低端影视.py`
|
||||
|
||||
## 验收标准
|
||||
|
||||
满足以下条件即视为完成:
|
||||
|
||||
- 新增 `低端影视.py`,可被仓库按现有方式加载
|
||||
- `homeContent/categoryContent/detailContent/searchContent/playerContent` 均返回符合当前项目习惯的数据结构
|
||||
- 详情页普通线路与网盘线路分开输出
|
||||
- 网盘分享链接在详情页和播放阶段都不会被丢弃
|
||||
- 新增单测通过,且不破坏现有测试
|
||||
Reference in New Issue
Block a user