Skill Seekers RSS 技能生成:SKILL.md 金标输出结构与截断规范解析

原创2026-09-22 09:31:351,628 阅读
文章标签:人工智能AI 应用AI 技能RAGMCP 服务网页爬虫

Skill Seekers RSS 技能生成:SKILL.md 金标输出结构与截断规范解析

导读

本文以 Skill Seekers 仓库中 tests/golden/phase2/rss/SKILL.md 金标(golden)输出文件为骨架,完整解析 RSS/Atom 订阅源(Feed)被转换为 Claude AI Skill 后生成的 SKILL.md 结构规范:从前置元数据、Feed 信息块、文章概览到标签溢出与截断规则,并逐一对应到 RSS 抓取器源码 与 金标测试用例 的实现细节。读完本文,你将掌握 Skill Seekers 生成 RSS 技能的文件布局、字段约定、边界条件处理方式,以及如何用一条命令把一个技术博客的订阅源变成可被 Claude 直接引用的结构化技能。

一、金标文件的定位:什么是 RSS 技能的 SKILL.md

tests/golden/phase2/rss/SKILL.md 不是一篇普通文档,而是一份金标输出(golden output)——它是 Skill Seekers 在测试阶段对 RSS 抓取器产物做的“快照基准”。测试代码在 tests/test_phase2_golden_rss.py 顶部有明确说明:

The golden trees under tests/golden/phase2/rss* were captured from the PRE-DocumentSkillBuilder code; these tests prove the port is byte-identical.

也就是说,这份 SKILL.md 与同目录下的 references/ 子目录一起,构成一棵金标目录树,用于证明重构后的 RSS 构建路径与旧代码逐字节一致(byte-identical)。它同时是一份极具参考价值的“成品规格”:展示了当用户运行 skill-seekers rss 抓取一个真实 Feed 后,生成的技能入口文件应该长什么样。

这份金标文件围绕一个虚构的测试订阅源 https://example.com/feed.xml(标题 "Example Engineering Blog",类型 RSS 2.0,由 ExampleCMS 2.0 生成)构建,包含 4 篇文章、2 位作者、55 个标签。所有 URL 均为测试占位符,切勿视为真实数据。

二、RSS 技能的整体产物布局

根据金标目录树 tests/golden/phase2/rss/,一个 RSS 技能的完整产物结构如下:

rss/
├── SKILL.md                      # 技能入口:Feed 概览 + 导航
└── references/
    ├── index.md                  # 分类索引 + 统计信息
    ├── dev_ops.md                # 按标签归类的文章参考文件
    ├── python.md
    ├── uncategorized.md
    └── unnamed.md                # 全符号标签(★★★)的兜底文件名

这个结构由 RssToSkillConverter 负责生成。它继承自 DocumentSkillBuilder 的 build_skill 编排逻辑,但针对 RSS 数据“以文章(articles)+ 标签(tags)而非页面(pages)+ 标题(headings)为形态”的特点,重写了分类、参考文件生成、索引生成与 SKILL.md 生成四个环节(源码类注释对此有明确说明)。

index.md 的生成逻辑见 _generate_index,SKILL.md 的生成逻辑见 _generate_skill_md。下面逐区块拆解 SKILL.md 的构成。

三、YAML 前置元数据:name 与 description 的规范化

金标 SKILL.md 的开头是标准的 YAML frontmatter:

---
name: golden-rss
description: Use when testing the rss golden build
---

对应源码逻辑位于 _generate_skill_md:

  • name:取用户传入的 config["name"],统一转为小写、下划线与空格替换为连字符、截断到 64 字符。因此配置名 golden_rss 最终变成 golden-rss。
  • description:若用户未显式提供,会由 _infer_description_from_feed 根据 Feed 元数据自动推断——优先用 Feed 的 description(超过 150 字符时截断到 147 字符加省略号),其次用 Feed 标题拼出 Use when referencing articles from {title};最终写入 frontmatter 前还会被截断到 1024 字符以内。

description 是 Claude/Agent 判定“何时使用该技能”的关键信号,因此生成器始终以 Use when... 句式输出,保证语义一致性。

四、📡 Feed Information 区块:订阅源元数据的完整呈现

金标文件在这一区块输出了 7 个字段,覆盖 Feed 级元数据的全部关键维度:

字段 金标示例值 数据来源(feedparser 字段)
Feed Title Example Engineering Blog feed.title
Feed Type RSS 2.0 由 parsed.version 检测(见下)
Website https://example.com feed.link
Language en-us feed.language
Description 长描述截断至 300 字符 feed.subtitle 或 feed.description
Generator ExampleCMS 2.0 feed.generator
Rights © Example Inc. feed.rights

Feed 类型检测在 _detect_feed_type 中完成,支持四种取值:RSS 2.0、RSS 1.0 (RDF)、Atom、Unknown。检测优先级是:先看 feedparser 的 version 字段(含 "atom"、"rss20"、"rss10/rdf" 等关键词),再退回启发式判断(检查 xmlns 命名空间或 rss_version 字段)。

