把小红书关键词搜索结果中的用户按粉丝数分桶存档到本地 SQLite + 默认收藏夹。提供按桶导出 HTML/CSV/Markdown 的能力,方便按量级层分层浏览命中用户。
⚠ 关于"收藏夹分桶"原设想:实测发现小红书网页版没有"新建收藏夹/移动笔记到收藏夹"按钮;查阅所有开源逆向工具(xiaohongshu-cli、ReaJason/xhs、Xiaohongshu-API、RSSHub 等)均未逆向出该组接口——该能力是 App 独占。当前版本放弃收藏夹同步,笔记统一加到默认「所有收藏」,分桶信息保留在本地 SQLite 并可通过
export命令取出。
┌─ xhs CLI (xiaohongshu-cli) ─┐ ┌─ Playwright UI 自动化 ─┐
关键词 → 搜索 → 笔记 → 评论者 → 用户画像 → 按粉丝数分桶 → 收藏到对应文件夹
└────── 阶段 1/2 ─────────┘ └──────── 阶段 3 ────────┘
│ │
└── 全量写入 SQLite (users/hits/archives) ─┘
收藏夹桶(见 config/buckets.yaml):素人 0-100 / 萌新 100-1k / 腰部 1k-10k / 中部 10k-100k / 头部 100k+
小红书对海外 IP 做了搜索接口的风控(error_code=300012),不连 VPN 无法使用。建议用家宽/住宅 IP,避免数据中心 IP 被标记。
- Python ≥ 3.10
- Chromium(Playwright 自动下载)
# 1. Python 依赖
pip install -e .
python -m playwright install chromium
# 2. 配置
cp config/config.example.yaml config/config.yaml# 1. 登录(一条命令完成两套登录:xhs CLI 采集端 + Playwright 归档端)
rednote-agent login
# 2. 采集 + 归档
rednote-agent archive --keyword "巴厘岛" --note-limit 30
# 可选参数:
# --no-commenters 只抓作者,不抓评论者
# --resume 跳过已成功归档的用户
# --headed / --headless
# 3. 统计
rednote-agent stats
# 4. 按桶导出(HTML 打开就是一个分层浏览器)
rednote-agent export --bucket "腰部 1k-10k" --format html --out out.html
open out.html
# 其他导出格式
rednote-agent export --keyword "巴厘岛" --format md
rednote-agent export --bucket "素人 0-100" --format csv --out users.csv归档完成后,命中用户的代表笔记都在小红书「我 → 收藏 → 所有」里;按粉丝量级的分层浏览走本地 export 命令产生的 HTML。
- xhs CLI 用自己的 Cookie 存在
~/.xiaohongshu-cli/cookies.json(采集用) - Playwright 用
data/state/storage_state.json(归档点击"收藏→选文件夹"用) - 目前两套独立,需要各扫一次码。
rednote-agent login会按顺序引导你走完这两步。 - 跳过某一步:
rednote-agent login --skip-cli或--skip-playwright
rednote-agent/
├── config/
│ ├── buckets.yaml # 粉丝数分桶配置
│ └── config.example.yaml
├── src/rednote_agent/
│ ├── cli.py # typer 入口
│ ├── pipeline.py # 端到端编排(采集+归档)
│ ├── playwright_login.py # 归档端扫码登录
│ ├── crawler/
│ │ └── xhs_cli.py # subprocess 封装 xhs CLI
│ ├── archiver/
│ │ ├── bucket.py # 粉丝数 → 桶
│ │ └── favoriter.py # Playwright 收藏到指定文件夹
│ └── db/
│ ├── schema.sql
│ └── store.py
├── data/
│ ├── rednote.db # SQLite
│ ├── state/storage_state.json # Playwright 登录态
│ └── snapshots/<user_id>.json # xhs CLI 返回的原始画像
└── tests/
SQLite 三张表(详见 schema.sql):
users— 用户画像(粉丝、关注、获赞收藏、IP、标签、分桶)hits— 用户在哪个关键词下、以什么身份(作者/评论者)被命中archives— 归档动作结果(ok/skipped/failed)
-- 某关键词下的素人用户
SELECT u.nickname, u.fans, u.ip_location
FROM users u JOIN hits h ON h.user_id = u.user_id
WHERE h.keyword = '巴厘岛' AND u.bucket LIKE '素人%';# 查看 xhs CLI 实际输出结构(排查字段错位时有用)
xhs search "巴厘岛" --json | head -80
xhs user <user_id> --json
# 已存但未归档的用户
sqlite3 data/rednote.db "SELECT * FROM archives WHERE status='failed';"- 必须 VPN — 海外 IP 直连会触发 300012 风控
- ⚠ 目前笔记只能加到默认"所有收藏" —
xhs favoriteAPI 不接受 folder 参数,网页 UI 的"收藏到指定文件夹"流程脆弱且没打通。分桶信息仅存本地 SQLite。把笔记从默认收藏移到按粉丝数命名的子收藏夹是 TODO(可能需要手动,或实现 /user/profile/me 收藏页的 Playwright 自动化) - xhs CLI
user/user-posts子命令 API 失败 — 上游 bug(code -1);已用 Playwright 直接抓/user/profile/<id>的__INITIAL_STATE__绕过 - xhs CLI 字段映射 — 搜索结果结构是
data.items[].note_card.user.user_id(不是顶层 user_id),评论结构是data.comments[].user_info.user_id—— 字段在pipeline.py的_extract_note_fields/_extract_commenter_id里,上游改字段时改这两处 - 两套登录 — xhs CLI (
~/.xiaohongshu-cli/cookies.json) 和 Playwright (data/state/storage_state.json) 各一套;rednote-agent login扫一次码后cookie_bridge会自动把 Playwright 的 cookie 同步给 xhs CLI
仅供学习与个人研究。参考并依赖 xiaohongshu-cli 做数据采集;不得大规模爬取、商业化或分发。遵守小红书服务条款。