xhs-note-reader
抓取小红书图文笔记(含图片本体)作为 Claude 上下文。
⚡ TL;DR — 两个固定菜单,必须照抄,不许自由发挥
第一层(用户粘了 xhs 链接但没说要干嘛)
📌 STOP. 你的整个回复 = 下面这个 codeblock 的内容(只替换
<title>和<nickname>)。 回复之后不要再写任何文字。不要 invoke 任何工具。不要"基于内容动态调整选项"。 如果你想自由发挥,把那个冲动留到用户选了 a) 之后。
👀 看了一眼,这是一条小红书图文笔记,标题《<title>》(作者:<nickname>)。想让我:
a) 读一下,给你讲讲这篇在说什么
b) 抓下来整理成 .md 文档存到本地
c) 别的(告诉我)
第二层(用户选了 a 后、读完 6 段输出之后)
接下来想让我:
a) 要不要下载所有图片,打包到一个文件夹?
b) 抓一下评论区(用 Claude in Chrome 扩展走你浏览器的登录态拿)
c) 归档成 .md 文档存到本地(和图片放同一个文件夹)
d) 别的?
🚫 永远不要在菜单里出现的字眼
- 任何内部工具名:xhs-note-reader、脚本、Python、抓取、capture、flow、context、上下文备用 …
- 任何第三方平台:飞书 / Lark / Obsidian / Notion / Apple Notes / Bear / Logseq / Bear / 印象笔记 / 语雀 ……
- 任何"总结要点 / 拆解方法论 / 口头复述" 之类的二次创作——这些是用户选了 a 之后才能聊的事
照抄上面两个 codeblock 的文案,一字不差。要发挥就发挥在内容理解上,不要发挥在菜单措辞上。
何时使用
- 用户消息里出现
xiaohongshu.com/...或xhslink.com/...链接 - 且笔记是图文笔记(脚本会自动检测,遇到视频笔记直接退出并提示用户改用视频转写工具)
触发分支:
| 用户消息 | 行为 |
|---|---|
| 带明确动词(读/总结/翻译/作为上下文/喂给你 …)+ xhs 链接 | 直接跑脚本,跑完按用户动词执行 |
/xhs <url> 或 $xhs <url> | 直接跑脚本,跑完报告路径让用户决定下一步 |
| 裸 xhs 链接,无动词 | 不要自动跑脚本,做轻量 triage:从分享串里的标题/作者识别这是图文笔记,问用户想干什么 |
裸链接 triage —— 只能输出这 3 个固定选项,文案抄死不许改
用户只粘了链接没说要干嘛 → 不要急着抓图。直接照抄这个模板:
👀 看了一眼,这是一条小红书图文笔记,标题《<title>》(作者:<nickname>)。想让我:
a) 读一下,给你讲讲这篇在说什么
b) 抓下来整理成 .md 文档存到本地
c) 别的(告诉我)
a/b/c 是预设动作,不许根据笔记内容动态改写——你不需要"创造",照抄就行。
🚫 DON'T(这些都是真实出现过的违规):
| 错误输出 | 错在哪 |
|---|---|
a) 用 xhs-note-reader 抓下来作为上下文备用 | 暴露了内部工具名 |
b) 抓下来后再总结成要点 / 拆解方法论 | 擅自把 b 改成"总结要点" |
c) 抓下来归档到 Obsidian 或飞书文档 | 提第三方平台 |
| 出现 4 个选项(a/b/c/d 别的) | 这一层只有 3 个选项,没有 d |
| 选项措辞用了"作为上下文"、"flow"、"capture"、"留档备查" 等工程师味儿词 | 措辞要像跟朋友说话 |
✅ DO:
- 照抄模板,3 个选项一字不差——把上面那 3 行复制过去就行
- 标题和作者从分享串里提(xhs 分享文案前面那段
【标题 - 作者 \| 小红书】就是) - 绝不提及任何内部工具名(xhs-note-reader、脚本、Python、抓取……)
- 绝不提及任何第三方平台(飞书 / Obsidian / Notion / Apple Notes / Bear / Logseq……)
- 绝不自作主张把 b 改成"总结要点"或 c 改成"基于内容的追问"——那些是用户选了 a 之后才出现的二级菜单的事
用户选了以后怎么办
- 选 a) → 跑脚本 → 按完整 6 段格式输出(再进入二级 a/b/c/d 菜单)
- 选 b) → 跑脚本拿到
note.md+ 图片 → 一起放到~/Downloads/xhs-<title-slug>/→open文件夹 → 报路径 - 选 c) → 用户会说他要干啥,按用户说的做
如何使用
python3 ~/.claude/skills/xhs-note-reader/scripts/xhs-fetch.py '<url>'
输入可以是:
xhslink.com/o/...短链(脚本会自动跟 302)xiaohongshu.com/discovery/item/<id>?xsec_token=...完整链接(xsec_token必须保留,否则鉴权失败)
成功时 stdout 第一行:
OK <tmpdir>
note.md: <tmpdir>/note.md
images: N
stats: 👍X 💬Y
失败时 stderr 一行原因,退出码 ≠ 0:
- 退出码
2→ 视频笔记,建议引导用户改用视频转写工具(本 skill 不处理视频) - 退出码
1→ 其他错误(鉴权失败、页面结构变了、网络等)
输出结构
<tmpdir>/(系统临时目录,用完即弃;图片 CDN 链接带时间戳,几小时后会 403):
note.md # YAML frontmatter + 正文 + 图片引用 + 互动数
img_01.jpg # 按笔记原顺序
img_02.jpg
...
raw.json # 原始 noteDetail JSON,debug 用
note.md 里图片用  相对引用——Claude 用 Read 工具直接读每张 jpg 即可(多模态原生,不需要 OCR)。
消费输出(强制流程,不可跳过)
核心原则:skill 跑完 ≠ 上下文加载完。你必须把 note.md 和每张图都 Read 进来,才算"读过这篇笔记"。仅看 stdout 的统计数字就回复用户 = 失败。
跑完脚本后,在向用户输出任何文字之前,按顺序执行:
- Read
<tmpdir>/note.md(1 次 Read 调用) - Read 每一张
<tmpdir>/img_NN.jpg(N 次 Read 调用,全部读完,一张都不能省)- 可以在一条消息里并行发起多个 Read 调用以提速
- Claude 是多模态的,Read 图片就是看图,不要"觉得没必要"
- 现在你才真正"读完了这篇笔记",可以开始回复
回复格式要求(强制 6 段结构)
目标:让用户读完你的回复后,不用打开原笔记也能搞懂这篇在讲什么——这个 skill 的使命是"帮用户预读",所以输出必须能替代笔记本身。
固定 6 段,固定顺序,固定 emoji 锚点(让眼睛能扫,让格式可预期):
🔍 这是一篇小红书图文笔记。
📌 标题
<原标题,一字不改>
✍️ 正文(原文)
> <把 desc 整段引用,保留作者的语气、表情、话题 tag,不要总结、不要改写>
🖼️ 图里讲了什么(N 张图)
<**两段式写法,不要 OCR**:
第一段(overall):N 张图整体在讲什么、按什么逻辑组织?**1-2 句话,最多两行**。
只写两件事:
- 叙事逻辑(层层递进 / 平铺清单 / 决策树 / 时间线 / 对比矩阵 / 一图一梗…)
- 整组覆盖的主题("从全景到选品到进阶记忆系统再到产品哲学" 这种一条线)
**禁止描述视觉风格**(米白底、像素吉祥物、等宽英文……都不要写)——用户要的是
"这组图讲了什么",不是"这组图长什么样"。
第二段(逐图,仅当 N≤10 时):每张一行,**讲它在这组里承担的功能 + 一句话 takeaway**,
**不要把卡片上的文字字段全列出来**。
- ❌ OCR 式:"P3 上面是标题"AI 编程最低门槛",下面三个 bullet:可视化界面、共享 CLAUDE.md、本地文件…"
- ✅ 功能 + takeaway 式:"P3 是张决策树——三道是非题把读者引到对应产品;底注收得很温柔("刚开始?从 Chat 用起"),明显是给新手做的"
如果 N>10 或者笔记本身是清单型(每张一个独立条目,如词典/工具盘点/N 个 tip),
可降级为分类聚合(厨房系/魔法系/…),每类点 2-3 个代表即可,不要全数枚举。
**核心区别**:你要写"这张图在干什么"而不是"这张图上有什么字"。
你的读者已经知道这是图文笔记了,不需要你帮他读完字——他需要你帮他**看懂结构**。>
📊 互动
👍 X ⭐ Y 💬 Z 🔁 W
<一句话解读热度信号:收转比是否反常、是否典型的"工具类干货传播曲线"等>
💬 评论区
<暂未抓取(需登录态)。N 条评论。>
🧭 一句话总结
<整篇笔记浓缩成一句,作为用户的「理解校验」>
接下来想让我:
a) 要不要下载所有图片,打包到一个文件夹?
b) 抓一下评论区(用 Claude in Chrome 扩展走你浏览器的登录态拿)
c) 归档成 .md 文档存到本地(和图片放同一个文件夹)
d) 别的?
硬性要求:选项只能是这 4 个,文案固定,不许扩。a/b/c 都是预设动作,不要换成"基于内容的追问"那种动态选项。用户想延伸具体内容方向,会走 d) 自己说。
两个固定入口的具体处理:
共用的目标目录约定
a) 下载图片 和 c) 归档 .md 都落到同一个文件夹:
~/Downloads/xhs-<title-slug>/
<title-slug>= 笔记标题(保留中文,去掉/、换行、不可见字符;过长截前 30 字)- 整个 skill 运行期间,slug 算一次就锁定,a 和 c 用同一个
- 文件夹若已存在:
- 同笔记重复操作(a 后再 c,或反之)→ 复用同一文件夹,不要新建
-2 - 真的撞名(不同笔记同标题,少见)→ 追加
-2、-3
- 同笔记重复操作(a 后再 c,或反之)→ 复用同一文件夹,不要新建
- 路径不要写在菜单选项的描述里——只在动作完成后报告
「a) 下载所有图片」具体处理
SRC=<tmpdir>; DST="$HOME/Downloads/xhs-<title-slug>"
mkdir -p "$DST" && cp "$SRC"/img_*.jpg "$DST"/
( command -v open >/dev/null && open "$DST" ) || ( command -v xdg-open >/dev/null && xdg-open "$DST" ) || true
末行那条链式命令是为了跨平台:
open是 macOS 原生命令,Linux 用xdg-open。两个都没有就静默跳过(用户得自己进文件夹)。所有用到"打开文件夹" 的地方都按这个模板写。
- 只复制
img_*.jpg,不带note.md/raw.json open必须——自动用 Finder 打开文件夹,不让用户自己翻- 反馈格式:
✅ 已下载 16 张图到
~/Downloads/xhs-你可能不认识的Claude-Code加载词/已用 Finder 打开。
「c) 归档成 .md 文档」具体处理
SRC=<tmpdir>; DST="$HOME/Downloads/xhs-<title-slug>"
mkdir -p "$DST" && cp "$SRC"/note.md "$DST"/
( command -v open >/dev/null && open "$DST" ) || ( command -v xdg-open >/dev/null && xdg-open "$DST" ) || true
- 只复制
note.md(脚本生成的那份,含 YAML frontmatter + 正文 + 互动数 + 图片引用) - 如果
$DST里已经有图片(用户先选了 a 又选 c)→note.md里的相对引用直接生效,在 Markdown 编辑器里可以渲染 - 如果用户只选了 c 没下图 →
note.md里的图片引用会指向不存在的文件。默认不下图,但反馈里要提醒用户 - 反馈格式:
✅ 已归档
.md到~/Downloads/xhs-你可能不认识的Claude-Code加载词/note.md已用 Finder 打开。 (如需图片一起留存,再选 a 即可)
「b) 抓评论区」具体处理
xhs 评论 API 需要登录态签名,无 cookie 时返回 -101 无登录信息。绕路是借
Claude in Chrome MCP(官方扩展,工具前缀 mcp__claude-in-chrome__*)让
Chrome 用用户自己的登录态去拿。
步骤 0:兼容性检测(每次都先做)
用户选 b 之前你必须先确认 mcp__claude-in-chrome__* 这族工具是否可用:
-
检查方式:用
ToolSearch query: "claude-in-chrome"或直接看本会话工具列表里有没有mcp__claude-in-chrome__tabs_context_mcp、mcp__claude-in-chrome__navigate等 -
检测结果分支:
状态 行动 MCP 工具已就绪 直接进步骤 1 工具不存在 / 未连接 进入「安装引导」分支,不要让用户摸黑
「安装引导」分支文案(用户没装 Claude in Chrome 时贴这套):
这个功能需要 Claude in Chrome 扩展(用你浏览器的 xhs 登录态拿评论)。三步可装好:
- 装扩展:https://chromewebstore.google.com/detail/claude/fcoeoabgfenejglbffodgkkbkcdhcgfn
- 在本会话跑
/chrome——会自动写 native messaging 配置
- macOS:
~/Library/Application Support/Google/Chrome/NativeMessagingHosts/- Linux:
~/.config/google-chrome/NativeMessagingHosts/- 完全退出 Chrome 再开(macOS 是 ⌘Q;Linux
pkill chrome)+ 重启本 Claude Code 会话(MCP 列表是启动时加载的)前提:Claude Max 订阅(Pro 不行);Chrome 或 Edge(Arc / Brave / WSL 不行)。 装完告诉我,我重新跑一遍。
装不了的话也行——评论我抓不到,但其他 6 段内容是完整的。
步骤 1:navigate + 抓评论 DOM
mcp__claude-in-chrome__navigate到笔记的完整 xiaohongshu.com URL(保留xsec_token,丢了拿不到登录态内容)- 等页面 load 完,用
javascript_tool跑 DOM 查询:- 根评论节点选择器:
[class*="comment-item"](注意 class 名可能含 hash,用[class*="..."]模糊匹配) - 找
查看 N 条回复/展开按钮,程序化点击展开(一般 1-3 个) - 再次查询,拿到全部主评 + 已展开回复
- 根评论节点选择器:
- 提取每条:作者、文本、点赞数、(如有)回复
- 预期与显示数的 gap:xhs 显示的"评论 N 条"可能 > 实抓数,差额来自更深嵌套 / 折叠 / 被删评论。这是正常的,在反馈里坦白提一句即可
步骤 2:在会话里给出评论摘要
按以下结构呈现,不要原样贴所有评论(用户要的是信号不是噪声):
💬 评论区抓取完成(共 N 条,显示数 M——差额来自更深嵌套或折叠)
主线议题:
- <2-4 句话,看完所有评论后总结大家在讨论什么>
值得注意的几条:
- @用户A(👍 X):"...原话引用..." ← 标注为什么有意思
- @用户B(👍 Y):"..."
- ...(3-5 条高赞 / 有信息量的)
未回答的关键提问:
- @用户C 问 "X"——作者没回 / 评论区也没人答
作者运营节奏(如有):
- 作者回了 N 条,集中在 <时间点>,主要在 <回答/感谢/引导>
步骤 3:主动追问(必做,不能跳)——把成果固化到本地
抓完评论后,根据"本次会话有没有归档过 note.md"分两条路追问:
- 情况 A:已经归档过 note.md(用户之前从二级菜单选过 c,文件已在
~/Downloads/xhs-<slug>/note.md)要不要我把这份评论也追加到
note.md里?路径~/Downloads/xhs-<slug>/note.md。- 用户同意 → 在 not