Description 的 300 字符截断是本区块最值得注意的规范:金标测试特意构造了一个超长描述(见测试文件中的 LONG_FEED_DESCRIPTION),源码中对应的处理是:

if len(feed_desc) > 300:
    feed_desc = feed_desc[:297] + "..."

即超过 300 字符时,保留前 297 字符并以省略号结尾,保证信息块在技能入口文件中保持紧凑。

五、💡 When to Use 与 📖 Article Overview:技能的用途声明与内容盘点

When to Use This Skill 区块是生成器固定的 5 条“何时使用”清单,由源码逐行写入(_generate_skill_md):

  • Reference articles and content from Example Engineering Blog
  • Look up specific topics covered in the feed
  • Find author perspectives and expert analysis
  • Review recent posts and updates on the subject
  • Explore categorized content by tags or topics

紧随其后的 Article Overview 区块输出文章总数与分类分布,分类分布来自 categorize_content() 的返回结果(_categorize_content),其核心逻辑是:

  1. 取每篇文章的 categories(由 feedparser 的 tags 字段提取);
  2. 文章没有标签时落入 uncategorized 桶;
  3. 分类键经 _sanitize_filename 清洗后作为去重与文件名依据;
  4. 若整个 Feed 一篇文章都没有,则回退为单一的 all_articles 桶(金标树 tests/golden/phase2/rss_empty/SKILL.md 演示了空 Feed 场景)。

金标示例的分类分布为:Dev Ops 1 篇、Python 1 篇、uncategorized 1 篇、★★★ 1 篇,与 4 篇总数严格对应。

六、📰 Recent Articles 区块:摘要的 200 字符截断与元数据行

这是 SKILL.md 的信息密度核心。金标示例展示了 4 篇文章的三种元数据形态:

### Continuous Delivery in Practice

**Published:** Mon, 01 Jan 2024 10:00:00 GMT | **Author:** Jane Doe

This is a deliberately long summary that keeps going well past the two hundred character truncation threshold...(截断效果)

