6.3 KiB
独播库 Python 爬虫设计
目标
在当前 Python 仓库中新增一个符合 base.spider.Spider 接口的独播库站点爬虫,覆盖以下能力:
- 分类列表
- 详情页
- 搜索
- 播放解析
实现基于网页 DOM 抓取,不依赖站点私有 API,不修改 base/ 公共层。
范围
本次实现包含:
- 新增独立脚本,暂定文件名为
独播库.py - 使用单一站点主域:
https://www.dbku.tv - 支持列表页、搜索页、详情页和站内播放解析
本次实现不包含:
- 多域名自动回退
- 网盘资源解析
- 通用网页源抽象框架
方案选择
采用 requests + lxml 直接抓取网页 HTML,并吸收参考插件 plugin_dbku 中已经验证过的 DOM 结构与 player_data 解析规则。
不直接把整份 JS 逐行平移到 Python,原因是:
- Python 代码更容易维护
- 更贴合当前仓库的
Spider接口 - 只保留独播库真正需要的站点规则,减少噪音
模块边界
新增脚本只在站点文件内部维护逻辑,不修改 base/。
脚本内部职责拆分如下:
init- 初始化主域、请求头、分类映射
homeContent- 返回固定分类
categoryContent- 请求分类页并解析媒体卡片
searchContent- 请求搜索页并解析搜索结果
detailContent- 提取影片基础信息和剧集列表
playerContent- 解析剧集页中的
player_data,得到最终播放地址
- 解析剧集页中的
- 私有辅助函数
- URL 归一化
- 列表卡片解析
- 搜索结果解析
- 详情页解析
player_data提取与解码
Host 策略
本次只实现单域:
https://www.dbku.tv
请求失败时不做多域切换,只返回空结果或空播放地址。后续如果该站常态化换域,再补 host 回退。
分类设计
分类 ID 直接使用参考实现中的键,避免额外映射层:
indexmovievarietyanimehkluju
分类 URL 映射如下:
index -> /vodtype/2--------{pg}---.htmlmovie -> /vodtype/1--------{pg}---.htmlvariety -> /vodtype/3--------{pg}---.htmlanime -> /vodtype/4--------{pg}---.htmlhk -> /vodtype/20--------{pg}---.htmlluju -> /vodtype/13--------{pg}---.html
首页推荐 homeVideoContent 维持空列表,避免额外抓站点首页。
列表与搜索解析
分类页
分类页主要解析 myui-vodlist__box 卡片。
每张卡片提取规则:
- 链接:优先选择
href含/voddetail/的链接 - 标题:优先链接
title,回退到节点文本 - 封面:优先取
data-original,其次src - 描述:优先取类名含
pic-text的文本,回退到卡片中首个有意义的附加文本
输出字段:
vod_id- 直接使用详情页绝对 URL
vod_namevod_picvod_remarks
搜索页
搜索 URL:
/vodsearch/-------------.html?wd=<keyword>&submit=
搜索结果优先解析 #searchList 容器内的卡片;若没有搜索容器或解析结果为空,则回退到普通列表卡片解析,以兼容不同模板。
分页策略
返回分页字段:
page = 当前页pagecount = pg + 1,若当页无内容则为当前页limit = 实际条目数total = 近似值
不依赖站点总数统计。
详情页设计
detailContent 使用 vod_id 请求详情页,提取:
vod_namevod_picvod_yearvod_areavod_actorvod_directorvod_content
播放列表只保留站内源:
vod_play_from = "独播库"
剧集项格式:
标题$剧集页URL
若发现多组播放列表,先按页面顺序合并同站剧集,去重后输出为单一播放源。
播放解析设计
独播库播放解析核心是剧集页中的 player_data。
实现步骤:
- 请求剧集页
- 提取页面脚本中的
player_dataJSON - 读取:
urlfromencrypt
- 按
encrypt解码播放地址
解码规则:
encrypt = 0- 原样返回
encrypt = 1- 执行
unescape等价解码
- 执行
encrypt = 2base64解码后再尝试 URL 解码
encrypt = 3- 按参考实现做裁剪后的
base64变体解码
- 按参考实现做裁剪后的
如果解码后的 URL 仍是站内中间页而不是最终播放地址,则继续请求该页面并再次尝试提取 player_data 或直链,直到:
- 得到最终可播放 URL
- 无法继续解析,此时返回空 URL
返回格式:
parse = 0playUrl = ""url = 最终播放地址header = {"User-Agent": "...", "Referer": "..."}
请求与兼容性
统一请求头至少包含:
- 浏览器
User-Agent - 需要时补
Referer
本次优先采用无状态请求;如果验证时发现独播库对 cookie 敏感,再补最小 cookie 维护。
错误处理
实现遵循“失败返回空,不抛异常中断”的原则:
- 页面请求失败时返回空列表或空播放 URL
- DOM 节点缺失时字段回退为空字符串
player_data解析失败时继续尝试回退规则- 最终失败则返回
{"parse": 0, "playUrl": "", "url": ""}
日志只保留必要调试信息。
测试设计
采用测试优先方式实现,先给纯解析函数写测试,再补生产代码。
测试重点:
- 分类卡片解析
- 断言能从
myui-vodlist__box提取详情链接、标题、封面和描述
- 断言能从
- 搜索结果解析
- 断言优先使用
#searchList - 断言缺失时会回退到普通列表解析
- 断言优先使用
- 详情页解析
- 断言影片元信息提取正确
- 断言剧集列表生成正确并去重
player_data解码- 覆盖
encrypt = 0/1/2/3
- 覆盖
playerContent- 断言能从剧集页解析到最终播放地址
优先使用 unittest 和 mock,避免测试依赖真实站点网络。
实施顺序
- 新增独播库测试文件,覆盖卡片、搜索、详情和播放器解析
- 新增
独播库.py基本骨架与分类映射 - 实现分类页和搜索页抓取
- 实现详情页和剧集列表
- 实现
player_data解码与高层playerContent - 运行测试并做最小手工验证
风险
- 页面模板可能调整
player_data格式或encrypt规则可能变化- 个别剧集可能存在站内二跳或额外播放器包装
对应策略:
- 列表和搜索解析都保留回退路径
- 播放解析按
encrypt分类处理 - 测试覆盖所有已知解码路径,降低回归风险