首页
/ last30days-skill v2.1 版本解析:X 搜索内置化与 YouTube 字幕源的实现原理

last30days-skill v2.1 版本解析:X 搜索内置化与 YouTube 字幕源的实现原理

2026-09-04 19:17:41作者:戚魁泉Nursing

本文基于 docs/v2.1-launch-copy.md 的 v2.1 发布说明,完整还原该版本的两大主线功能——内置 X(Twitter)搜索客户端与 YouTube 字幕(transcript)作为第四信息源——的设计动机、配置方式与源码级实现细节。读完后你可以理解 last30days-skill 如何在零 API 密钥的前提下接入 X 与 YouTube,并掌握 AUTH_TOKEN/CT0/XAI_API_KEY 的完整配置链路。

版本背景:Bird CLI 消失,v2.1 必须自给自足

v2.1 的发布动因写在文档开头:Bird CLI(@steipete/bird)已从 npm 上被弃用(deprecated),其 GitHub 仓库也被删除,且没有人 fork 后重新发布。这意味着 v2.0 时代依赖外部 bird CLI 的 X 搜索链路随时会断掉。v2.1 的解法是:在仓库内 vendor(内置)Bird v0.8.0 的一个"仅搜索"子集,用户不再需要安装任何外部 X 搜索工具。

当前仓库中该内置客户端位于 skills/last30days/scripts/lib/vendor/bird-search/,其 package.json 给出了权威版本信息:

{
  "name": "bird-search",
  "version": "0.8.0",
  "description": "Vendored Bird CLI search subset for /last30days",
  "engines": { "node": ">=22" },
  "license": "MIT",
  "attribution": "Based on @steipete/bird v0.8.0 by Peter Steinberger (MIT License)"
}

三个关键事实可以从这里确认:内置的是 v0.8.0、MIT 许可、运行前提是 Node.js 22+。这正好对应发布文案中"just Node.js 22+ plus AUTH_TOKEN and CT0"的表述。

第二个动因是 YouTube:v2.1 受 Peter Steinberger 的 yt-dlp + summarize 工具链启发,直接使用 yt-dlp(不引入 summarize 依赖)搜索 YouTube、抓取观看量并提取自动生成字幕,喂给合成引擎。零 API 密钥、零成本。

功能一:X 搜索完全内置

认证配置:AUTH_TOKEN 与 CT0

X 搜索优先使用显式环境变量认证,目的是让本地运行保持 headless,避免浏览器 cookie 弹窗和 macOS Keychain 提示。发布文案给出的推荐步骤是:在已登录 x.com 的浏览器中打开开发者工具,复制 x.com 域下的 auth_tokenct0 两个 cookie,保存为:

# ~/.config/last30days/.env 或 .claude/last30days.env
AUTH_TOKEN=your_auth_token
CT0=your_ct0_token

官方发布文案中给出的安装块 env 行也一致:

AUTH_TOKEN=...            # recommended for X search
CT0=...                   # recommended for X search
XAI_API_KEY=xai-...       # optional X fallback

xAI 回退路径:如果不愿意提供 AUTH_TOKENCT0,可以改设 XAI_API_KEY,走 xAI 的 x_search 后端。README 中同样把 XAI_API_KEY 列为 X 搜索的可选密钥路径之一(见 README.md 的源表与 keychain 存储示例)。

验证命令:确认内置客户端可认证,直接运行:

node ~/.claude/skills/last30days/scripts/lib/vendor/bird-search/bird-search.mjs --whoami

在仓库内路径对应为 skills/last30days/scripts/lib/vendor/bird-search/bird-search.mjs(注意 ~/.claude/skills/ 是 skill 安装目录,仓库内相对路径是 skills/last30days/)。

源码纵深:Python 侧如何驱动内置客户端