摘要截断规则:源码对每篇文章的 summary 做 summary<a href="https://link.gitcode.com/i/472b7b1432a11c94284dde5f08b6dd23" target="_blank">:200] + "..." 处理([_generate_skill_md),即超过 200 字符截断并追加省略号。金标测试特意把第一篇文章的摘要写得远超 200 字符,用于验证此分支。

元数据行组装规则:Published 与 Author 用 | 连接成一行,但两者均可选——无发布日期的文章(如 "An Uncategorized Note")只显示作者,无作者的文章(如 "Symbols Only")只显示发布时间。每条文章末尾输出 Read more,无链接(如 "An Uncategorized Note")则不输出。

Recent 列表上限:取文章列表的前 10 篇(articles[:10]),对于超大 Feed,SKILL.md 只展示最新 10 篇,其余内容全部沉淀到 references 参考文件中,保证入口文件不至于膨胀。

七、✍️ Authors、🏷️ Tags 与 📊 Feed Statistics:统计维度的三个区块

Authors:由 _count_authors 统计每篇文章的 author 字段并按文章数降序排列,SKILL.md 展示前 15 位,索引文件展示前 20 位。金标示例为 Jane Doe 2 篇、John Roe 1 篇。

Tags:展示全部唯一标签,最多列出前 50 个,超出部分以 ... and N more 结尾:

`Dev Ops`, `Python`, `dev-ops`, `tag00`, ..., `tag46` ... and 5 more

金标测试用 55 个标签专门验证了这条溢出分支(tag00~tag50 共 51 个,加 4 个主题标签共 55 个,多出的 5 个触发 and 5 more)。注意这里不截断标签内容,只截断数量,与摘要/描述的字符截断形成对照。

Feed Statistics:汇总输出 6 项统计,其中 Full Content Scraped 直接反映 follow_links 配置:

  • Total Articles / Feed Type / Categories-Tags / Authors / Full Content Scraped(Yes/No)/ Date Range

Date Range 由 _get_date_range 计算:取全部文章 published_iso 的最小值与最大值(仅取日期部分 [:10])。金标示例为 2024-01-01 to 2024-03-15。

八、🗺️ Navigation 区块与 references 参考文件体系

SKILL.md 的收尾区块是指向参考文件的导航清单,金标示例:

**Reference Files:**

- `references/dev_ops.md` - Dev Ops (1 articles)
- `references/python.md` - Python (1 articles)
- `references/uncategorized.md` - uncategorized (1 articles)
- `references/unnamed.md` - ★★★ (1 articles)

See `references/index.md` for complete feed structure.

这里隐藏着 RSS 构建路径的两个关键边界处理,也正是金标测试重点覆盖的场景:

8.1 重叠归一化键的去重("Dev Ops" 与 "dev-ops")

categorize_content 中,分类名 Dev Ops 与 dev-ops 经 _sanitize_filename 清洗后都变成 dev_ops,会落入同一个分类桶。源码通过维护已加入文章的 id 集合来避免同一篇文章被重复收录(_categorize_content)。金标测试的第一篇文章故意携带 <a href="https://link.gitcode.com/i/ca3abb936b19056417e24212fc36a51e" target="_blank">"Dev Ops", "dev-ops"] 两个标签来触发此守卫。查看 [references/dev_ops.md 可确认该文章只出现一次,且 Tags 行完整保留了原始双标签 Dev Ops, dev-ops。

8.2 全符号标签的 "unnamed" 兜底("★★★")

_sanitize_filename 会把非字母数字字符剥离:★★★ 清洗后得到空字符串。源码的 _sanitize_filename 以 return safe or "unnamed" 兜底,确保不产生空文件名——这正是 references/unnamed.md 的由来,其内容见 references/unnamed.md。

8.3 参考文件内部结构

每个分类参考文件(如 references/python.md)按“分类标题 → 文章数 → 每篇文章的元数据块(Author / Published / Link / Tags)→ Summary → Content → Full Article”的固定顺序排版。三个内容来源有明确优先级与条件:

  • Summary:总是输出;
  • Content:仅当 Feed 内联正文(content)存在且与 summary 不同才输出(金标测试第二篇文章 content == summary,专门验证该分支被跳过);
  • Full Article:仅当 follow_links 抓取到完整页面文本(full_text)时输出,见 references/uncategorized.md 中由 "An Uncategorized Note" 展示的 ### Full Article 区块。

index.md 则聚合全部分类链接与统计信息,格式见 references/index.md。

九、金标验证:如何保证字节级一致

金标树不是静态展示,而是由测试动态校验的。核心测试为 test_phase2_golden_rss.py 中的 test_rss_build_matches_golden:

converter = RssToSkillConverter({
    "name": "golden_rss",
    "description": "Use when testing the rss golden build",
    "feed_url": "https://example.com/feed.xml",
    "output_dir": str(tmp_path / "skill"),
})
converter.extracted_data = _extracted_data()
assert_matches_golden(build_snapshot(converter), "rss")

测试直接注入 _extracted_data() 构造的 4 篇文章(覆盖:双标签去重、无标签文章、无链接/日期/作者文章、纯符号标签、55 个标签溢出、长摘要、长 Feed 描述),调用转换器生成快照,与金标树逐字节比对。配套的 test_rss_empty_feed_matches_golden 则用空 Feed 验证 all_articles 兜底与 Full Content Scraped: No 统计分支。

这意味着你看到的这份金标 SKILL.md 的每一个字符,包括省略号、空格、连字符,都是可回归测试的“契约”,任何重构都必须保持逐字节不变。

十、从金标到实战:如何生成自己的 RSS 技能

金标文件对应的是完整抓取流水线的“输出端”。输入端由 RssToSkillConverter 的 extract_feed() 驱动,CLI 用法(见 rss_scraper.py 模块 docstring):

# 从远程 Feed URL 抓取(默认跟随文章链接抓取全文)
skill-seekers rss --feed-url https://example.com/feed.xml --name myblog

# 从本地 Feed XML 文件解析
skill-seekers rss --feed-path ./feed.xml --name myblog

# 不跟随文章链接,仅用 Feed 内的摘要与内联正文
skill-seekers rss --feed-url https://example.com/rss --no-follow-links --name myblog

# 复用已抽取的中间 JSON 继续构建
skill-seekers rss --from-json myblog_extracted.json

# 等价于直接调用模块
python3 -m skill_seekers.cli.rss_scraper --feed-url https://example.com/atom.xml --name myblog

可配置项及其默认值(来自 _init):

配置项 默认值 说明
feed_url / feed_path 必选其一 远程 URL 或本地 XML 文件
follow_links True 是否跟随文章链接抓取全文(对应金标中 Full Content Scraped: Yes)
max_articles 50 最多处理文章数(entries[:max_articles])
description 自动推断 覆盖自动生成的 Use when 描述

两个值得注意的运行时保护:抓取全文时每篇文章请求超时 15 秒、请求间固定间隔 1 秒(_REQUEST_DELAY),并设有 180 秒总时间预算(_FOLLOW_TIME_BUDGET),慢速 Feed 不会无限阻塞构建(_extract_feed);单篇文章正文上限 50000 字符,超出截断并追加 [Content truncated]。此外,RSS 功能依赖可选依赖 feedparser,未安装时会明确提示 pip install "skill-seekers[rss]"。

结语:金标文件是一份可执行的输出规范

tests/golden/phase2/rss/SKILL.md 的价值远超“测试样本”:它完整定义了 Skill Seekers 将 RSS/Atom 订阅源转化为 Claude 技能时的入口文件规范——frontmatter 的命名与描述约定、Feed 元数据的 7 字段呈现、300/200/1024 字符与 50 标签的四类截断边界、uncategorized/unnamed/all_articles 三种兜底分类,以及 references 参考文件体系的排版规则。结合 RSS 抓取器源码、金标测试 与 references 目录 相互印证,读者既可以把这份文件当作格式参考来审查自己生成的技能,也可以把它当作理解整个 RSS→Skill 管线的入口地图。

登录后查看全文
Skill_Seekers