
Xiaohongshu Title
- 245 installs
- 316 repo stars
- Updated August 4, 2026
- redfox-data/redfox-community
Use xiaohongshu-title for development tasks
About
xiaohongshu-title: A skill for development. This provides functionality for development workflows.
- xiaohongshu-title
Xiaohongshu Title by the numbers
- 245 all-time installs (skills.sh)
- +16 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #1,581 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-titleAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 245 |
|---|---|
| repo stars | ★ 316 |
| Last updated | August 4, 2026 |
| Repository | redfox-data/redfox-community ↗ |
What it does
Use xiaohongshu-title for development tasks
Files
小红书标题生成
1. 简介
基于用户输入的任何信息生成小红书爆款标题的专业工具 -- 通过查询小红书平台真实爆款数据,分析爆款标题的共同特征,结合用户输入的核心主题,自动生成 10 个高匹配度的小红书爆款标题,每个标题附带匹配指数、参考爆款和详细推荐理由。
适用对象:小红书创作者、内容运营、文案策划、需要标题灵感的写作者。
---
2. 功能特性
核心功能:
- 智能理解用户输入 -- 无论输入什么内容,都能提取核心关键词
- 爆款数据查询 -- 基于用户关键词查询小红书热门笔记标题
- 爆款规律分析 -- 从标题结构、关键词、情绪表达等维度分析爆款特征
- 批量标题生成 -- 一次性生成 10 个符合爆款规律的新标题
- 匹配指数评分 -- 每个标题附带 8-10 分的匹配指数
特色亮点:
- 泛化词拓展策略:对大类词(如 "美妆"、"穿搭")自动推荐 10 个细分方向供用户选择
- 精准关键词理解:严格区分产品形态(如 "防晒霜" 只查霜状产品,不扩展到喷雾、帽子等)
- 数据不足自动扩展时间范围(禁止换词)
- 统一输出格式:标题X + 匹配指数 + 参考爆款 + 推荐理由 + 分隔线
---
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..."依赖安装
依赖 requests 库(标准 Python 库),如未安装可执行 pip install requests。
---
4. 使用指南
基础使用
核心原则:无论用户输入什么,最终目标都是生成小红书爆款标题。
示例理解:
- "我想写关于护肤的内容" -> 基于 "护肤" 生成爆款标题
- "上班族早餐" -> 基于 "上班族早餐" 生成爆款标题
- "防晒霜" -> 只查询防晒霜(膏状/乳状),不包含防晒喷雾、防晒衣等
完整操作流程(严格按顺序执行)
第一步:理解用户输入并提取关键词
1. 分析用户输入,从输入中提取核心主题和关键词。 2. 判断关键词类型:
- 细分词 / 垂直赛道(含具体场景/属性修饰)-> 直接查询数据
- 具体产品词(如 "防晒霜"、"睫毛膏")-> 直接查询该产品数据,不扩展到其他产品
- 泛化词 / 大分类(纯大类词,如 "穿搭"、"美食")-> 执行泛化词拓展策略
精准关键词理解规则:
- 用户输入的是什么产品就只查询什么产品,不随意扩展到相关但不同的产品
- 霜 != 喷雾 != 衣:用户输入 "防晒霜",要的是有防晒作用的霜,不包含防晒喷雾、防晒衣
- 膏 != 液 != 粉:用户输入 "睫毛膏",要的是膏状的睫毛产品,不包含假睫毛、睫毛增长液
- 液 != 霜 != 喷雾:用户输入 "粉底液",要的是液体状的粉底,不包含气垫、BB 霜
第二步:泛化词拓展策略(仅当关键词为泛化词时执行)
1. 查询近 7 天网页资讯中和泛化词相关的小红书热点并生成细分词(禁止调用脚本搜索数据) 2. 输出 10 个细分方向词(趋势词、人群词、场景词、意图词各 2-3 个) 3. 必须等待用户回复「拓展」或「不拓展」后再执行,不得在同一次对话中继续执行任何脚本调用
拓展词输出示例:
我识别到「美妆」是较大的分类,已查询近期热门趋势,推荐以下细分方向:
柔焦底妆、养肤妆、亚裔妆、油皮定妆、通勤妆、夏日妆容、新手妆容、平价彩妆、妆容教程、彩妆测评
回复「拓展」将同时搜索这10个词,回复「不拓展」将继续搜索「美妆」第三步:时间范围与数据查询
- 数据库只包含昨天至 30 天前的数据
- "最近" 默认定义为最近 7 天(startDate = 今天 - 6 天)
- 日期格式必须为 yyyy-MM-dd
数据不足时的自动调整(优先扩展时间,禁止换词):
- 处理原则:数据不足 5 条时,只能扩展时间范围,不能更换或拓展关键词
- 调整顺序:近 1 天 -> 近 3 天 -> 近 7 天 -> 近 30 天
- 每次扩展后提示用户:"该关键词近 X 天数据不足 5 条,已自动扩展时间范围至近 Y 天"
- 最终兜底:即使扩展到近 30 天仍不足 5 条,如实展示现有数据,但必须提示用户数据不足
执行命令:
# 有赛道关键词
python scripts/fetch_xhs_trends.py --keyword <关键词> --start-date <日期>
# 无赛道关键词(查询全站热门)
python scripts/fetch_xhs_trends.py --keyword "" --start-date <日期>第四步:爆款数据(仅内部执行,页面不展示)
读取生成的 Markdown 文件:关键词_爆款数据.md
第五步:分析爆款标题并生成新标题(严格按此顺序)
第一步 - 分析爆款标题(仅内部执行):
- 从获取的爆款数据中提取所有标题
- 分析共同特征:标题结构、关键词使用、情绪表达、目标人群、痛点点出、利益承诺
第二步 - 生成新爆款标题:
- 基于分析结果创作 10 个新的爆款标题
- 标题必须控制在 20 个字以内
- 匹配指数范围:8-10 之间(不得低于 8),保留一位小数
- 同一个匹配指数最多重复出现 2 次
- 参考的爆款标题必须支持点击查看作品链接:
[标题文字](https://www.xiaohongshu.com/explore/{photoId})
第六步:验证输出格式是否正确
必须在输出前完成格式验证,确保所有格式要求 100% 符合。
最终输出顺序:先输出 "数据说明",再输出全部 10 个推荐标题。
输出格式(必须严格遵守)
基于本次分析,为您生成以下10个爆款标题:
**数据说明**:!!!受小红书风控规则限制,部分作品链接可能无法正常跳转,您可复制对应作品标题前往小红书搜索查看,感谢理解🙇♀️🙇♀️
**标题1:[标题内容]**
📈匹配指数:[数值]
🔥参考的爆款:[参考标题1](链接)(互动数:XXX)、[参考标题2](链接)(互动数:YYY)
👍推荐理由:[详细推荐理由,包含:标题结构、关键词、目标人群、痛点、价值承诺、受欢迎原因]
---
**标题2:[标题内容]**
📈匹配指数:[数值]
🔥参考的爆款:[参考标题C](链接)(互动数:XXX)
👍推荐理由:[详细推荐理由]
---
...(共10个标题)
---高级使用
用词规范(必须 100% 遵守):
- 在所有输出内容中,绝对禁止使用 "爬取"、"抓取" 这两个词
- 必须用 "获取" 来替代
匹配指数规则:
- 数值范围:8-10 之间
- 保留一位小数
- 同一个匹配指数最多重复出现 2 次
使用建议: 1. 先测试匹配指数较高的 2-3 个标题,观察实际数据表现 2. 根据测试结果,调整标题的关键词和表达方式 3. 结合自己的内容特点,对推荐标题进行个性化修改
常用指令速查
| 场景 | 示例输入 | 处理方式 |
|---|---|---|
| 细分词直接查询 | "上班族早餐" | 直接搜索生成标题 |
| 泛化词需拓展 | "穿搭"、"美妆" | 先推荐 10 个细分方向 |
| 具体产品词 | "防晒霜" | 严格限定该产品形态查询 |
| 无关键词 | "最近有什么热门" | 查询全站热门生成标题 |
---
5. 使用场景
1. 新手创作者找标题灵感:输入自己的内容主题(如 "减脂餐"),获取 10 个符合爆款规律的高匹配度标题,直接选用或参考修改。 2. 内容运营批量产出标题:针对不同的细分关键词依次查询,快速批量生成多套标题方案,提升内容产出效率。 3. 文案策划验证标题质量:将自己草拟的标题作为输入,让系统基于同赛道爆款数据生成对比标题,验证标题是否踩中爆款规律。 4. 泛类目方向的选题探索:输入泛化词(如 "穿搭"),通过拓展策略获取 10 个细分方向,再对每个方向生成标题,发掘潜力爆款方向。
---
6. 项目架构
目录结构
xiaohongshu-title/
├── SKILL.md # 本文件
└── scripts/
└── fetch_xhs_trends.py # 数据查询脚本,调用红狐API获取爆款标题数据技术栈
| 技术 | 用途 |
|---|---|
| Python + requests | HTTP 请求与数据获取 |
| 红狐 API | 小红书爆款标题数据来源 |
| AI 智能分析 | 爆款规律提炼与新标题生成 |
核心模块说明
- fetch_xhs_trends.py:接收关键词和时间范围参数,调用红狐 API 查询小红书热门笔记标题数据,输出 Markdown 格式的爆款数据文件(
关键词_爆款数据.md),供后续分析使用。
资源索引
| 文件 | 用途 |
|---|---|
| scripts/fetch_xhs_trends.py | 数据查询脚本 |
---
7. 常见问答
安装
Q: 需要安装什么依赖? A: 需要 requests 库,如未安装可执行 pip install requests。
Q: 如何配置 API Key? A: 请前往 红狐hub 获取 API KEY,通过环境变量 REDFOX_API_KEY 配置。
使用
Q: 数据覆盖多长时间? A: 数据库只包含昨天至 30 天前的数据。
Q: 泛化词和细分词如何区分? A: 泛化词是抽象层级高、覆盖范围广的概括性词汇(如 "穿搭"、"美妆")。细分词是含具体场景/属性修饰的词(如 "职场穿搭"、"减脂餐")。
Q: 数据不足怎么办? A: 自动按近 1 天 -> 近 3 天 -> 近 7 天 -> 近 30 天的顺序扩展时间范围,禁止换词。
Q: 标题为什么限制 20 字? A: 基于小红书爆款数据分析,20 字以内的标题点击率最高。
故障排除
Q: 为什么不能搜索 "今天" 的数据? A: 用户说 "今天/今日" 时,回答 "非常抱歉,今天的数据暂未更新,已为您展示最近可用的数据"。
Q: 为什么不能查询超过 30 天的数据? A: 用户要求的时间超出 30 天时,回答 "非常抱歉,当前仅支持最近 30 天的数据,已为您展示最接近的数据"。
XHS Title Suite / xiaohongshu-title
---
Overview
Powered by daily-collected viral note data across the platform, this skill intelligently analyzes viral title patterns and generates 10 high-traffic attention-grabbing titles for you in one shot.
Core Value
- Large-scale sample alignment: Viral notes are collected continuously every day, giving your title creation a solid data foundation rather than fabricated examples or engagement numbers.
- Analyze before write: The skill completes a "viral title analysis" phase before outputting new titles, making the underlying patterns clear and easy to act on.
- Batch delivery: 10 titles in a unified format at once — each with a match score, reference link, and detailed rationale — making comparison and A/B testing straightforward.
Who It's For
- 📝 Xiaohongshu creators — Stop agonizing over titles; let data-driven patterns boost your click-through rate and reach.
- 🛍️ Brand / e-commerce operators — Quickly produce multiple title candidates based on product keywords and selling points.
- 🏢 MCN / content strategists — Batch-propose titles for the same track and build a reusable library of title frameworks.
---
Features
Core Capabilities
- Keyword-driven: Supports product keywords and topic keywords. When the input is a broad category, the skill recommends sub-directions for your confirmation before proceeding.
- Smart time strategy: If sample data is insufficient, the query window is automatically extended (from recent to further back) without replacing your core keyword.
- Two-phase output: First analyzes the structure, audience, and patterns of viral titles; then creates 10 new titles (not copies of the originals).
- Standard delivery format: Every title comes with a match score, a referenceable viral-note link, and detailed rationale — consistent layout for easy selection.
---
API Key Acquisition & Security
- This skill requires the environment variable:
REDFOX_API_KEY. REDFOX_API_KEYis provided by RedFoxHub (https://redfox.hk).- Visit RedFoxHub to register and obtain your
REDFOX_API_KEY. - Configure the
REDFOX_API_KEYenvironment variable on your device before using this skill. - Before providing your key, confirm its source, scope, expiry, and whether it supports reset/revocation.
- Never hard-code or expose the key in plain text within code, prompts, logs, or output files.
---
Usage Guide
Just describe your product, topic, or creative need in plain language — no commands to memorize.
Quick-Reference Phrases
| Intent | Example | What You Get |
|---|---|---|
| Title for a single item | "Write some viral Xiaohongshu titles for a sunscreen — key selling point: lightweight, non-greasy" | Aligns with viral samples by keyword, analyzes then outputs 10 candidates |
| Regular track updates | "Outfit track — want to post about fall/winter coats, give me a title set" | Extracts same-track patterns to iterate your title library |
| Broad category first | "I want to do beauty content but haven't decided a direction yet" | Recommends sub-directions for you to confirm before querying and generating |
| Riding trending topics | "What titles are trending site-wide lately? Adapt a few for me" | Applies hot patterns to your specific product and tone |
Output Example
After analysis, you will receive 10 titles. Each entry looks roughly like this (illustrative):
Title 1: Style an oversized coat like this — even petite frames look tall
📈 Match Score: 9.2 🔥 Reference viral note: Original title excerpt (Engagement: example) 👍 Rationale: Combines a numerical pain point with an outfit-result promise, matching the sentence structure common to high-engagement titles in this track.
---
(10 titles total, separated by dividers for easy copying and selection.)
---
Use Cases
| Scenario | Role | Example Request | Benefit |
|---|---|---|---|
| New product launch | E-commerce / brand ops | "New product dropping — help me write XHS titles highlighting ingredients and effects" | Multiple publish-ready candidates fast, boosting click-through |
| Ongoing account posts | Creator / content lead | "Skincare track, posting a serum review this week — give me 10 titles" | Sustain track viral patterns, reduce title and topic paralysis |
| Testing a broad niche | New creator | "Want to do beauty content but only know the broad category" | Narrow the direction first, then generate — lower trial-and-error cost |
| Trending remix | Content operations | "What titles are trending site-wide? Adapt a few I can post" | Translate hot patterns into your specific product and voice |
---
小红书标题生成 / xiaohongshu-title
---
简介
基于全网每日持续收录的爆款笔记数据,智能分析爆款标题规律,一键为你生成 10 个高流量吸睛标题。
核心价值
- 海量样本对齐:每日持续收录爆款笔记,标题创作有据可依,避免凭空臆造案例与互动数据。
- 先析后写:先完成「爆款标题分析」,再输出新标题,规律清晰、便于选用。
- 批量交付:一次给出 10 条统一版式标题,含匹配指数、参考链接与推荐理由,方便对比与 A/B 测试。
适用对象
- 📝 小红书博主 — 告别标题纠结,用数据规律提升笔记点击率与曝光。
- 🛍️ 品牌 / 电商运营 — 按产品词与卖点快速产出多组备选标题。
- 🏢 MCN / 内容策划 — 同赛道批量提案,沉淀可复用的标题套路。
---
功能特性
核心功能
- 关键词驱动:支持产品词、话题词;输入较宽泛的大类词时,会先推荐细分方向,由你确认后再继续。
- 智能时间策略:样本不足时自动扩大查询时间范围(由近到远),不擅自更换你的核心关键词。
- 双阶段产出:先分析爆款标题的结构、人群与规律,再创作 10 条新标题(非照抄原题)。
- 标准交付形态:每条标题附带匹配指数、可参考的爆款链接与详细推荐理由,版式统一、便于筛选。
---
密钥获取与安全说明
- 本技能需要使用环境变量:
REDFOX_API_KEY。 REDFOX_API_KEY由 红狐 hub (https://redfox.hk) 提供。- 请前往 红狐 hub 注册账号,获取
REDFOX_API_KEY。 - 配置设备环境变量
REDFOX_API_KEY后使用本技能。 - 在提供密钥前,请先确认密钥来源、可用范围、有效期及是否支持重置/撤销。
- 禁止在代码、提示词、日志或输出文件中硬编码/明文暴露密钥。
---
使用指南
直接用自然语言说出你的产品、话题或创作需求即可,无需记忆固定命令。
常用说法速查
| 意图 | 示例话术 | 效果 |
|---|---|---|
| 为单品起标题 | 「帮我给防晒霜写几个小红书爆款标题,卖点是清爽不油腻」 | 按关键词对齐爆款样本,先分析再出 10 条备选 |
| 赛道日常更新 | 「穿搭赛道,最近想发秋冬大衣,来一组标题」 | 拉取同赛道规律,迭代你的标题库 |
| 大类先细分 | 「想做美妆方向的标题,方向还没定」 | 先推荐细分方向,你确认后再继续查询与生成 |
| 追近期热点 | 「看看最近全站什么标题火,帮我改编几条」 | 基于近期热门样本再落到你的具体创作 |
输出示例
完成分析后,你将收到 10 条标题,每条大致如下(示意):
标题 1:秋冬大衣这样穿,小个子也能显高
📈 匹配指数:9.2 🔥 参考的爆款:原爆款标题摘要(互动数:示例) 👍 推荐理由:结合数字痛点与穿搭结果承诺,符合同类高互动标题的句式习惯。
---
(共 10 条,条与条之间以分隔线区分,便于复制选用。)
---
使用场景
| 场景 | 角色 | 示例问法 | 收益 |
|---|---|---|---|
| 新品起标题 | 电商 / 品牌运营 | 「新品上市,帮我写小红书标题,突出成分和功效」 | 快速得到多组可发布备选,提升点击率 |
| 账号日常更新 | 博主 / 编导 | 「护肤赛道,这周想发精华测评,来 10 个标题」 | 延续赛道爆款规律,减少选题与标题空转 |
| 大类试水 | 新手创作者 | 「想做美妆内容,但只知道大类」 | 先细分方向再生成,降低盲目试错成本 |
| 追热点改编 | 内容运营 | 「最近全站什么标题火?帮我改几条能发的」 | 把热门规律落到自己的具体产品与话术 |
---
#!/usr/bin/env python3
"""
小红书热门数据查询脚本
接口地址:https://redfox.hk/story/api/cozeSkill/getXhsCozeSkillData
"""
import os
import sys
import argparse
import json
import requests
def fetch_xhs_trends(keyword: str, debug: bool = False, max_retries: int = 3, start_date: str = None):
"""
调用接口获取小红书热门数据
Args:
keyword: 搜索关键词(多个关键词用逗号分隔,最多5个,总长度不超过200)
debug: 是否打印调试信息
max_retries: 最大重试次数
start_date: 开始日期,格式 yyyy-MM-dd,最长为最近30天
Returns:
dict: 包含4类爆款数据
Raises:
Exception: 当API调用失败时抛出异常
"""
url = "https://redfox.hk/story/api/cozeSkill/getXhsCozeSkillData"
# 从环境变量获取 API Key
api_key = os.getenv("REDFOX_API_KEY")
if not api_key:
raise Exception("未找到 REDFOX_API_KEY 环境变量,请先配置 API Key。参考文档中的鉴权说明进行配置。")
params = {
"keyword": keyword,
"source": "小红书爆款标题创作-GitHub"
}
# 添加开始日期参数
if start_date:
params["startDate"] = start_date
headers = {
"Content-Type": "application/json",
"X-API-KEY": api_key,
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Accept": "application/json, text/plain, */*",
"Accept-Language": "zh-CN,zh;q=0.9",
}
last_error = None
for attempt in range(max_retries):
try:
if debug:
print(f"\n=== DEBUG: 第 {attempt + 1} 次尝试 ===", file=sys.stderr)
response = requests.get(url, params=params, headers=headers, timeout=30)
if debug:
print(f"状态码: {response.status_code}", file=sys.stderr)
if response.status_code >= 400:
raise Exception(f"HTTP请求失败: 状态码 {response.status_code}, {response.text[:200]}")
data = response.json()
if "data" not in data:
error_msg = data.get("msg", "未知错误")
raise Exception(f"API 错误: {error_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)
return {
"keyword": keyword,
"low_fan_explosive": result_data.get("lowPowderExplosiveArticle", []),
"daily_like_top500": result_data.get("likeTheTop500", []),
"daily_increment": result_data.get("singleDayIncrements", []),
"weekly_increment": result_data.get("sevenDaysOfIncrements", [])
}
except requests.exceptions.RequestException as e:
last_error = f"请求失败: {str(e)}"
if debug:
print(f" 错误: {type(e).__name__}: {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" 错误: {type(e).__name__}: {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_per_category=5):
"""提取所有封面图URL"""
urls = []
categories = [
('low_fan_explosive', '低粉高赞'),
('daily_like_top500', '点赞最多'),
('daily_increment', '单日互动爆发'),
('weekly_increment', '7日持续增长')
]
for key, name in categories:
items = data.get(key, [])[:max_per_category]
for item in items:
cover_url = item.get('coverUrl', '')
photo_id = item.get('photoId', '')
title = item.get('title', '')[:20]
if cover_url and photo_id:
urls.append({
'category': name,
'title': title,
'photo_id': photo_id,
'cover_url': cover_url,
'link': f"https://www.xiaohongshu.com/explore/{photo_id}"
})
return urls
def format_output(data: dict, max_items: int = None, start_date: str = None):
"""
格式化输出热门数据(表格形式)
Args:
data: 原始数据
max_items: 每类爆款数据最多展示数量,None 表示展示所有数据
start_date: 开始日期,格式 yyyy-MM-dd,用于计算统计时间范围
"""
from datetime import datetime
# 计算统计时间范围
def get_time_range(start_date):
if start_date:
try:
start = datetime.strptime(start_date, '%Y-%m-%d')
end = datetime.now()
days = (end - start).days
if days <= 1:
return "近1天"
elif days <= 7:
return f"近{days}天"
else:
return f"近{days}天"
except:
return "近30天"
return "近30天"
time_range = get_time_range(start_date)
def process_title(item):
"""处理标题:转义特殊字符,空标题使用desc替代"""
title = item.get('title', '')
# 如果标题为空,尝试使用 desc 字段
if not title or title.strip() == '':
desc = item.get('desc', '')
if desc:
# 移除 desc 中的换行符并截取前30个字符
title = desc.replace('\n', ' ').replace('\r', ' ').strip()[:30]
if len(desc) > 30:
title = title + '...'
if not title or title.strip() == '':
title = '无标题'
# 转义 Markdown 表格特殊字符(|)
title = title.replace('|', '\\|')
# 移除换行符
title = title.replace('\n', ' ').replace('\r', ' ')
# 移除多余空格
title = ' '.join(title.split())
# 截断过长标题
if len(title) > 30:
title = title[:30] + "..."
return title
def format_time(item):
"""格式化发布时间为 X月X日"""
pub_time = item.get('publicTime', '')
if pub_time:
try:
month = int(pub_time[5:7])
day = int(pub_time[8:10])
return f"{month}月{day}日"
except:
pass
return '--'
def format_note_link(item):
"""生成作品链接"""
photo_id = item.get('photoId', '')
if photo_id:
return f"[查看详情](https://www.xiaohongshu.com/explore/{photo_id})"
return '--'
def get_latest_date(data):
"""获取数据中最新的发布日期"""
all_items = []
for key in ['low_fan_explosive', 'daily_like_top500', 'daily_increment', 'weekly_increment']:
all_items.extend(data.get(key, []))
latest_date = None
for item in all_items:
pub_time = item.get('publicTime', '')
if pub_time:
try:
date_str = pub_time[:10] # 取 "YYYY-MM-DD" 部分
if latest_date is None or date_str > latest_date:
latest_date = date_str
except:
pass
return latest_date
output = []
# 检查数据日期
latest_date = get_latest_date(data)
# 按 photoId 去重(API 返回数据可能有重复)
def dedup_items(items):
seen = set()
result = []
for item in items:
photo_id = item.get('photoId', '')
if photo_id and photo_id not in seen:
seen.add(photo_id)
result.append(item)
return result
# 按时间倒序排序
def sort_by_time_desc(items):
"""按发布时间倒序排列"""
def get_time_key(item):
pub_time = item.get('publicTime', '')
if pub_time:
return pub_time
return '0'
return sorted(items, key=get_time_key, reverse=True)
# 检查是否有任何数据
low_fan_items = dedup_items(data.get("low_fan_explosive", []))
daily_like_items = dedup_items(data.get("daily_like_top500", []))
daily_increment_items = dedup_items(data.get("daily_increment", []))
weekly_increment_items = dedup_items(data.get("weekly_increment", []))
total_count = len(low_fan_items) + len(daily_like_items) + len(daily_increment_items) + len(weekly_increment_items)
# 如果所有类型都没有数据,输出友好提示
if total_count == 0:
keyword = data.get("keyword", "")
output.append(f"# 小红书爆款数据分析报告\n\n**关键词**:{keyword}\n\n")
output.append("---\n\n")
output.append("## 暂无相关爆款数据\n\n")
output.append(f"很抱歉,当前关键词 **「{keyword}」** 尚未有足够的爆款笔记数据。\n\n")
output.append("### 可能原因\n\n")
output.append("- 该关键词相对小众或新兴,爆款内容积累较少\n")
output.append("- 近期该赛道热度较低,暂无突出爆款笔记\n")
output.append("- 关键词表述方式可以更加具体或热门\n\n")
output.append("### 建议操作\n\n")
output.append("- 更换为更热门的关键词,如:**\"早八穿搭\"**、**\"减脂餐\"**、**\"职场干货\"** 等\n")
output.append("- 尝试更细分的长尾关键词,如:**\"小个子穿搭\"**、**\"学生党便当\"** 等\n")
output.append("- 输入其他感兴趣的领域或赛道进行追踪\n\n")
output.append("---\n\n")
output.append("*数据来源:小红书爆款雷达,每日更新最新热门内容*\n")
return "\n".join(output)
# 1. 低粉高赞
items = sort_by_time_desc(low_fan_items)
if max_items is not None:
items = items[:max_items]
output.append(f"\n### - **低粉高赞**(粉丝<5000的博主中点赞最多的内容)")
output.append("\n")
if not items:
output.append("(无数据)\n")
else:
output.append("| 序号 | 发布时间 | 标题 | 作者 | 收藏 | 分享 | 评论 | 点赞 | **互动总数** |")
output.append("|------|----------|------|------|------|------|------|------|-------------|")
for idx, item in enumerate(items, 1):
user_id = item.get('userId', '')
user_name = item.get('userName', '未知')
fans = item.get('fans', 0)
# 作者信息添加主页链接
if user_id:
author_str = f"[{user_name}](https://www.xiaohongshu.com/user/profile/{user_id})(粉丝:{fans})"
else:
author_str = f"{user_name}(粉丝:{fans})"
title = process_title(item)
pub_time = format_time(item)
# 标题添加作品链接
photo_id = item.get('photoId', '')
if photo_id:
note_link = f"https://www.xiaohongshu.com/explore/{photo_id}"
title_with_link = f"[{title}]({note_link})"
else:
title_with_link = title
output.append(f"| {idx} | {pub_time} | {title_with_link} | {author_str} | {item.get('collectedCount', 0)} | {item.get('useShareCount', 0)} | {item.get('useCommentCount', 0)} | {item.get('useLikeCount', 0)} | **{item.get('interactiveCount', 0)}** |")
# 2. 点赞最多
items = sort_by_time_desc(data.get("daily_like_top500", []))
if max_items is not None:
items = items[:max_items]
output.append(f"\n### - **点赞最多**(统计时间内点赞数最多的内容)")
output.append("\n")
if not items:
output.append("(无数据)\n")
else:
output.append("| 序号 | 发布时间 | 标题 | 作者 | **点赞** | 收藏 | 分享 | 评论 | 互动总数 |")
output.append("|------|----------|------|------|--------|------|------|------|------------|")
for idx, item in enumerate(items, 1):
user_id = item.get('userId', '')
user_name = item.get('userName', '未知')
fans = item.get('fans', 0)
# 作者信息添加主页链接
if user_id:
author_str = f"[{user_name}](https://www.xiaohongshu.com/user/profile/{user_id})(粉丝:{fans})"
else:
author_str = f"{user_name}(粉丝:{fans})"
title = process_title(item)
pub_time = format_time(item)
# 封面图
cover_url = item.get('coverUrl', '')
if cover_url:
cover_str = f"[查看封面]({cover_url})"
else:
cover_str = "--"
# 标题添加作品链接
photo_id = item.get('photoId', '')
if photo_id:
note_link = f"https://www.xiaohongshu.com/explore/{photo_id}"
title_with_link = f"[{title}]({note_link})"
else:
title_with_link = title
output.append(f"| {idx} | {pub_time} | {title_with_link} | {author_str} | **{item.get('useLikeCount', 0)}** | {item.get('collectedCount', 0)} | {item.get('useShareCount', 0)} | {item.get('useCommentCount', 0)} | {item.get('interactiveCount', 0)} |")
# 3. 单日互动爆发
items = sort_by_time_desc(data.get("daily_increment", []))
if max_items is not None:
items = items[:max_items]
output.append(f"\n### - **单日互动爆发**(当天互动量增长最多的内容)")
output.append("\n")
if not items:
output.append("(无数据)\n")
else:
output.append("| 序号 | 发布时间 | 标题 | 作者 | 收藏 | 分享 | 评论 | 点赞 | 互动总数 |")
output.append("|------|----------|------|------|------|------|------|------|------------|")
for idx, item in enumerate(items, 1):
user_id = item.get('userId', '')
user_name = item.get('userName', '未知')
fans = item.get('fans', 0)
# 作者信息添加主页链接
if user_id:
author_str = f"[{user_name}](https://www.xiaohongshu.com/user/profile/{user_id})(粉丝:{fans})"
else:
author_str = f"{user_name}(粉丝:{fans})"
title = process_title(item)
pub_time = format_time(item)
# 标题添加作品链接
photo_id = item.get('photoId', '')
if photo_id:
note_link = f"https://www.xiaohongshu.com/explore/{photo_id}"
title_with_link = f"[{title}]({note_link})"
else:
title_with_link = title
# 从 anaAdd 对象获取新增互动数据
ana_add = item.get('anaAdd', {})
if ana_add:
total = ana_add.get('addInteractiveount', 0)
collected = ana_add.get('addCollectedCunt', 0)
share = ana_add.get('addShareCount', 0)
comment = ana_add.get('addCommentCount', 0)
like = ana_add.get('addLikeCount', 0)
else:
total = 0
collected = 0
share = 0
comment = 0
like = 0
output.append(f"| {idx} | {pub_time} | {title_with_link} | {author_str} | {collected} | {share} | {comment} | {like} | **{total}** |")
# 4. 7日持续增长
items = sort_by_time_desc(data.get("weekly_increment", []))
if max_items is not None:
items = items[:max_items]
output.append(f"\n### - **7日持续增长**(近7天互动量持续增长最多的内容)")
output.append("\n")
if not items:
output.append("(无数据)\n")
else:
output.append("| 序号 | 发布时间 | 标题 | 作者 | 收藏 | 分享 | 评论 | 点赞 | 互动总数 |")
output.append("|------|----------|------|------|------|------|------|------|------------|")
for idx, item in enumerate(items, 1):
user_id = item.get('userId', '')
user_name = item.get('userName', '未知')
fans = item.get('fans', 0)
# 作者信息添加主页链接
if user_id:
author_str = f"[{user_name}](https://www.xiaohongshu.com/user/profile/{user_id})(粉丝:{fans})"
else:
author_str = f"{user_name}(粉丝:{fans})"
title = process_title(item)
pub_time = format_time(item)
# 标题添加作品链接
photo_id = item.get('photoId', '')
if photo_id:
note_link = f"https://www.xiaohongshu.com/explore/{photo_id}"
title_with_link = f"[{title}]({note_link})"
else:
title_with_link = title
# 从 anaAdd 对象获取新增互动数据
ana_add = item.get('anaAdd', {})
if ana_add:
total = ana_add.get('addInteractiveount', 0)
collected = ana_add.get('addCollectedCunt', 0)
share = ana_add.get('addShareCount', 0)
comment = ana_add.get('addCommentCount', 0)
like = ana_add.get('addLikeCount', 0)
else:
total = 0
collected = 0
share = 0
comment = 0
like = 0
output.append(f"| {idx} | {pub_time} | {title_with_link} | {author_str} | {collected} | {share} | {comment} | {like} | **{total}** |")
return "\n".join(output)
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=['text', 'json', 'markdown'],
default='markdown', help='输出格式:text(文本表格)、json(JSON格式)或 markdown(Markdown格式,默认)')
parser.add_argument('--output-file', type=str, default=None,
help='输出文件路径(默认:关键词_爆款数据.md)')
parser.add_argument('--start-date', type=str, default=None,
help='开始日期,格式 yyyy-MM-dd(默认最近30天)')
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_trends(args.keyword, debug=args.debug, max_retries=args.max_retries, start_date=args.start_date)
# 生成输出内容
if args.output_format == 'json':
output_content = json.dumps(data, ensure_ascii=False, indent=2)
elif args.output_format == 'markdown':
# Markdown 格式添加标题
markdown_header = f"# 小红书爆款数据分析报告\n\n**关键词**:{args.keyword}\n\n"
output_content = markdown_header + format_output(data, max_items=args.max_items, start_date=args.start_date)
else:
output_content = format_output(data, max_items=args.max_items, start_date=args.start_date)
# 确定输出文件路径(markdown 格式默认输出到文件)
output_file = args.output_file
if output_file is None and args.output_format == 'markdown':
# 默认文件名:关键词_爆款数据.md
output_file = f"{args.keyword}_爆款数据.md"
# 输出到文件或控制台
if output_file:
with open(output_file, 'w', encoding='utf-8') as f:
f.write(output_content)
print(f"✓ 结果已保存到: {output_file}", file=sys.stderr)
print(f"✓ 关键词: {args.keyword}", file=sys.stderr)
# 统计数据
total_items = (
len(data.get('low_fan_explosive', [])) +
len(data.get('daily_like_top500', [])) +
len(data.get('daily_increment', [])) +
len(data.get('weekly_increment', []))
)
print(f"✓ 总计: {total_items} 条数据", file=sys.stderr)
# 显示每类数据量
print(f" - 低粉高赞: {len(data.get('low_fan_explosive', []))} 条", file=sys.stderr)
print(f" - 点赞最多: {len(data.get('daily_like_top500', []))} 条", file=sys.stderr)
print(f" - 单日互动爆发: {len(data.get('daily_increment', []))} 条", file=sys.stderr)
print(f" - 7日持续增长: {len(data.get('weekly_increment', []))} 条", file=sys.stderr)
# 输出封面图URL供后续分析
cover_urls = get_cover_urls(data, max_per_category=3)
if cover_urls:
print(f"\n=== 封面图URL(用于风格分析)===", file=sys.stderr)
for i, item in enumerate(cover_urls, 1):
print(f"{i}. [{item['category']}] {item['title']}: {item['cover_url']}", file=sys.stderr)
else:
print(output_content)
except Exception as e:
print(f"❌ 错误: {str(e)}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()