news 2026/9/5 23:22:33

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
last30days-skill v2.1 版本解析:X 搜索内置化与 YouTube 字幕源的实现原理

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

【免费下载链接】last30days-skillAI agent skill that researches any topic across Reddit, X, YouTube, HN, Polymarket, and the web - then synthesizes a grounded summary项目地址: https://gitcode.com/GitHub_Trending/la/last30days-skill

本文基于 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 时代依赖外部birdCLI 的 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+ plusAUTH_TOKENandCT0"的表述。

第二个动因是 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 = 5000(youtube_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-L532 与 L607-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 搜索内置化、统一评分管道与零成本("Justbrew 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

【免费下载链接】last30days-skillAI agent skill that researches any topic across Reddit, X, YouTube, HN, Polymarket, and the web - then synthesizes a grounded summary项目地址: https://gitcode.com/GitHub_Trending/la/last30days-skill

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/5 23:15:38

Python实现播放量月报自动化:准神话曲统计系统实战

相信很多长期关注“术力口”文化圈的朋友&#xff0c;每个月都有类似的习惯&#xff1a;等着看一批播放量数据接近“神话级”的曲目更新。与其说这是单纯的音乐盘点&#xff0c;不如说它是一套典型的“数据指标监控”需求——把作品的播放量按固定周期拉成快照&#xff0c;再计…

作者头像 李华
网站建设 2026/9/5 23:12:38

蒸烤一体机大彩屏值不值?凯度52L Pro从三层系统拆解

如果你最近在看嵌入式蒸烤箱&#xff0c;一定绕不开凯度 SR52FDF24-TR Pro 这类带“大彩屏”的 52L 蒸烤一体机。商品页最显眼的位置写着“19 英寸彩屏”&#xff0c;下面跟着一长串智能菜谱和 APP 联动介绍。很多人看完第一反应是&#xff1a;好像很高级&#xff0c;但它真的值…

作者头像 李华
网站建设 2026/9/5 23:10:15

沙盒游戏生物更新:从加法到乘法的数据驱动开发

如果你经常逛独立游戏社区&#xff0c;会看到很多世界类项目更新公告长这样&#xff1a;“26N8.8更新&#xff01;新生物&#xff1a;藻虫&#xff0c;改模生物&#xff1a;虹蝾螈&#xff08;瞎取的&#xff09;&#xff0c;顺便聊突变叠加。” 标题越短&#xff0c;信息量往往…

作者头像 李华
网站建设 2026/9/5 23:09:09

游戏内容更新指南:新生物、改模与突变叠加规则梳理

索纳里亚世界的 26N8.8 更新内容&#xff0c;标题里写得非常直接&#xff1a;新生物藻虫、改模生物虹蝾螈、以及一次关于突变叠加的规则梳理。这个组合乍看是三个不相关的事&#xff0c;实际拆开以后是三条非常清楚的线&#xff1a;新增内容、存量内容修改、机制口径统一。如果…

作者头像 李华
网站建设 2026/9/5 23:08:10

Spring Boot 3 + Vue 3 实现活动嘉宾展示与在线预约报名

先来聊一个很常见的需求场景。任何一场线下嘉宾秀、发布会、校园晚会或公司年会&#xff0c;除了内容本身之外&#xff0c;总是绕不开“观众如何了解嘉宾、如何报名、如何查看流程”这类问题。标题里提到的 KISS N TELL 嘉宾秀&#xff08;KDC 26.8.8&#xff09;&#xff0c;如…

作者头像 李华