X 搜索的 Python 侧入口是 skills/last30days/scripts/lib/bird_x.py,值得关注的实现点有:

  • 深度配置DEPTH_CONFIG = {"quick": 12, "default": 30, "deep": 60} 控制每次搜索请求的结果数,分别对应 30/45/60 秒超时(bird_x.py#L48-L52)。
  • 环境白名单_SUBPROCESS_ENV_ALLOWLIST 精确限定了传给 Node 子进程的环境变量面——平台变量、Node TLS/代理配置,以及 X 会话 cookie(AUTH_TOKENCT0 及其 TWITTER_* 别名)。.env 中其他无关密钥一律不会到达这个被扫描排除的 vendor 代码(源码注释引用了 issue #1063,见 bird_x.py#L64-L78)。
  • 强制禁用浏览器 cookie 回退_subprocess_env() 中硬编码 BIRD_DISABLE_BROWSER_COOKIES=1,保证正常管道运行不会触发 Safari/Chrome Keychain 弹窗——这正是发布文案"no browser-cookie prompts"承诺的底层实现。
  • 反爬重试:Twitter 边缘节点偶尔返回 HTML 反爬拦截页而非 JSON,_run_bird_search() 对非 JSON stdout 最多重试 2 次、间隔 5 秒,并把该失败形态标记为 schema drift 而非"无结果"(bird_x.py#L346-L424)。
  • 零结果重试阶梯search_x() 在 0 结果时依次降级——先尝试多词 OR 组(("term A" OR "term B") since:DATE),再截短到前 2 个词,最后锚定到最强特征词(排除 best/hot/latest 等低信号词),宁可返回 0 也不扩散到无锚点的通用词(bird_x.py#L457-L511)。
  • 探针probe_works()from:x since:... 发一条 1 结果探针,廉价验证认证是否真正能返回数据;网络超时会被判为"不确定"而不降级状态,避免误报故障(bird_x.py#L228-L256)。

认证状态如何被判定

skills/last30days/scripts/lib/env.py 负责把配置里的 AUTH_TOKEN/CT0 解析进运行时配置("first COMPLETE pair wins"——第一个成对出现的来源获胜),随后调用 bird_x.set_credentials() 注入模块级凭据;is_bird_authenticated() 返回的认证源字符串(如 env AUTH_TOKEN)最终出现在诊断输出中(见 env.py#L1067-L1075 附近逻辑)。这也解释了为什么 get_bird_status() 返回的 username 字段实际是认证来源标签。

功能二:YouTube 字幕作为第四信息源

使用方式:零密钥、零成本

启用 YouTube 源只需要安装 yt-dlp:

brew install yt-dlp     # 或 pip install yt-dlp

安装后,/last30days 会自动搜索 YouTube、抓取观看量,并从头部视频提取自动生成字幕。首次运行向导(first-run setup wizard)也会自动完成 yt-dlp 安装——见 SKILL.md 中 Step 0 的流程说明(run_auto_setup() 会提取 cookie、安装 yt-dlp 与 Digg CLI,零交互)。

深度配置与字幕预算

skills/last30days/scripts/lib/youtube_yt.py 中的两个表定义了工作预算:

DEPTH_CONFIG = {"quick": 6, "default": 8, "deep": 40}   # 搜索/抓取的候选视频数
TRANSCRIPT_LIMITS = {"quick": 0, "default": 2, "deep": 8}  # 实际提取字幕的视频数上限

即 quick 档只搜视频拿元数据不抓字幕,default 档对前 2 个视频提取字幕,deep 档对前 8 个提取。关于字幕长度:发布文案中写的是"截断到每视频约 500 词",而当前仓库实现的截断常量为 TRANSCRIPT_MAX_WORDS = 5000youtube_yt.py#L59),说明该阈值在 v2.1 之后上调过,以仓库当前值为准。

字幕提取的技术链路

search_youtube() 通过 ytsearchN:<core_topic> 让 yt-dlp 直接输出 JSON 元数据,解析出 view_countlike_countcomment_countupload_date、时长与描述,然后:

  1. 软日期过滤:不加 --dateafter(YouTube 搜索按相关性排序,严格日期过滤对常青主题常返回 0 条),改为 Python 侧软过滤——窗口内结果 ≥3 条时只保留窗口内,否则全部保留(youtube_yt.py#L520-L532L607-L613)。
  2. 按观看量降序排序,头部视频优先进入字幕提取队列。
  3. 字幕抓取:yt-dlp --write-auto-subs --sub-lang en,es,pt --sub-format vtt;语言优先级可经 LAST30DAYS_YT_SUB_LANGS 调整(默认 en,es,pt)。非零退出码被明确判定为"真实抓取错误(限流/机器人验证/网络)"而非"无字幕",瞬态错误按每视频错位的退避(2.0 * (attempt+1) + 0~1s 抖动)重试 2 次(youtube_yt.py#L836-L918)。
  4. 并发与搜索缓存:进程级信号量把并发 yt-dlp 子进程限制在 2(_YTDLP_MAX_CONCURRENT = 2),防止比较模式(comparison fan-out)下相同 IP 踩踏 YouTube 限流;同一次运行内相同查询经 inflight 合并 + 缓存去重(youtube_yt.py#L77-L87)。
  5. 高光抽取extract_transcript_highlights() 过滤口播填充词(subscribe、welcome back 等),按具体度(数字、专有名词、主题词重叠)为句子打分,取 Top 5 可引用片段进入合成。

此外,源码还支持两个发布文案未提的运维能力(从源码结构看属于后来的增强):LAST30DAYS_YOUTUBE_SSH_HOST 可将 yt-dlp 路由到住宅 IP 的远程主机以绕开数据中心 IP 的 bot-wall(youtube_yt.py#L302-L338),以及默认注入 player_client=android 的 extractor-args 以绕过 web bot-gate(youtube_yt.py#L344-L399)。

统一的评分管道

发布文案强调:"YouTube 走与 Reddit 和 X 相同的评分管道——相关性、时效性、互动量。" 源码印证了这一点:每条视频在解析时就计算 relevancetoken_overlap_relevance,与 bird_x.py_compute_relevance 同源),engagement 携带 views/likes/comments,date 提供时效信号——三者随后进入与社交帖子一致的排序与融合阶段。字幕则与社交帖子一起喂给合成引擎,"一条 20 分钟评测包含的信号量是一条推文的 10 倍"这一卖点由此落地。

输出契约与社区沟通

发布文案还固定了两处对外输出格式,供后续版本保持一致:

SKILL.md 状态行(源统计输出格式):

├─ 🔵 X: {N} posts │ {N} likes │ {N} reposts

面向 issue 回复与社交发布的核心信息点(原文档保留的沟通模板,供维护者参考):

  • 对 GitHub issue #19 的回复要点:Bird 已弃用且仓库被删;v2.1 直接内置 X 搜索,无需外部 CLI、无需 npm install、无需 brew,只需 Node.js 22+ 与 AUTH_TOKEN/CT0(或 XAI_API_KEY 回退);同时新增 YouTube 作为第四源;推荐一次性从 x.com 复制 cookie 存入 env 以避开浏览器 cookie 与 Keychain 弹窗。
  • 社媒短版(280 字符内)与 thread 版的四个帖子:分别讲 YouTube 字幕源、X 搜索内置化、统一评分管道与零成本("Just brew install yt-dlp")、以及试用方式 /last30days [any topic]——"Reddit + X + YouTube + Web. Four sources, one command."

适用前提与限制

以当前仓库内容为准,复现 v2.1 这两项能力需要满足:X 搜索要求 Node.js 22+(engines 字段)且 AUTH_TOKENCT0 成对出现才会被判为已认证;YouTube 源要求本机(或配置的 SSH 远程主机)装有 yt-dlp,且 quick 档不提取字幕(TRANSCRIPT_LIMITS.quick = 0)。YouTube 抓取走公共数据接口、无 API 密钥,但受 YouTube 限流与 bot-gate 影响,源码为此内置了重试、退避与并发限制;X 搜索同样可能遭遇反爬拦截页,客户端已做非 JSON 重试与失败形态分类。两项功能均由 skills/last30days/SKILL.md 的首次运行向导自动完成依赖安装,配置则集中存放于 ~/.config/last30days/.env.claude/last30days.env

登录后查看全文
热门项目推荐
相关项目推荐