Xiaohongshu Scraper
Overview
Use this skill for 小红书笔记链接抓取和表格回填. Prefer reliable, low-frequency access patterns and preserve user intent: do not invent engagement numbers when the public page hides them.
Browser Profile
Use the dedicated Xiaohongshu browser profile and CDP endpoint when a logged-in visible browser is explicitly needed:
- CDP URL:
http://127.0.0.1:9223
- user-data-dir:
$HOME/Library/Application Support/Google/SocialScraperProfiles/Xiaohongshu
- launcher:
~/.agents/social-browser-profiles/launch-social-chrome.sh xhs
Do not use the default Chrome profile for Xiaohongshu scraping. Do not share this port/profile with Douyin or Weibo jobs.
The Base entrypoint uses a local platform lock at /tmp/social-scraper-locks/xiaohongshu.lock; do not run two Xiaohongshu jobs at the same time from different sessions.
Workflow
- Extract canonical URLs from raw text, Markdown links, or Base cells.
- Run the static scraper first:
node ~/.agents/skills/xiaohongshu-scraper/scripts/scrape-xhs.mjs --json --delay-ms 6000 < urls.txt
- For Lark Base batch work, use the safe Base entrypoint instead of shell loops:
node ~/.agents/skills/xiaohongshu-scraper/scripts/process-lark-xhs.mjs \
--base-token <base_token> \
--table-id <table_id> \
--view-id <view_id> \
--batch-size 10
- If a URL returns only
小红书, 404, or 当前内容无法展示, retry with a real Chrome profile only when the user agrees:node ~/.agents/skills/xiaohongshu-scraper/scripts/process-lark-xhs.mjs \
--base-token <base_token> \
--table-id <table_id> \
--view-id <view_id> \
--browser-confirm \
--chrome-user-data-dir "$HOME/Library/Application Support/Google/SocialScraperProfiles/Xiaohongshu" \
--batch-size 3
- For Lark Base updates, read the table fields first. Default runs process records whose
抓取状态 is blank, 准备抓取, or 保持抓取.
- Write only storage fields such as
正文, 点赞数, 收藏数, 抓取时间, and confirmed terminal 抓取状态. Use lark-base for Base commands.
- Process in very small batches. Default: 3-5 records when using a logged-in browser, 10 records only for static H5. Stop when failures cluster.
scrape-xhs.mjs --json Output
{"ok": true, "url": "...", "finalUrl": "...", "noteId": "6a35...",
"title": "...", "desc": "...", "body": "title\ndesc",
"noteType": "video|image", "publishedAt": 1781884007000,
"likedCount": 198, "collectedCount": 130, "commentCount": 8,
"imageUrls": ["https://sns-webpic-qc.xhscdn.com/..."]}
imageUrls takes the largest available rendition per image (H5_DTL > H5_PRV). The original
is not reachable — stripping the processing parameters returns 403, and every downloadable
rendition carries the Xiaohongshu watermark plus whatever caption the creator burned in. Treat
these images as internal reference only; they are not publishable assets.
Counts are null when the page omits them, unless --missing-count-as-zero is passed. A null
count means "not reported", not zero.
Do not wrap scrape-xhs.mjs --browser in a shell loop for Base work. It is a lower-level scraper; use process-lark-xhs.mjs so status filtering, failure fuses, and Base writes stay consistent.
Lark Status Rules
Use 抓取状态 as the control plane:
- blank/null: treat as
准备抓取.
准备抓取: new or newly appended row, eligible for first scraping. Fetch 正文, 点赞数, 收藏数, and 抓取时间.
保持抓取: first scrape succeeded and data has been written; refresh only 点赞数, 收藏数, and 抓取时间. Do not fetch or overwrite 正文 by default.
抓取异常: confirmed inaccessible, app-only, login-wall, 404, repeated no-note-state, or platform warning risk. Do not retry automatically.
停止抓取: manual or rule-based stop state for rows that no longer need engagement tracking.
Default runs scrape rows whose 抓取状态 is blank, 准备抓取, or 保持抓取. Treat blank as 准备抓取. When a 准备抓取 row succeeds, write the scraped body and engagement fields, then set 抓取状态 to 保持抓取. When a 保持抓取 row succeeds, update only engagement fields and 抓取时间; keep 正文 and 抓取状态 unchanged. When a row is confirmed failed after the allowed fallback path, set 抓取状态 to 抓取异常, write 抓取时间, and preserve existing useful values.
Comment Status Rules
Use 评论状态 as a separate operations queue. Keep it blank by default. The scraper may set 准备评论 only when a configured engagement threshold is reached or the user explicitly asks to queue rows for manual commenting; it must not publish Xiaohongshu comments automatically.
- blank/null: default, not yet selected for commenting.
准备评论: selected by threshold or manual review and waiting for human commenting on Xiaohongshu.
取消评论: manually decided not to comment.
评论成功: human comment has been posted.
评论失败: a comment attempt failed and is not currently being retried.
For now, Xiaohongshu commenting is all manual. The skill can help surface candidates by writing 评论状态=准备评论, but comment publishing and final status changes are handled by the user. 准备评论 on Xiaohongshu means "ready for a human to comment", not "auto-comment now".
Video Notes
When the row is marked 视频 or the note state contains video streams:
- Download the video from the note's resolved stream URL when available, or use the local
video-download skill if the stream URL is not directly exposed.
- Extract representative frames with ffmpeg:
ffmpeg -hide_banner -loglevel error -i video.mp4 -vf "fps=1/2,scale=720:-1" frames/frame_%03d.jpg
- If MiniMax is configured, analyze the clearest frames with
mmx vision describe:mmx vision describe --region global --image frames/frame_001.jpg --prompt "请提取这帧里的字幕、画面主体和对理解小红书视频正文有用的信息。"
- Combine title, original desc, visible captions, and visual summaries into
正文. Clearly mark inferred video content as 【视频内容解析】.
MiniMax requires local authentication (MINIMAX_API_KEY or mmx auth login). If unavailable, fall back to manual frame review and say so. Video rows are higher risk and slower; process fewer per batch.
Output Rules
正文: title + newline + desc when both exist. Write this only for 准备抓取 rows unless the user explicitly requests body reprocessing.
- For videos, append a concise
【视频内容解析】 section when frame/video evidence is available.
点赞数 / 收藏数: refresh for both 准备抓取 and 保持抓取 rows. Leave unavailable values unchanged/null unless the user explicitly asks to treat hidden values as 0.
抓取时间: use the user's current local datetime rounded to minutes, e.g. YYYY-MM-DD HH:mm:00, when the Base field supports time.
抓取状态: write 保持抓取 only after a successful 准备抓取 first scrape. Keep 保持抓取 unchanged during engagement refresh. Write 抓取异常 only after an access failure is confirmed and no automatic retry should happen. Never write 停止抓取 automatically unless a separate stop-tracking rule is explicitly enabled.
评论状态: blank by default; write 准备评论 only when an engagement threshold or explicit user instruction selects the row for commenting. Xiaohongshu 准备评论 means a human should comment.
- Preserve failed rows and report why they failed; do not overwrite useful existing values with blanks.
Safety And Access
- Do not bypass CAPTCHAs, paywalls, private content, account restrictions, or platform access controls.
- Do not export or print cookies, tokens, localStorage, QR codes, or profile secrets.
- Default to non-logged-in static/H5 scraping. Use the user's own logged-in Chrome profile only as a fallback after consent. Keep rate low and human-paced.
- Do not repeatedly test rows already confirmed as inaccessible. Mark them
抓取异常.
- Browser mode must reuse one browser session for a batch; do not launch and close Chrome for each URL.
- If using a visible CDP browser, use port
9223 and the Xiaohongshu profile only.
- Stop immediately after a platform warning or CAPTCHA/login-risk signal.
- Do not rotate IPs or use third-party proxies unless the user explicitly provides a compliant, owned proxy and the task is permitted.
References
- Read
references/strategy.md before changing crawl behavior, retry policy, browser profile usage, or Lark Base write semantics.
1---2name: xiaohongshu-scraper3description: Use when a user provides Xiaohongshu/XHS/xhslink URLs, asks to fetch 小红书 note or video content, likes, saves/collections, comments, publish metadata, or wants to fill a spreadsheet/Base from 小红书 links.4---56# Xiaohongshu Scraper78## Overview910Use this skill for 小红书笔记链接抓取和表格回填. Prefer reliable, low-frequency access patterns and preserve user intent: do not invent engagement numbers when the public page hides them.1112## Browser Profile1314Use the dedicated Xiaohongshu browser profile and CDP endpoint when a logged-in visible browser is explicitly needed:1516- CDP URL: `http://127.0.0.1:9223`17- user-data-dir: `$HOME/Library/Application Support/Google/SocialScraperProfiles/Xiaohongshu`18- launcher: `~/.agents/social-browser-profiles/launch-social-chrome.sh xhs`1920Do not use the default Chrome profile for Xiaohongshu scraping. Do not share this port/profile with Douyin or Weibo jobs.21The Base entrypoint uses a local platform lock at `/tmp/social-scraper-locks/xiaohongshu.lock`; do not run two Xiaohongshu jobs at the same time from different sessions.2223## Workflow24251. Extract canonical URLs from raw text, Markdown links, or Base cells.262. Run the static scraper first:27 ```bash28 node ~/.agents/skills/xiaohongshu-scraper/scripts/scrape-xhs.mjs --json --delay-ms 6000 < urls.txt29 ```303. For Lark Base batch work, use the safe Base entrypoint instead of shell loops:31 ```bash32 node ~/.agents/skills/xiaohongshu-scraper/scripts/process-lark-xhs.mjs \33 --base-token <base_token> \34 --table-id <table_id> \35 --view-id <view_id> \36 --batch-size 1037 ```384. If a URL returns only `小红书`, `404`, or `当前内容无法展示`, retry with a real Chrome profile only when the user agrees:39 ```bash40 node ~/.agents/skills/xiaohongshu-scraper/scripts/process-lark-xhs.mjs \41 --base-token <base_token> \42 --table-id <table_id> \43 --view-id <view_id> \44 --browser-confirm \45 --chrome-user-data-dir "$HOME/Library/Application Support/Google/SocialScraperProfiles/Xiaohongshu" \46 --batch-size 347 ```485. For Lark Base updates, read the table fields first. Default runs process records whose `抓取状态` is blank, `准备抓取`, or `保持抓取`.496. Write only storage fields such as `正文`, `点赞数`, `收藏数`, `抓取时间`, and confirmed terminal `抓取状态`. Use `lark-base` for Base commands.507. Process in very small batches. Default: 3-5 records when using a logged-in browser, 10 records only for static H5. Stop when failures cluster.5152## `scrape-xhs.mjs --json` Output5354```json55{"ok": true, "url": "...", "finalUrl": "...", "noteId": "6a35...",56 "title": "...", "desc": "...", "body": "title\ndesc",57 "noteType": "video|image", "publishedAt": 1781884007000,58 "likedCount": 198, "collectedCount": 130, "commentCount": 8,59 "imageUrls": ["https://sns-webpic-qc.xhscdn.com/..."]}60```6162`imageUrls` takes the largest available rendition per image (`H5_DTL` > `H5_PRV`). The original63is not reachable — stripping the processing parameters returns 403, and every downloadable64rendition carries the Xiaohongshu watermark plus whatever caption the creator burned in. Treat65these images as internal reference only; they are not publishable assets.6667Counts are `null` when the page omits them, unless `--missing-count-as-zero` is passed. A `null`68count means "not reported", not zero.6970Do not wrap `scrape-xhs.mjs --browser` in a shell loop for Base work. It is a lower-level scraper; use `process-lark-xhs.mjs` so status filtering, failure fuses, and Base writes stay consistent.7172## Lark Status Rules7374Use `抓取状态` as the control plane:7576- blank/null: treat as `准备抓取`.77- `准备抓取`: new or newly appended row, eligible for first scraping. Fetch `正文`, `点赞数`, `收藏数`, and `抓取时间`.78- `保持抓取`: first scrape succeeded and data has been written; refresh only `点赞数`, `收藏数`, and `抓取时间`. Do not fetch or overwrite `正文` by default.79- `抓取异常`: confirmed inaccessible, app-only, login-wall, 404, repeated no-note-state, or platform warning risk. Do not retry automatically.80- `停止抓取`: manual or rule-based stop state for rows that no longer need engagement tracking.8182Default runs scrape rows whose `抓取状态` is blank, `准备抓取`, or `保持抓取`. Treat blank as `准备抓取`. When a `准备抓取` row succeeds, write the scraped body and engagement fields, then set `抓取状态` to `保持抓取`. When a `保持抓取` row succeeds, update only engagement fields and `抓取时间`; keep `正文` and `抓取状态` unchanged. When a row is confirmed failed after the allowed fallback path, set `抓取状态` to `抓取异常`, write `抓取时间`, and preserve existing useful values.8384## Comment Status Rules8586Use `评论状态` as a separate operations queue. Keep it blank by default. The scraper may set `准备评论` only when a configured engagement threshold is reached or the user explicitly asks to queue rows for manual commenting; it must not publish Xiaohongshu comments automatically.8788- blank/null: default, not yet selected for commenting.89- `准备评论`: selected by threshold or manual review and waiting for human commenting on Xiaohongshu.90- `取消评论`: manually decided not to comment.91- `评论成功`: human comment has been posted.92- `评论失败`: a comment attempt failed and is not currently being retried.9394For now, Xiaohongshu commenting is all manual. The skill can help surface candidates by writing `评论状态=准备评论`, but comment publishing and final status changes are handled by the user. `准备评论` on Xiaohongshu means "ready for a human to comment", not "auto-comment now".9596## Video Notes9798When the row is marked `视频` or the note state contains video streams:991001. Download the video from the note's resolved stream URL when available, or use the local `video-download` skill if the stream URL is not directly exposed.1012. Extract representative frames with ffmpeg:102 ```bash103 ffmpeg -hide_banner -loglevel error -i video.mp4 -vf "fps=1/2,scale=720:-1" frames/frame_%03d.jpg104 ```1053. If MiniMax is configured, analyze the clearest frames with `mmx vision describe`:106 ```bash107 mmx vision describe --region global --image frames/frame_001.jpg --prompt "请提取这帧里的字幕、画面主体和对理解小红书视频正文有用的信息。"108 ```1094. Combine title, original desc, visible captions, and visual summaries into `正文`. Clearly mark inferred video content as `【视频内容解析】`.110111MiniMax requires local authentication (`MINIMAX_API_KEY` or `mmx auth login`). If unavailable, fall back to manual frame review and say so. Video rows are higher risk and slower; process fewer per batch.112113## Output Rules114115- `正文`: title + newline + desc when both exist. Write this only for `准备抓取` rows unless the user explicitly requests body reprocessing.116- For videos, append a concise `【视频内容解析】` section when frame/video evidence is available.117- `点赞数` / `收藏数`: refresh for both `准备抓取` and `保持抓取` rows. Leave unavailable values unchanged/null unless the user explicitly asks to treat hidden values as `0`.118- `抓取时间`: use the user's current local datetime rounded to minutes, e.g. `YYYY-MM-DD HH:mm:00`, when the Base field supports time.119- `抓取状态`: write `保持抓取` only after a successful `准备抓取` first scrape. Keep `保持抓取` unchanged during engagement refresh. Write `抓取异常` only after an access failure is confirmed and no automatic retry should happen. Never write `停止抓取` automatically unless a separate stop-tracking rule is explicitly enabled.120- `评论状态`: blank by default; write `准备评论` only when an engagement threshold or explicit user instruction selects the row for commenting. Xiaohongshu `准备评论` means a human should comment.121- Preserve failed rows and report why they failed; do not overwrite useful existing values with blanks.122123## Safety And Access124125- Do not bypass CAPTCHAs, paywalls, private content, account restrictions, or platform access controls.126- Do not export or print cookies, tokens, localStorage, QR codes, or profile secrets.127- Default to non-logged-in static/H5 scraping. Use the user's own logged-in Chrome profile only as a fallback after consent. Keep rate low and human-paced.128- Do not repeatedly test rows already confirmed as inaccessible. Mark them `抓取异常`.129- Browser mode must reuse one browser session for a batch; do not launch and close Chrome for each URL.130- If using a visible CDP browser, use port `9223` and the Xiaohongshu profile only.131- Stop immediately after a platform warning or CAPTCHA/login-risk signal.132- Do not rotate IPs or use third-party proxies unless the user explicitly provides a compliant, owned proxy and the task is permitted.133134## References135136- Read `references/strategy.md` before changing crawl behavior, retry policy, browser profile usage, or Lark Base write semantics.