
Xiaohongshu Write
- 259 installs
- 316 repo stars
- Updated August 4, 2026
- redfox-data/redfox-community
Use xiaohongshu-write for development tasks
About
xiaohongshu-write: A skill for development. This provides functionality for development workflows.
- xiaohongshu-write
Xiaohongshu Write by the numbers
- 259 all-time installs (skills.sh)
- +16 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #1,489 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/redfox-data/redfox-community --skill xiaohongshu-writeAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 259 |
|---|---|
| repo stars | ★ 316 |
| Last updated | August 4, 2026 |
| Repository | redfox-data/redfox-community ↗ |
What it does
Use xiaohongshu-write for development tasks
Files
小红书笔记创作
1. 简介
专为小红书内容创作打造的一站式笔记生成工具 -- 基于全网每日持续收录的 2000+ 条爆款笔记数据,根据用户输入关键词精准检索热门爆款笔记,通过 AI 深度复盘爆款内容的结构、开头逻辑、干货密度与互动话术,提炼核心流量密码与创作要点,生成通顺、合规、可直接发布的完整笔记文案。
适用对象:小红书创作者、内容运营、品牌方内容团队、需要高效产出流量内容的个人或团队。
---
2. 功能特性
核心功能:
- 爆款笔记查询 -- 基于关键词搜索小红书热门笔记,最多获取 50 条数据
- 爆款规律分析 -- 从标题、内容结构、互动引导、标签策略等维度提炼流量密码
- 智能内容生成 -- 生成完整的推荐标题(3-6 个)、正文内容、推荐标签(5-10 个)
- 个人风格融合 -- 支持用户上传个人写作样本,融合其风格到生成的文案中
- 爆款公式溯源 -- 输出参考的爆款规律和核心参考笔记
特色亮点:
- 泛化词拓展策略:对大类词推荐 10 个细分方向
- 数据不足自动扩展时间范围(禁止换词)
- 严格输出格式:推荐标题 + 正文内容 + 推荐标签 + 爆款公式来源
- 输出前自检查机制:确保所有字段完整
- 搜索最新热点补充创作素材
---
3. 一键安装
鉴权
获取 API Key
请前往 红狐hub 获取API KEY
配置 API Key
方案1: 以OpenClaw为例,将REDFOX_API_KEY添加到~/.openclaw/openclaw.json中
{ "env": { "REDFOX_API_KEY": "ak_xxxx..." } }方案2: 终端配置:export REDFOX_API_KEY="ak_xxxx..."
export REDFOX_API_KEY="ak_xxxx..."依赖安装
无需额外安装,使用 Python 标准库即可运行。
---
4. 使用指南
基础使用
触发条件:当用户说 "帮我写一篇关于 XX 的小红书笔记"、"生成 XX 相关的文案内容" 等文案生成类需求时使用。
核心规则:仅在主 Agent 中执行,不派发给子 Agent。
完整操作流程
Step 1:查询爆款笔记
1.1 关键词处理:
- 无赛道关键词(如 "最近热门笔记有哪些")-> 关键词传空字符串
"",查询全站热门 - 有赛道关键词 -> 提取精确搜索关键词:
- 细分词 / 垂直赛道 -> 直接搜索
- 泛化词 / 大类(如 "穿搭"、"美食")-> 先推荐 10 个细分方向,等待用户选择后再查询
1.2 时间范围:
- 默认最近 7 天(
startDate = 今天 - 7 天) - 数据不足时自动扩展时间范围(优先扩展时间,禁止换词):近 1 天 -> 近 3 天 -> 近 7 天 -> 近 30 天
1.3 调用脚本:
python scripts/fetch_xhs_hot_articles.py \
--keyword "<用户关键词>" \
--max-items 50 \
--page-size 50 \
--start-date "<yyyy-MM-dd>"参数说明:
--keyword:搜索关键词,无关键词时传空字符串""--max-items:固定传 50,获取 50 条数据用于深度分析--page-size:固定传 50--start-date:开始日期,格式 yyyy-MM-dd
脚本输出(JSON 格式输出到控制台):
items:搜索结果列表(noteId、title、desc、createTime、互动数据、评分等)latestHotArticles:推荐热门笔记relatedSearches:拓展词推荐
详细字段说明见 references/xhs_hot_article_format.md。
执行要求:
- 执行脚本后,直接基于输出数据进行分析
- 禁止将原始爆款数据展示给用户
- 禁止仅发送文件路径或 "已保存" 等简短提示
Step 2:分析爆款规律
基于脚本返回的 50 条数据 进行深度分析:
标题规律:
- 高互动标题的共同特征(数字使用、情绪词、人群标签)
- 标题长度与结构模式
内容规律:
- 热门笔记的主题方向与切入角度
- 内容结构与段落分布特点
- 互动引导方式
标签策略:
- 高频出现的标签类型
- 热门话题标签
数据分析维度:
| 指标 | 分析要点 |
|---|---|
| 互动总量 | 高互动内容的核心特征 |
| 收藏率 | 内容实用价值高低 |
| 评论量 | 话题性与互动引导效果 |
| 点赞比 | 情绪共鸣程度 |
| 评分排名 | 有关键词时参考 totalScore 排序 |
Step 3:引导用户上传个人风格参考
在生成文案前,必须主动询问用户是否提供个人风格参考:
想让我更懂你的风格?发几段平时的笔记、日记或随笔给我就行
- 若用户提供:分析其写作风格(用词习惯、语气特点、表达方式),融合到生成的文案中
- 若用户不提供:直接基于爆款规律生成文案
Step 4:生成文案
必须严格按照爆款规律分析结果进行创作。
创作前的准备: 1. 回顾爆款规律分析结果:提取的高频关键词和热词(必须融入正文)、热门标题模式(必须严格遵循)、爆款内容的结构特征、热门内容风格 2. 搜索最新资讯 / 热点:使用 web_search 工具搜索 小红书 + <选题关键词> + 最新,必须获取至少 1-2 个最新热点或资讯作为创作素材
撰写小红书笔记内容: 1. 标题创作:严格遵循爆款标题模式,优先使用数字型标题、疑问句、感叹句,标题最多不超过 20 字 2. 正文创作:必须融入高频关键词,参考爆款开头 "钩子" 手法,融入最新热点资讯,结构参考分点说明 / 步骤教程 / 对比展示,结尾添加引导互动话术,良好分段并点缀少量 Emoji 3. Tags:结尾添加 5-10 个相关标签(Tags 仅用于笔记正文,不渲染到图片中)
Step 5:输出前自检(必须执行)
在输出前逐项检查:
- [ ] 推荐标题:是否包含 3-6 个推荐标题?
- [ ] 正文内容:是否包含完整可发布的正文?
- [ ] 推荐标签:是否包含 5-10 个相关标签?
- [ ] 爆款公式来源 - 参考的爆款规律:是否简述提炼的爆款公式?
- [ ] 爆款公式来源 - 参考的爆款笔记:是否列出 2-3 篇核心参考笔记(每篇含标题、作品链接、作者名、作者链接、完整互动数据)?
输出格式(必须严格遵守)
### 推荐标题
1. [标题1]
2. [标题2]
3. [标题3]
### 正文内容
[完整可发布的正文]
### 推荐标签
#标签1 #标签2 #标签3 #标签4 #标签5
### 爆款公式来源
**参考的爆款规律**:[简述提炼的爆款公式,如"数字型标题 + 痛点开场 + 分点干货 + 互动收尾"]
**参考的爆款笔记**(列出 2-3 篇核心参考笔记,优先选择互动数据最高的笔记):
1. [笔记标题](noteLink) - [@作者名](authorLink) - 互动数据:收藏 X / 分享 X / 评论 X / 点赞 X
2. [笔记标题](noteLink) - [@作者名](authorLink) - 互动数据:收藏 X / 分享 X / 评论 X / 点赞 X
3. [笔记标题](noteLink) - [@作者名](authorLink) - 互动数据:收藏 X / 分享 X / 评论 X / 点赞 X禁止输出:卡片设计或图片、脚本执行命令、文件路径或下载链接、仅展示数据而不生成文案。
高级使用
数据说明:数据库仅包含昨天至 30 天前的数据。笔记互动数据截止为入库时间,不是实时数据。
常用指令速查
| 场景 | 输入示例 | 处理方式 |
|---|---|---|
| 细分词直接生成 | "帮我写一篇关于减脂餐的小红书笔记" | 直接搜索生成文案 |
| 泛化词需拓展 | "帮我写一篇穿搭相关的文案" | 先推荐 10 个细分方向 |
| 融合个人风格 | 用户提供笔记样本后 | 分析风格融合到生成文案中 |
---
5. 使用场景
1. 新手创作者从零开始:输入选题关键词(如 "减脂餐"),获取基于真实爆款数据分析的可发布完整笔记,直接降低创作门槛。 2. 内容运营批量产出:输入不同细分关键词,批量生成多篇差异化文案,提高团队产出效率。 3. 品牌方深度定制内容:提供品牌产品信息和风格样本,生成符合品牌调性同时踩中爆款规律的小红书种草笔记。 4. 创作者优化已有内容:将已有文案作为风格参考输入,基于最新热点和爆款数据重新生成优化版本,提升内容竞争力。
---
6. 项目架构
目录结构
xiaohongshu-write/
├── SKILL.md # 本文件
├── scripts/
│ └── fetch_xhs_hot_articles.py # 调用红狐数据API获取热门笔记数据,输出JSON到stdout
└── references/
└── xhs_hot_article_format.md # 数据字段格式和输出规范技术栈
| 技术 | 用途 |
|---|---|
| Python 标准库 | HTTP 请求与数据解析 |
| 红狐 API | 小红书爆款笔记数据来源 |
| WebSearch | 获取最新热点资讯补充创作素材 |
| AI 智能分析 | 爆款规律提炼与文案生成 |
核心模块说明
- fetch_xhs_hot_articles.py:接收关键词、max-items、page-size、start-date 参数,调用红狐 API 获取热门笔记数据,输出 JSON 格式到 stdout,包含 items(搜索结果)、latestHotArticles(推荐热门笔记)、relatedSearches(拓展词推荐)。
资源索引
| 文件 | 用途 |
|---|---|
| scripts/fetch_xhs_hot_articles.py | 调用红狐数据API获取热门笔记数据,输出JSON到stdout |
| references/xhs_hot_article_format.md | 了解数据字段格式和输出规范时读取 |
---
7. 常见问答
安装
Q: 需要安装什么依赖? A: 无需额外安装,使用 Python 标准库即可运行。
Q: 如何配置 API Key? A: 请前往 红狐hub 获取 API KEY,通过环境变量 REDFOX_API_KEY 配置。
使用
Q: 为什么不能直接在子 Agent 中执行? A: 本 Skill 仅限于在主 Agent 中执行,不派发给子 Agent,以确保输出格式的一致性和爆款公式来源的完整性。
Q: 数据范围是多少? A: 数据库仅包含昨天至 30 天前的数据,默认时间范围为最近 7 天。
Q: 什么时候会用到 WebSearch? A: 在创作准备阶段,需要搜索 小红书 + <选题关键词> + 最新 获取至少 1-2 个最新热点作为创作素材。
Q: 输出必须包含哪些部分? A: 必须包含推荐标题(3-6 个)、正文内容、推荐标签(5-10 个)、爆款公式来源(参考的爆款规律 + 参考的爆款笔记 2-3 篇)。
故障排除
Q: 生成的文案不符合预期? A: 提供个人写作样本(平时的笔记、日记或随笔),让系统分析你的风格并融合到生成的文案中。
Q: 数据不足怎么办? A: 自动按近 1 天 -> 近 3 天 -> 近 7 天 -> 近 30 天的顺序扩展时间范围,禁止换词。
Xiaohongshu Write
---
Overview
A one-stop note generation tool purpose-built for Xiaohongshu content creation. Powered by 2,000+ viral notes collected daily across the platform, simply enter a keyword to precisely search the hottest trending notes. Through AI-powered deep analysis of viral content structures, opening hooks, information density, and engagement tactics, the tool distills core traffic-driving formulas — generating polished, platform-compliant, and ready-to-publish notes that fit Xiaohongshu's content ecosystem.
Core Value
- Data-driven: Built on massive real viral data across the platform — no guesswork
- Pattern extraction: Automatically analyzes title patterns, content structures, engagement hooks, and hashtag strategies from high-performing notes
- Publish-ready: Generated copy fits platform style, copy and post directly
- Style fusion: Supports incorporating your personal writing style to keep your content unique
Who It's For
- 🧑💻 Content Creators — Generate high-quality notes fast with lower creation barriers
- 📈 Brand Operators — Batch produce platform-aligned promotional copy
- 🔍 New Influencers — Learn viral patterns and find your creative direction
---
Features
Core Capabilities
- Viral Note Search: Search Xiaohongshu's trending notes by keyword and retrieve complete data including titles, engagement metrics, and author info
- Deep Viral Pattern Analysis: Automatically extract title patterns, content structures, emotional hooks, and hashtag strategies from high-engagement notes
- AI Copy Generation: Generate complete, platform-aligned, publish-ready note copy based on analysis results
- Personal Style Fusion: Upload your previous note content to analyze your writing habits and blend them into generated copy
Highlights
- 2,000+ Daily Data Pool: Continuously collected viral notes daily, covering the latest trends
- All-in-One Workflow: Search, analyze, and generate — all in one request, no tool switching
- Quantified Pattern Output: Not just copy — get the viral formula and reference note sources behind the results
- Real-time Trend Integration: Automatically searches latest news to incorporate into copy for timeliness and topicality
---
API Key Acquisition & Security
- This skill requires the environment variable:
REDFOX_API_KEY. REDFOX_API_KEYis provided by RedFoxHub (https://redfox.hk).- Please visit RedFoxHub to register an account and obtain your
REDFOX_API_KEY. - Set the environment variable
REDFOX_API_KEYon your device before using this skill. - Before providing your key, verify its source, available scope, validity period, and whether reset/revocation is supported.
- Never hardcode or expose your API key in plaintext within code, prompts, logs, or output files.
---
Usage Guide
Simply describe your needs in natural language — no commands to memorize.
Quick Reference
| Intent | Example Prompt | Result |
|---|---|---|
| Write a note | "Help me write a Xiaohongshu note about healthy meal prep" | Generates complete copy directly |
| Analyze viral patterns | "Help me analyze viral patterns for 'office outfits'" | Outputs viral pattern analysis |
| Find trending notes | "Find me trending 'skincare' notes recently" | Retrieves relevant popular content |
| Broad topic suggestions | "Help me write a note about fashion styling" | Recommends 10 niche sub-topics to choose from |
Output Example
After entering "Help me write a Xiaohongshu note about healthy meal prep," you'll receive:
### Recommended Titles
1. 3-Day Meal Prep Plan | The Secret to Losing Weight While Eating Well
2. One Week Meal Prep Collection! Tear-Jerkingly Delicious Weight-Loss Magic
3. 5 Things You Must Eat During a Diet — The Last One is a Game Changer
### Body Content
[Complete publish-ready copy infused with viral patterns]
### Recommended Tags
#HealthyMealPrep #WeightLossRecipes #LowCalorieFood #...
### Viral Formula Source
**Referenced Viral Formula**: Number-driven titles + pain-point hook + bullet-point value + engagement closing
**Referenced Viral Notes** (listing 2-3 core reference notes with links and engagement data)---
Use Cases
| Scenario | Role | Example Prompt | Benefit |
|---|---|---|---|
| Daily topic creation | Individual blogger | "Write a Xiaohongshu note about commute outfits" | Rapid output based on viral patterns, reduces topic pressure |
| Viral pattern research | Content operator | "Analyze viral patterns in the 'skincare' category" | Master traffic-driving tactics and optimize content strategy |
| Multi-platform content distribution | Matrix account owner | "Write a note about mom-and-baby product recommendations" | Fast batch production, boosts publishing efficiency |
| Beginner learning | New influencer | "Find trending 'food review' notes recently" | Learn viral patterns and accelerate creative growth |
---
Important Data Notes
- The database only contains data from yesterday up to 30 days ago; real-time same-day content is not included
- Default query covers the most recent 7 days of viral content
- When data is insufficient, the time range automatically expands: 1 day → 3 days → 7 days → 30 days
- When the search keyword is a broad category (e.g., "fashion," "food"), 10 niche sub-topics will be suggested first for you to choose from
小红书笔记创作 / xiaohongshu-write
---
简介
专为小红书内容创作打造的一站式笔记生成工具,基于全网每日持续收录的 2000+ 条爆款笔记数据,输入关键词即可精准检索当下热门爆款笔记,通过 AI 深度复盘爆款内容的结构、开头逻辑、干货密度与互动话术,提炼核心流量密码,严格贴合小红书内容生态,生成通顺、合规、可直接发布的完整笔记文案。
核心价值
- 数据驱动:基于全网海量真实爆款数据,拒绝凭空创作
- 规律提炼:自动分析高互动笔记的标题模式、内容结构、互动引导与标签策略
- 即产即用:生成的文案贴合平台风格,直接复制即可发布
- 风格融合:支持融入你的个人写作风格,保持内容独特性
适用对象
- 🧑💻 内容创作者 — 快速产出高质量笔记,降低创作门槛
- 📈 品牌运营 — 批量生成符合平台调性的种草文案
- 🔍 自媒体新人 — 学习爆款规律,找到适合自己的创作方向
---
功能特性
核心功能
- 爆款笔记检索:按关键词搜索小红书热门爆款笔记,获取标题、互动数据、作者信息等完整数据
- 爆款规律深度分析:自动提炼高互动笔记的标题模式、内容结构、情绪共鸣点和标签策略
- AI 文案生成:基于分析结果生成贴合平台风格、可直接发布的完整笔记文案
- 个人风格融合:支持上传你的过往笔记内容,分析写作习惯后融入生成的文案
特色亮点
- 2000+ 日更数据池:每日持续收录海量爆款笔记,数据覆盖最新趋势
- 一站式闭环:从检索、分析到生成,无需切换工具,一个请求搞定
- 量化规律输出:不仅生成文案,还告诉你背后的爆款公式和参考笔记来源
- 即时热点融入:自动搜索最新资讯融入文案,增加话题度和时效性
---
密钥获取与安全说明
- 本技能需要使用环境变量:
REDFOX_API_KEY。 REDFOX_API_KEY由 红狐 hub(https://redfox.hk)提供。- 请前往 红狐 hub 注册账号,获取
REDFOX_API_KEY。 - 配置设备环境变量
REDFOX_API_KEY后使用本技能。 - 在提供密钥前,请先确认密钥来源、可用范围、有效期及是否支持重置/撤销。
- 禁止在代码、提示词、日志或输出文件中硬编码/明文暴露密钥。
---
使用指南
直接用自然语言描述需求,无需记忆命令。
常用说法速查
| 意图 | 示例话术 | 效果 |
|---|---|---|
| 写一篇笔记 | "帮我写一篇关于减脂餐的小红书笔记" | 直接生成完整文案 |
| 分析爆款 | "帮我分析一下「职场穿搭」的爆款规律" | 输出爆款规律分析 |
| 找爆款笔记 | "帮我找最近「护肤」的爆款笔记" | 检索相关热门内容 |
| 泛化方向推荐 | "帮我写一篇穿搭相关的文案" | 推荐 10 个细分方向供你选择 |
输出示例
输入「帮我写一篇关于减脂餐的小红书笔记」后,你会得到:
### 推荐标题
1. 3天减脂餐食谱|越吃越瘦的秘密
2. 一周减脂餐合集!好吃到流泪的掉秤神器
3. 减脂期最该吃的5样东西,最后一个太绝了
### 正文内容
[完整可发布的正文,融入爆款规律]
### 推荐标签
#减脂餐 #减肥食谱 #低卡美食 #...
### 爆款公式来源
**参考的爆款规律**:数字型标题 + 痛点开场 + 分点干货 + 互动收尾
**参考的爆款笔记**(列出 2-3 篇核心参考笔记,含链接与互动数据)---
使用场景
| 场景 | 角色 | 示例问法 | 收益 |
|---|---|---|---|
| 日常选题创作 | 个人博主 | "帮我写一篇关于通勤穿搭的小红书笔记" | 基于爆款规律快速产出,降低选题压力 |
| 爆款规律研究 | 内容运营 | "分析一下「护肤」赛道的爆款规律" | 掌握流量密码,优化内容策略 |
| 多平台内容分发 | 矩阵号主 | "给我写一篇母婴好物推荐的笔记" | 快速批量产出,提升发布效率 |
| 新人上手学习 | 自媒体新手 | "帮我找最近「探店」的热门笔记" | 借鉴爆款模式,加速创作成长 |
---
重要数据说明
- 数据库仅包含昨天至 30 天前的数据,不含当日实时内容
- 默认查询最近 7 天的爆款内容
- 数据不足时自动扩展时间范围:近 1 天 → 近 3 天 → 近 7 天 → 近 30 天
- 搜索关键词为泛化大类词(如"穿搭""美食")时,会先推荐 10 个细分方向供你选择
小红书热门笔记数据格式说明
概览
本文档定义了小红书热门笔记搜索脚本 fetch_xhs_hot_articles.py 的输入输出格式规范。
输入格式
脚本参数
python scripts/fetch_xhs_hot_articles.py --keyword <关键词> [选项]| 参数 | 必填 | 说明 | 默认值 |
|---|---|---|---|
--keyword | 是 | 搜索关键词 | - |
--max-items | 否 | 最多展示数量 | 10 |
--output-format | 否 | 输出格式:text、json 或 html | html |
--output-file | 否 | 输出文件路径 | 关键词_热门数据.html |
--start-date | 否 | 开始日期,格式 yyyy-MM-dd | - |
--end-date | 否 | 结束日期,格式 yyyy-MM-dd | - |
--page-num | 否 | 页码 | 1 |
--page-size | 否 | 每页条数 | 50 |
--debug | 否 | 调试模式,打印原始API响应 | False |
API 接口
请求参数
{
"keyword": "女士护肤",
"pageNum": 1,
"pageSize": 10,
"startDate": "",
"endDate": "",
"source": "小红书笔记创作"
}| 参数 | 类型 | 说明 |
|---|---|---|
keyword | string | 搜索关键词 |
pageNum | int | 页码,从1开始 |
pageSize | int | 每页条数,最大50 |
startDate | string | 开始日期,格式 yyyy-MM-dd |
endDate | string | 结束日期,格式 yyyy-MM-dd |
source | string | 固定值:"小红书笔记创作" |
响应格式
{
"code": 2000,
"data": {
"articles": [...],
"hotTopics": [],
"keyword": "女士护肤",
"latestHotArticles": [],
"pageNum": 1,
"pageSize": 50,
"relatedSearches": [],
"tips": null,
"total": 23813
},
"msg": "成功"
}输出格式
作品数据字段(完整)
每条文章包含以下字段:
作品基本信息
| 字段名 | 类型 | 说明 |
|---|---|---|
id | string | 作品ID(唯一标识) |
title | string | 作品标题 |
desc | string | 作品描述/正文 |
createTime | string | 发布时间(格式:YYYY-MM-DD HH:MM:SS) |
cover | string | 封面图URL |
shareInfoLink | string | 作品链接 |
作者信息
| 字段名 | 类型 | 说明 |
|---|---|---|
authorId | string | 作者ID |
authorNickname | string | 作者名称 |
authorFans | int | 粉丝数 |
作者主页链接拼接规则:
https://www.xiaohongshu.com/user/profile/{authorId}互动数据
| 字段名 | 类型 | 说明 |
|---|---|---|
likedCount | int | 点赞数 |
collectedCount | int | 收藏数 |
commentsCount | int | 评论数 |
sharedCount | int | 分享数 |
interactiveCount | int | 互动总数 |
评分数据
| 字段名 | 类型 | 说明 |
|---|---|---|
popularityScore | float | 热度分数 |
recencyScore | float | 时效分数 |
relevanceScore | float | 相关性分数 |
totalScore | float | 总分 |
JSON 输出示例
{
"keyword": "女士护肤",
"total": 23813,
"pageNum": 1,
"pageSize": 50,
"items": [
{
"noteId": "69dcbb56000000001d01ae3c",
"title": "防晒换个思路,别再只看女士护肤品了!",
"desc": "#防晒#油痘#高夫#高夫防晒#肤感#油皮#物理防晒#高夫小蓝盾",
"authorId": "62bec245000000001902de0f",
"authorNickname": "可口可粒",
"authorFans": 196831,
"createTime": "2026-04-13 18:30:55",
"noteLink": "https://www.xiaohongshu.com/explore/69dcbb56000000001d01ae3c",
"authorLink": "https://www.xiaohongshu.com/user/profile/62bec245000000001902de0f",
"interactiveCount": 2560,
"likedCount": 1753,
"collectedCount": 719,
"commentsCount": 88,
"sharedCount": 44,
"totalScore": 11.5,
"relevanceScore": 10.0,
"popularityScore": 1.0,
"recencyScore": 0.5
}
]
}评分说明
数据评分由接口直接返回,无需计算:
| 字段名 | 说明 |
|---|---|
totalScore | 综合评分(主排序依据) |
popularityScore | 热度分数 |
relevanceScore | 相关性分数 |
recencyScore | 时效性分数 |
排序规则:按 totalScore 降序排列。
常见错误处理
| 错误 | 原因 | 解决方案 |
|---|---|---|
缺少 API Key 配置 | 未配置凭证 | 配置 COZE_REDFORX_XHS_API 环境变量 |
HTTP请求失败: 状态码 401 | API Key 无效 | 检查 API Key 是否正确 |
API 错误: xxx | 接口返回错误 | 检查请求参数是否正确 |
#!/usr/bin/env python3
"""
小红书热门笔记搜索脚本(支持 HTML 卡片布局输出)
基于红狐数据API,支持关键词搜索、分页、时间筛选
"""
import sys
import os
import argparse
import json
import urllib.request
import urllib.error
def parse_count(value):
"""解析数量,支持 "17w+"、"1.5w" 格式"""
if value is None:
return 0
if isinstance(value, int):
return value
value_str = str(value).replace('+', '').replace(',', '').strip()
# 处理 "w" 或 "W"(万)
if 'w' in value_str.lower():
value_str = value_str.lower().replace('w', '')
try:
return int(float(value_str) * 10000)
except:
return 0
try:
return int(float(value_str))
except:
return 0
def fuzzy_count(value):
"""对5000+的互动数做模糊处理,5000以下保留原始数值"""
if value is None:
return '--'
num = parse_count(value)
if num <= 0:
return '--'
if num < 5000:
return str(num)
if num < 10000:
return '5000+'
# 1万以上:以万为单位,向下取整
wan = num // 10000
return f'{wan}w+'
def get_api_key():
"""从环境变量 REDFOX_API_KEY 获取 API Key,未配置时报错退出"""
api_key = os.environ.get("REDFOX_API_KEY", "")
if not api_key:
print("❌ 未找到 API Key,请配置环境变量 REDFOX_API_KEY。", file=sys.stderr)
print(" 示例:export REDFOX_API_KEY=your_api_key_here", file=sys.stderr)
sys.exit(1)
return api_key
def fetch_xhs_hot_notes(keyword: str, debug: bool = False, max_retries: int = 3,
start_date: str = None, end_date: str = None,
page_num: int = 1, page_size: int = 50):
"""调用接口获取小红书热门笔记数据"""
# API Key(从环境变量 REDFOX_API_KEY 读取,支持 shell 配置文件回退)
api_key = get_api_key()
# 构建请求
url = "https://redfox.hk/story/api/xhs/search/search"
headers = {
"Content-Type": "application/json",
"X-API-KEY": api_key
}
payload = {
"keyword": keyword,
"pageNum": page_num,
"pageSize": page_size,
"startDate": start_date or "",
"endDate": end_date or "",
"source": "小红书笔记创作-GitHub"
}
last_error = None
for attempt in range(max_retries):
try:
if debug:
print(f"\n=== DEBUG: 第 {attempt + 1} 次尝试 ===", file=sys.stderr)
print(f"请求参数: {json.dumps(payload, ensure_ascii=False)}", file=sys.stderr)
body = json.dumps(payload, ensure_ascii=False).encode("utf-8")
req = urllib.request.Request(url, data=body, headers=headers, method="POST")
with urllib.request.urlopen(req, timeout=30) as resp:
status_code = resp.status
resp_bytes = resp.read()
resp_text = resp_bytes.decode("utf-8")
if debug:
print(f"状态码: {status_code}", file=sys.stderr)
print(f"响应长度: {len(resp_text)} 字节", file=sys.stderr)
if status_code >= 400:
raise Exception(f"HTTP请求失败: 状态码 {status_code}, {resp_text[:200]}")
data = json.loads(resp_text)
# 检查返回码
if data.get("code") != 2000:
raise Exception(f"API 错误: {data.get('msg', '未知错误')}")
result_data = data.get("data", {})
if debug:
print("=== DEBUG: API 返回的 data 字段键 ===", file=sys.stderr)
print(json.dumps(list(result_data.keys()), ensure_ascii=False, indent=2), file=sys.stderr)
print(f"总条数: {result_data.get('total', 0)}", file=sys.stderr)
articles = result_data.get("articles", [])
return {
"keyword": result_data.get("keyword", keyword),
"articles": articles,
"total": len(articles),
"pageNum": result_data.get("pageNum", page_num),
"pageSize": result_data.get("pageSize", page_size),
"hotTopics": result_data.get("hotTopics", []),
"relatedSearches": result_data.get("relatedSearches", []),
"latestHotArticles": result_data.get("latestHotArticles", [])
}
except urllib.error.URLError as e:
last_error = f"请求失败: {str(e)}"
if debug:
print(f" 错误: {str(e)[:100]}", file=sys.stderr)
import time
if attempt < max_retries - 1:
time.sleep(2 ** attempt)
continue
except Exception as e:
last_error = str(e)
if debug:
print(f" 错误: {str(e)[:100]}", file=sys.stderr)
import time
if attempt < max_retries - 1:
time.sleep(2 ** attempt)
continue
raise Exception(f"{last_error}(已尝试 {max_retries} 次)")
def get_cover_urls(data, max_items=10):
"""提取所有封面图URL"""
urls = []
articles = data.get("articles", [])[:max_items]
for item in articles:
cover_url = item.get('cover', '')
note_id = item.get('id', '')
title = (item.get('title', '') or item.get('desc', ''))[:30]
if cover_url and note_id:
urls.append({
'title': title,
'note_id': note_id,
'cover_url': cover_url,
'link': item.get('shareInfoLink', f"https://www.xiaohongshu.com/explore/{note_id}")
})
return urls
def get_top_articles(data, max_items=10):
"""
获取文章列表(按接口原始返回顺序,截取前 max_items 条)
"""
articles = data.get("articles", [])[:max_items]
return articles
def format_as_html(data: dict, max_items: int = 10, start_date: str = None):
"""
格式化输出热门笔记数据(HTML 卡片布局)
"""
from datetime import datetime
keyword = data.get("keyword", "")
total = data.get("total", 0)
is_full_site = not keyword or keyword.strip() == ""
def process_title(item):
"""处理标题"""
title = item.get('title', '')
if not title or title.strip() == '':
desc = item.get('desc', '')
if desc:
title = desc.replace('\n', ' ').replace('\r', ' ').strip()[:30]
if len(desc) > 30:
title = title + '...'
if not title or title.strip() == '':
title = '无标题'
title = title.replace('<', '<').replace('>', '>').replace('"', '"')
return title
def format_time(item):
"""格式化发布时间"""
create_time = item.get('createTime', '')
if create_time:
try:
month = int(create_time[5:7])
day = int(create_time[8:10])
return f"{month}月{day}日"
except:
pass
return '--'
def generate_card(item, idx):
"""生成单个卡片 HTML"""
note_id = item.get('id', '')
author_id = item.get('authorId', '')
author_name = item.get('authorNickname', '未知')
fans = item.get('authorFans', 0)
title = process_title(item)
pub_time = format_time(item)
interactive_count = fuzzy_count(item.get('interactiveCount', 0))
like_count = fuzzy_count(item.get('likedCount', 0))
collect_count = fuzzy_count(item.get('collectedCount', 0))
# 作品链接
note_link = item.get('shareInfoLink') or f"https://www.xiaohongshu.com/explore/{note_id}"
# 作者主页链接
author_link = f"https://www.xiaohongshu.com/user/profile/{author_id}" if author_id else "#"
relevance_score = item.get('relevanceScore', 0)
popularity_score = item.get('popularityScore', 0)
recency_score = item.get('recencyScore', 0)
total_score = item.get('totalScore', 0)
# 评分标签(全站热门时不展示)
scores_html = ''
if not is_full_site:
scores_html = f'''
<div class="card-scores">
<span class="score-tag relevance">相关性 {relevance_score}</span>
<span class="score-tag popularity">热度 {popularity_score}</span>
<span class="score-tag recency">时效 {recency_score}</span>
</div>
'''
card_html = f'''
<div class="card">
<div class="card-title-row">
<span class="card-index">{idx + 1}.</span>
<a href="{note_link}" class="card-title" target="_blank">{title}</a>
</div>
<div class="card-meta">
<a href="{author_link}" class="author-link" target="_blank">{author_name}({fuzzy_count(fans)}粉)</a>
<span class="meta-divider">·</span>
<span class="pub-time">发布日期:{pub_time}</span>
</div>
{scores_html}
<div class="card-stats">
<span class="interaction-count">🔥 {interactive_count}互动</span>
<span class="detail-stats">👍{like_count} ⭐{collect_count}</span>
<a href="{note_link}" class="view-note-btn" target="_blank">查看作品 ↗</a>
</div>
</div>
'''
return card_html
# 获取数据(接口原始顺序)
top_items = get_top_articles(data, max_items)
latest_hot_items = data.get("latestHotArticles", [])[:10]
# 主列表为空时的提示
no_articles_hint = ''
if not top_items:
no_articles_hint = '''
<div class="no-data-hint">
<p>未查询到相关热门笔记,建议更换关键词重试。</p>
</div>
'''
cards_html = ''.join([generate_card(item, idx) for idx, item in enumerate(top_items)]) if top_items else ''
# 推荐热门笔记区域(latestHotArticles,仅在有关键词文章时额外展示)
latest_hot_html = ''
if latest_hot_items:
latest_cards = ''.join([generate_card(item, idx) for idx, item in enumerate(latest_hot_items)])
latest_hot_html = f'''
<div class="section-header">
<h2>近期热门笔记推荐</h2>
</div>
<div class="card-grid">
{latest_cards}
</div>
'''
time_range = f"近30天" if not start_date else f"从{start_date}起"
html_content = f'''<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小红书热门笔记数据分析报告</title>
<style>
* {{
margin: 0;
padding: 0;
box-sizing: border-box;
}}
body {{
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
background-color: #f5f5f5;
padding: 16px;
color: #333;
}}
.container {{
max-width: 1200px;
margin: 0 auto;
}}
.report-header {{
background: linear-gradient(135deg, #ff2442 0%, #ff6b81 100%);
color: white;
padding: 20px 24px;
border-radius: 12px;
margin-bottom: 20px;
}}
.report-header h1 {{
font-size: 20px;
margin-bottom: 8px;
}}
.report-header .keyword {{
font-size: 14px;
opacity: 0.9;
}}
.report-header .total {{
font-size: 12px;
opacity: 0.8;
margin-top: 4px;
}}
.card-grid {{
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 16px;
}}
.card {{
background: white;
border-radius: 12px;
padding: 16px;
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
transition: transform 0.2s, box-shadow 0.2s;
display: flex;
flex-direction: column;
gap: 10px;
}}
.card:hover {{
transform: translateY(-2px);
box-shadow: 0 4px 16px rgba(0,0,0,0.12);
}}
.card-title-row {{
border-bottom: 1px solid #f0f0f0;
padding-bottom: 10px;
display: flex;
align-items: flex-start;
gap: 6px;
}}
.card-index {{
font-size: 15px;
font-weight: 700;
color: #ff2442;
min-width: 20px;
}}
.card-title {{
font-size: 15px;
font-weight: 700;
color: #1a1a1a;
text-decoration: none;
line-height: 1.5;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
transition: color 0.2s;
}}
.card-title:hover {{
color: #ff2442;
}}
.card-meta {{
font-size: 13px;
color: #999;
padding: 8px 0;
}}
.author-link {{
color: #666;
text-decoration: none;
transition: color 0.2s;
}}
.author-link:hover {{
color: #ff2442;
}}
.meta-divider {{
margin: 0 6px;
}}
.pub-time {{
color: #999;
}}
.card-scores {{
display: flex;
gap: 8px;
flex-wrap: wrap;
}}
.score-tag {{
font-size: 12px;
padding: 2px 8px;
border-radius: 10px;
font-weight: 500;
}}
.score-tag.relevance {{
background: #e8f5e9;
color: #2e7d32;
}}
.score-tag.popularity {{
background: #fff3e0;
color: #e65100;
}}
.score-tag.recency {{
background: #e3f2fd;
color: #1565c0;
}}
.card-stats {{
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 16px;
margin: 0 -16px;
background: linear-gradient(135deg, #fff5f5, #fff);
}}
.interaction-count {{
font-size: 14px;
font-weight: 600;
color: #ff2442;
}}
.detail-stats {{
font-size: 12px;
color: #666;
}}
.view-note-btn {{
color: #ff2442;
text-decoration: none;
font-size: 14px;
font-weight: 500;
transition: opacity 0.2s;
}}
.view-note-btn:hover {{
opacity: 0.7;
text-decoration: underline;
}}
.data-note {{
text-align: center;
color: #999;
font-size: 12px;
margin-top: 20px;
padding: 12px;
background: white;
border-radius: 8px;
}}
.section-header {{
margin-top: 24px;
margin-bottom: 16px;
padding: 12px 16px;
background: linear-gradient(135deg, #ff6b81 0%, #ff2442 100%);
border-radius: 8px;
}}
.section-header h2 {{
color: white;
font-size: 16px;
font-weight: 600;
}}
</style>
</head>
<body>
<div class="container">
<div class="report-header">
<h1>小红书热门笔记数据分析报告</h1>
<div class="keyword">关键词:{keyword} | 时间范围:{time_range}</div>
<div class="total">共找到 {total} 条相关笔记</div>
</div>
{no_articles_hint}
<div class="card-grid">
{cards_html}
</div>
{latest_hot_html}
<div class="data-note">
数据来源:小红书热门笔记搜索,每日更新最新热门内容<br>
备注:互动数据为入库快照,实时数据可能持续增长
</div>
</div>
</body>
</html>'''
return html_content
def format_as_json(data: dict, max_items: int = 10):
"""
格式化输出 JSON 格式(供智能体分析生成推荐理由)
"""
top_items = get_top_articles(data, max_items)
keyword = data.get('keyword', '')
is_full_site = not keyword or keyword.strip() == ""
latest_hot_items = data.get("latestHotArticles", [])[:10]
result = []
for item in top_items:
note_id = item.get('id', '')
item_data = {
'noteId': note_id,
'title': item.get('title', '') or item.get('desc', '')[:50],
'desc': item.get('desc', ''),
'authorId': item.get('authorId', ''),
'authorNickname': item.get('authorNickname', ''),
'authorFans': fuzzy_count(item.get('authorFans', 0)),
'createTime': item.get('createTime', ''),
'noteLink': item.get('shareInfoLink') or f"https://www.xiaohongshu.com/explore/{note_id}",
'authorLink': f"https://www.xiaohongshu.com/user/profile/{item.get('authorId', '')}" if item.get('authorId') else '',
'interactiveCount': fuzzy_count(item.get('interactiveCount', 0)),
'likedCount': fuzzy_count(item.get('likedCount', 0)),
'collectedCount': fuzzy_count(item.get('collectedCount', 0)),
'commentsCount': fuzzy_count(item.get('commentsCount', 0)),
'sharedCount': fuzzy_count(item.get('sharedCount', 0)),
}
# 有关键词时才输出评分字段
if not is_full_site:
item_data['totalScore'] = item.get('totalScore', 0)
item_data['relevanceScore'] = item.get('relevanceScore', 0)
item_data['popularityScore'] = item.get('popularityScore', 0)
item_data['recencyScore'] = item.get('recencyScore', 0)
result.append(item_data)
# 格式化推荐热门笔记(latestHotArticles,无评分字段)
latest_hot_result = []
for item in latest_hot_items:
note_id = item.get('id', '')
latest_hot_result.append({
'noteId': note_id,
'title': item.get('title', '') or item.get('desc', '')[:50],
'authorNickname': item.get('authorNickname', ''),
'authorFans': fuzzy_count(item.get('authorFans', 0)),
'createTime': item.get('createTime', ''),
'noteLink': item.get('shareInfoLink') or f"https://www.xiaohongshu.com/explore/{note_id}",
'authorLink': f"https://www.xiaohongshu.com/user/profile/{item.get('authorId', '')}" if item.get('authorId') else '',
'interactiveCount': fuzzy_count(item.get('interactiveCount', 0)),
'likedCount': fuzzy_count(item.get('likedCount', 0)),
'collectedCount': fuzzy_count(item.get('collectedCount', 0)),
})
return {
'keyword': data.get('keyword', ''),
'total': data.get('total', 0),
'pageNum': data.get('pageNum', 1),
'pageSize': data.get('pageSize', 50),
'isFullSite': is_full_site,
'items': result,
'latestHotArticles': latest_hot_result,
'relatedSearches': data.get('relatedSearches', [])
}
def main():
"""主函数"""
parser = argparse.ArgumentParser(description='小红书热门笔记搜索工具')
parser.add_argument('--keyword', required=True, help='搜索关键词')
parser.add_argument('--max-items', type=int, default=10,
help='最多展示数量(默认10条)')
parser.add_argument('--output-format', choices=['json', 'html'],
default='json', help='输出格式(默认json输出到stdout,html输出到文件)')
parser.add_argument('--output-file', type=str, default=None,
help='输出文件路径(默认:关键词_热门数据.html)')
parser.add_argument('--start-date', type=str, default=None,
help='开始日期,格式 yyyy-MM-dd')
parser.add_argument('--end-date', type=str, default=None,
help='结束日期,格式 yyyy-MM-dd')
parser.add_argument('--page-num', type=int, default=1,
help='页码(默认1)')
parser.add_argument('--page-size', type=int, default=50,
help='每页条数(默认50)')
parser.add_argument('--debug', action='store_true', help='启用调试模式')
parser.add_argument('--max-retries', type=int, default=3,
help='最大重试次数(默认3次)')
args = parser.parse_args()
try:
data = fetch_xhs_hot_notes(
keyword=args.keyword,
debug=args.debug,
max_retries=args.max_retries,
start_date=args.start_date,
end_date=args.end_date,
page_num=args.page_num,
page_size=args.page_size
)
# 生成 JSON 数据(始终输出到 stdout,供智能体读取)
json_data = format_as_json(data, max_items=args.max_items)
# 输出 JSON 到 stdout(智能体从此读取结构化数据)
print(json.dumps(json_data, ensure_ascii=False, indent=2))
# 同时生成 HTML 文件
html_content = format_as_html(data, max_items=args.max_items, start_date=args.start_date)
keyword_safe = args.keyword.replace('"', '').replace(' ', '_') or '全站热门'
html_file = args.output_file or f"{keyword_safe}_热门数据.html"
with open(html_file, 'w', encoding='utf-8') as f:
f.write(html_content)
# 统计信息输出到 stderr
print(f"✓ HTML 结果已保存到: {html_file}", file=sys.stderr)
print(f"✓ 关键词: {args.keyword}", file=sys.stderr)
print(f"✓ 总条数: {json_data['total']} 条", file=sys.stderr)
print(f"✓ 筛选结果: {len(json_data['items'])} 条", file=sys.stderr)
print(f"✓ 推荐热门笔记: {len(json_data.get('latestHotArticles', []))} 条", file=sys.stderr)
# 输出封面图URL供后续分析
cover_urls = get_cover_urls(data, max_items=5)
if cover_urls:
print(f"\n=== 封面图URL(用于风格分析)===", file=sys.stderr)
for i, item in enumerate(cover_urls, 1):
print(f"{i}. {item['title']}: {item['cover_url']}", file=sys.stderr)
except Exception as e:
print(f"❌ 错误: {str(e)}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()