douyin-crawler-poc/docs/superpowers/specs/2026-04-17-douyin-zero-arg-target-detection-design.md

5.4 KiB
Raw Blame History

Douyin Zero-Argument Target Detection Design

Goal

将当前抓取入口从“主要依赖手动传 URL 或页码参数”收敛为“默认零参数运行”,让用户在最常见场景下只需要:

./.venv/bin/python login_douyin.py
./.venv/bin/python Douyin.py

脚本会优先附着已登录浏览器,并自动识别当前活动标签页是博主主页还是单视频页。

Current Context

  • login_douyin.py 已能启动带调试端口的可见 Chrome。
  • Douyin.py 已能附着浏览器、监听博主作品列表接口并下载视频。
  • 当前抓取入口仍偏向“显式传 URL + 可选翻页参数”。
  • 当前实现默认会继续滚动翻页,这与“只按当前浏览器已加载状态工作”的目标不一致。

User Experience

Default Flow

  1. 用户运行 ./.venv/bin/python login_douyin.py
  2. 用户在 Chrome 里完成抖音登录、验证码,并停留在目标页面
  3. 用户运行 ./.venv/bin/python Douyin.py

Default Crawl Behavior

  • 如果当前活动标签页是博主主页:
    • 只抓当前页面已经加载出来的作品
    • 不自动继续翻多页
  • 如果当前活动标签页是单视频页:
    • 只下载这一条视频
  • 如果当前活动标签页不是受支持页面:
    • 明确报错
    • 提示用户手动传入链接或 aweme_id

Manual Fallback

用户仅在自动判断失败或不想切换浏览器页面时,才传一个简单目标值:

./.venv/bin/python Douyin.py "https://www.douyin.com/user/..."
./.venv/bin/python Douyin.py "https://www.douyin.com/video/..."
./.venv/bin/python Douyin.py "7619989983668240802"

Chosen Approach

采用“内部显式分类,外部最小参数”的方案:

  • 对用户:
    • 默认零参数
    • 保留一个位置参数作为手动兜底入口
  • 对代码:
    • 先统一解析输入来源和目标类型
    • 再分发到“博主页抓取”或“单视频下载”路径

这样既避免 --mode --target 的使用负担,也保留明确的内部边界,便于测试。

Internal Model

建议在 Douyin.py 内新增一层目标解析:

  • creator
    • 来源可以是当前活动页 URL 或手动传入的博主页 URL
  • single-video
    • 来源可以是当前活动页 URL、手动传入的视频 URL 或 aweme_id
  • unsupported
    • 当前页或手动输入都不符合支持规则

建议新增的小函数边界:

  • parse_target_input(value: str) -> ParsedTarget
  • resolve_target(page: Any, cli_target: str | None) -> ParsedTarget
  • is_creator_url(url: str) -> bool
  • is_video_url(url: str) -> bool
  • is_aweme_id(value: str) -> bool
  • get_active_page_url(page: Any) -> str

Crawl Paths

Creator Path

  • 复用当前 web/aweme/post/ 监听和解析能力
  • 默认只处理当前已加载内容
  • 不再在默认主流程中自动继续滚动翻页
  • 若页面未加载出可用作品数据,明确提示用户先在浏览器中完成加载或筛选后再重试

Single Video Path

  • 若目标是视频 URL先解析出 aweme_id
  • 若目标本身就是 aweme_id,直接进入单视频下载
  • 下载结果仍写入 video/
  • 最终只落地一个 mp4 文件

CLI Design

Keep

  • 保留 --browser-port
  • 保留 --output-dir
  • 保留 --timeout

Change

  • 位置参数从“默认博主页 URL”改为“可选手动目标值”
  • 默认不再依赖硬编码博主页 URL

De-Emphasize

  • --pages 不再作为默认主流程的核心参数
  • 如果保留兼容性也不应影响零参数主路径的“visible-only”语义

Error Handling

  • 浏览器端口不可用:提示先运行 login_douyin.py 并确认 Chrome 仍在运行
  • 当前活动标签页不是受支持页面:提示切到目标页面,或手动传入链接/aweme_id
  • 手动输入既不是博主页 URL、视频 URL也不是 aweme_id:明确报错
  • 博主页没有加载出作品数据:提示用户先在浏览器页面完成滚动或等待加载
  • 视频标识无法解析:明确报错

Testing Strategy

Unit Tests First

第一轮 TDD 先覆盖目标识别和错误路径:

  1. 当前页是博主页 URL 时,识别为 creator
  2. 当前页是单视频页 URL 时,识别为 single-video
  3. 手动传入博主页 URL 时,识别为 creator
  4. 手动传入视频 URL 时,识别为 single-video
  5. 手动传入 aweme_id 时,识别为 single-video
  6. 当前页不支持且没传参数时,抛出可读错误
  7. 手动输入不支持时,抛出可读错误

第二轮 TDD 再覆盖执行路径:

  1. 博主页默认不自动继续翻页
  2. 单视频路径最终只下载一条
  3. 端口不可用时提前失败

Implementation Boundaries

本次实现只做:

  • 零参数目标识别
  • 当前活动标签页自动判断
  • 单位置参数兜底输入
  • 博主页 visible-only 默认行为
  • 单视频下载路径
  • 对应自动化测试

本次不做:

  • 自动登录
  • 自动搜索博主
  • 自动筛选页面条件
  • 抓完整个博主历史内容
  • 任意网页抓取

Success Criteria

满足以下条件即视为完成:

  1. 用户默认执行 ./.venv/bin/python Douyin.py 可以按当前活动标签页工作
  2. 当前页为博主页时,只抓当前已加载内容
  3. 当前页为单视频页时,只下载这一条
  4. 当前页不支持时,提示用户手动传链接或 aweme_id
  5. 手动传入博主页 URL、视频 URL 或 aweme_id 时可正常工作
  6. 关键路径都有自动化测试覆盖,并按 TDD 落地