
Xiaohongshu Search
- 1 installs
- 404 repo stars
- Updated August 5, 2026
- aiskillstore/marketplace
xiaohongshu-search is a skill that searches public Xiaohongshu (RED) data via a Node CLI for viral-note discovery, competitor analysis, KOL screening, and trend monitoring.
About
xiaohongshu-search is a Node.js command tool that mines public Xiaohongshu (RED) data for marketing and competitor analysis. A marketer uses it to find high-engagement notes, monitor keywords and competitor accounts, and screen KOLs by audience and engagement. It runs via scripts/search.js with options for search type, sort order, result count, and JSON or Markdown output, and requires a GUAIKEI_API_TOKEN. The documentation is written in Chinese.
- Searches Xiaohongshu (RED) public data for marketing insight
- Covers viral-note discovery, competitor analysis, and KOL screening
- Node CLI with sort, type, limit, and JSON/Markdown output
Xiaohongshu Search by the numbers
- 1 all-time installs (skills.sh)
- Ranked #1,710 of 1,879 Marketing & SEO skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
xiaohongshu-search capabilities & compatibility
- Capabilities
- research · web search · marketing · data analysis
- Use cases
- research · web search · marketing · data analysis
- Pricing
- Bring your own API key
What xiaohongshu-search says it does
小红书运营全链路数据工具|关键词监控+爆款挖掘+竞品分析+KOL筛选+趋势洞察
配置环境变量 `GUAIKEI_API_TOKEN`(默认TOKEN仅用于体验,私有TOKEN需申请)
`--limit <10>`:返回数量,1-60(默认10)
npx skills add https://github.com/aiskillstore/marketplace --skill xiaohongshu-searchAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1 |
|---|---|
| repo stars | ★ 404 |
| Last updated | August 5, 2026 |
| Repository | aiskillstore/marketplace ↗ |
What it does
Mine public Xiaohongshu data for viral notes, competitor tracking, and KOL screening.
Who is it for?
Mining Xiaohongshu public data for competitor and KOL marketing research
Skip if: English or non-Xiaohongshu platforms; guidance is Chinese and RED-specific
When should I use this skill?
Researching Xiaohongshu trends, competitors, or KOLs by data
What you get
Data-driven Xiaohongshu insights on viral notes, competitors, and KOLs
- JSON or Markdown reports of Xiaohongshu notes and KOL data
By the numbers
- --limit accepts 1-60 results
- 4 sort modes: comprehensive, latest, most likes, most comments
Files
📊 小红书商业洞察与竞品分析助手
一句话价值主张:告别盲目创作,用数据驱动小红书流量增长。从海量公开数据中提炼可落地的爆款逻辑、竞品策略、KOL价值,覆盖内容创作、品牌营销、市场分析全场景,让小红书运营决策有迹可循。
1. 技能概述
这是一款专注于小红书商业数据挖掘的工具。它能够穿透小红书的公开数据层,为你提供深度的竞品监控、趋势预测和KOL 筛选服务。无论你是内容创作者、品牌营销人员还是市场分析师,都能通过此工具获取决策支持。
1.1 核心能力矩阵
| 能力模块 | 核心功能 | 解决痛点 |
|---|---|---|
| 🔍 爆款挖掘 | 热门笔记发现、高互动内容检索 | 找不到选题灵感,不知道什么内容火 |
| 🕵️ 竞品分析 | 对标账号监控、笔记表现追踪 | 竞品为什么涨粉快?他们的策略是什么? |
| 👥 KOL 筛选 | 博主粉丝画像、互动率分析 | 找不到合适的投放博主,担心数据造假 |
| 📈 趋势监控 | 关键词热度追踪、话题趋势分析 | 错过热点,无法预判市场风向 |
1.2 适用人群
✅ 小红书内容创作者/运营 | ✅ 品牌营销/市场人员 | ✅ 数据分析师 | ✅ MCN机构/博主经纪人
2. 快速使用指南
2.1 前置条件
- 安装Node.js 16+环境
- 配置环境变量
GUAIKEI_API_TOKEN(默认TOKEN仅用于体验,私有TOKEN需申请)
2.2 基础语法
# 语法:node scripts/search.js [关键词] [选项]2.3 选项说明
--type <0>:搜索类型,0-全部,1-视频,2-图文(默认0)--sort <0>:排序依据,0-综合,1-最新,2-最多点赞,3-最多评论,4-最多收藏(默认0)--limit <10>:返回数量,1-60(默认10)--output <json>:输出格式,json/markdown(默认json)
2.4 典型示例
# 示例1:基础搜索(JSON格式)
node scripts/search.js AI
# 示例2:带空格的关键词
node scripts/search.js "AI 教程"
# 示例3:自定义搜索类型(视频)
node scripts/search.js AI --type 1
# 示例4:自定义排序(最多点赞)
node scripts/search.js "AI 模型" --sort 2
# 示例5:自定义返回结果数量(20条)
node scripts/search.js AI --limit 20
# 示例6:自定义输出格式(Markdown)
node scripts/search.js "AI 教程" --output markdown
# 示例7:复杂搜索(图文+最多点赞+20条结果+JSON格式)
node scripts/search.js --keyword "AI 教程" --type 2 --sort 2 --limit 20 --output json3. 数据合规说明
✅ 仅抓取小红书公开可见内容,无隐私数据泄露风险 ✅ 数据仅用于商业分析参考,需遵守小红书平台使用条款 ✅ 所有输出数据均做脱敏处理,不涉及用户个人信息
4. 技术说明(OpenClaw 适配)
- 运行环境:Node.js 16+,需提前配置
GUAIKEI_API_TOKEN环境变量 - 数据输出格式:支持JSON/Markdown(按需返回)
- 触发方式:支持自然语言指令直接触发,无需固定语法,容错率高
/**
* TOKEN管理模块
*/
const utils = require("./utils");
function apiKey(token) {
let isDefault = false;
if (token == undefined) {
isDefault = true;
} else if (token == "") {
isDefault = true;
} else if (typeof token != "string") {
isDefault = true;
} else if (token.length != 32) {
isDefault = true;
}
if (isDefault) {
utils.printError(
"未正确设置 GUAIKEI_API_TOKEN 环境变量, 将使用默认值, 可能影响搜索效率或搜索频率受限, 建议升级为私有TOKEN以获得更好的搜索体验",
);
return "e10adc3949ba59abbe56e057f20f883e";
} else {
return token;
}
}
module.exports = {
apiKey,
};
/**
* 通用工具函数模块
*/
function printBanner() {
console.log("╔════════════════════════════════════════════╗");
console.log("║ ║");
console.log("║ 📕 小红书搜索 ║");
console.log("║ ║");
console.log("╚════════════════════════════════════════════╝");
console.log("");
}
function printLog(level, message) {
const colorMap = {
INFO: "\x1b[34m",
SUCCESS: "\x1b[32m",
WARN: "\x1b[33m",
ERROR: "\x1b[31m",
};
console.log(
`${colorMap[level] || ""}[${new Date().toLocaleString()}] [${level}] ${message}\x1b[0m`,
);
}
module.exports = {
printBanner,
printInfo: (msg) => printLog("INFO", msg),
printSuccess: (msg) => printLog("SUCCESS", msg),
printError: (msg) => printLog("ERROR", msg),
printWarn: (msg) => printLog("WARN", msg),
};
/**
* 小红书笔记搜索模块
*/
const https = require("https");
const querystring = require("querystring");
const BASE_URL = "www.guaikei.com";
const utils = require("./utils");
/**
* 检查搜索关键词是否符合要求
*/
function notIdealFormat(keyword) {
keyword = keyword.trim();
if (keyword.length < 2) {
utils.printError(`搜索关键词长度不能小于 2 个字符`);
return false;
}
if (keyword.length > 50) {
utils.printError(`搜索关键词长度不能超过 50 个字符`);
return false;
}
if (/[<>\"'&]/g.test(keyword)) {
utils.printError(`搜索关键词包含特殊字符, 请输入普通关键词, 例如: 新媒体`);
return false;
}
if (keyword.includes("http")) {
utils.printError(
`搜索关键词包含 http 链接, 请输入普通关键词, 例如: 新媒体`,
);
return false;
}
return true;
}
/**
* 清洗搜索关键词
*/
function sanitizeKeyword(keyword) {
let trimmed = keyword.trim();
return trimmed.replace(/[^\u4e00-\u9fa5a-zA-Z0-9\s.,!?# ,。!?]/g, "");
}
/**
* 格式化搜索选项, 并检查是否有效
*/
function optionFormat(type, sort, limit, output) {
type = type || 0;
sort = sort || 0;
limit = limit || 10;
output = output || "json";
if (type !== 0 && type !== 1 && type !== 2) {
utils.printError(`搜索类型 ${type} 无效, 请使用 0, 1, 2。 默认值为 0`);
type = 0;
}
if (sort !== 0 && sort !== 1 && sort !== 2 && sort !== 3 && sort !== 4) {
utils.printError(
`排序依据 ${sort} 无效, 请使用 0, 1, 2, 3, 4。 默认值为 0`,
);
sort = 0;
}
if (limit < 1 || limit > 60) {
utils.printError(`搜索数量 ${limit} 无效, 请使用 1-60。 默认值为 10`);
limit = 10;
}
if (output !== "json" && output !== "markdown") {
utils.printError(
`输出格式 ${output} 无效, 请使用 json, markdown。 默认值为 json`,
);
output = "json";
}
return [type, sort, limit, output];
}
function formatMessage(keyword, result) {
let message = `**小红书笔记搜索结果**: ${keyword}\n`;
message += "-".repeat(35) + "\n\n";
for (let i = 0; i < result.length; i++) {
const item = result[i];
message += `**${i + 1} .** ${item.title || "[无标题]"}\n`;
message += `**发布时间**: ${item.publish_time || "[未知]"}\n`;
message += `**链接**: ${item.url || "[未知]"}\n`;
message += `**发布人**: ${item.user.nickname || "[未知]"}\n`;
if (item.image_list && item.image_list.length > 0) {
message += `**图文**: ${item.image_list.slice(0, 3).join(", ")}...\n`;
}
message += `**点赞**: ${item.liked_count || 0}\t`;
message += `**评论**: ${item.comment_count || 0}\t`;
message += `**收藏**: ${item.collected_count || 0}\t`;
message += `**分享**: ${item.shared_count || 0}\n`;
message += "\n";
}
message += "-".repeat(35) + "\n";
message += `**共 ${result.length} 条结果**\n`;
return message;
}
async function createWithRetry(token, keyword, type, sort, limit) {
let lastError = null;
const retryIntervals = [1000, 2000, 3000];
for (let attempt = 0; attempt < 3; attempt++) {
try {
const timeoutPromise = new Promise((_, reject) =>
setTimeout(
() => reject(new Error(`创建任务超时 (${attempt + 1}/3)`)),
10000,
),
);
const task = await Promise.race([
createSearchTask(token, keyword, type, sort, limit),
timeoutPromise,
]);
if (task.errcode === 0) return task;
throw new Error(`创建任务失败, 错误信息: ${JSON.stringify(task.errmsg)}`);
} catch (error) {
lastError = error;
utils.printInfo(
`【创建任务重试】 ${attempt + 1}/3 次 - ${error.message}`,
);
if (attempt < 2) {
await new Promise((resolve) =>
setTimeout(resolve, retryIntervals[attempt]),
);
}
}
}
throw lastError || new Error("创建搜索任务失败, 3次重试均失败");
}
/**
* 创建小红书笔记搜索任务
* @param {string} token - API令牌
* @param {string} keyword - 搜索关键词
* @param {number} type - 搜索类型, 0: 全部, 1: 视频, 2: 图文
* @param {number} sort - 排序依据, 0: 综合, 1: 最新, 2: 最多点赞, 3: 最多评论, 4: 最多收藏
* @param {number} limit - 搜索数量, 1-60
* @returns {Promise<Object>} 搜索任务状态
* @throws {Error} API调用失败时抛出错误
*/
async function createSearchTask(token, keyword, type, sort, limit) {
return new Promise((resolve, reject) => {
const url = "/api/xiaohongshu/note-search/keyword";
const params = { _: Date.now(), token: token };
const data = JSON.stringify({
keyword,
type,
sort,
limit,
});
const options = {
hostname: BASE_URL,
path: url + "?" + querystring.stringify(params),
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.byteLength(data),
},
timeout: 20000,
};
const req = https.request(options, (res) => {
let body = "";
res.on("data", (chunk) => {
body += chunk;
});
res.on("end", () => {
if (res.statusCode === 200) {
try {
const json = JSON.parse(body);
if (json.errcode === 0) {
resolve(json);
} else {
reject(new Error(`请求错误信息: ${json.errmsg}`));
return;
}
} catch (error) {
reject(new Error(`解析响应失败: ${error.message}`));
return;
}
} else if (
res.statusCode === 401 ||
res.statusCode === 407 ||
res.statusCode === 403 ||
res.statusCode === 410 ||
res.statusCode === 408
) {
reject(new Error(`GUAIKEI_API_TOKEN 无效, 请检查环境变量`));
} else {
reject(new Error(`请求失败, 状态码: ${res.statusCode}`));
}
});
});
req.on("error", (err) => {
reject(err);
});
req.write(data);
req.end();
});
}
async function searchWithRetry(token, keyword, type, sort, limit) {
let lastError = null;
const maxAttempts = 60;
const retryInterval = 2000;
for (let attempt = 0; attempt < maxAttempts; attempt++) {
try {
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => {
reject(new Error(`查询结果超时 (${attempt + 1}/${maxAttempts})`));
}, 5000);
});
const data = await Promise.race([
getSearchTask(token, keyword, type, sort, limit),
timeoutPromise,
]);
if (Array.isArray(data) && data.length > 0) return data;
throw new Error(`第 ${attempt + 1} 次查询无结果`);
} catch (error) {
lastError = error;
utils.printInfo(
`【查询结果重试】尝试 ${attempt + 1} / ${maxAttempts} - ${error.message}`,
);
await new Promise((resolve) => setTimeout(resolve, retryInterval));
}
}
throw lastError || new Error(`查询搜索结果失败, ${maxAttempts}次重试均失败`);
}
/**
* 获取小红书笔记搜索任务结果
* @param {string} token - API令牌
* @param {string} keyword - 搜索关键词
* @param {number} type - 搜索类型, 0: 全部, 1: 视频, 2: 图文
* @param {number} sort - 排序依据, 0: 综合, 1: 最新, 2: 最多点赞, 3: 最多评论, 4: 最多收藏
* @param {number} limit - 搜索数量, 1-60
* @returns {Promise<Array>} 搜索结果数组
* @throws {Error} API调用失败时抛出错误
*/
async function getSearchTask(token, keyword, type, sort, limit) {
return new Promise((resolve, reject) => {
const url = "/api/xiaohongshu/note-search/info";
const params = {
_: Date.now(),
token: token,
keyword: keyword,
type: type,
sort: sort,
limit: limit,
};
const options = {
hostname: BASE_URL,
path: url + "?" + querystring.stringify(params),
method: "GET",
headers: {
"Content-Type": "application/json",
},
timeout: 20000,
};
const req = https.request(options, (res) => {
let body = "";
res.on("data", (chunk) => {
body += chunk;
});
res.on("end", () => {
if (res.statusCode === 200) {
try {
const json = JSON.parse(body);
if (json.errcode === 0) {
for (let i = 0; i < json.data.length; i++) {
const item = json.data[i];
if (item.id && item.xsec_token) {
json.data[i].url =
"https://www.xiaohongshu.com/explore/" +
item.id +
"?xsec_token=" +
item.xsec_token;
}
if (item.user && item.user.user_id && item.user.xsec_token) {
json.data[i].user.url =
"https://www.xiaohongshu.com/user/profile/" +
item.user.user_id +
"?xsec_token=" +
item.user.xsec_token;
}
}
resolve(json.data);
} else {
reject(new Error(`请求错误信息: ${json.errmsg}`));
return;
}
} catch (error) {
reject(new Error(`解析响应失败: ${error.message}`));
return;
}
} else if (
res.statusCode === 401 ||
res.statusCode === 407 ||
res.statusCode === 403 ||
res.statusCode === 410 ||
res.statusCode === 408
) {
reject(new Error(`GUAIKEI_API_TOKEN 无效, 请检查环境变量`));
} else {
reject(new Error(`请求失败, 状态码: ${res.statusCode}`));
}
});
});
req.on("error", (err) => {
reject(err);
});
req.end();
});
}
module.exports = {
createWithRetry,
formatMessage,
optionFormat,
notIdealFormat,
sanitizeKeyword,
searchWithRetry,
};
{
"name": "xiaohongshu-search",
"version": "1.0.0",
"description": "小红书运营全链路数据工具|关键词监控+爆款挖掘+竞品分析+KOL筛选+趋势洞察,用数据驱动小红书流量增长,告别盲目创作",
"keywords": [
"小红书",
"竞品分析",
"爆款笔记",
"KOL营销",
"市场调研",
"数据挖掘",
"流量增长",
"用户画像",
"趋势监控"
],
"homepage": "https://github.com/um-why/xiaohongshu-openclaw-skill#readme",
"bugs": {
"url": "https://github.com/um-why/xiaohongshu-openclaw-skill/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/um-why/xiaohongshu-openclaw-skill.git"
},
"license": "MIT",
"author": "um-why",
"main": "scripts/search.js"
}Skill Name: 小红书搜索
#!/usr/bin/env node
const utils = require("../lib/utils");
const key = require("../lib/key");
const xiaohongshu = require("../lib/xiaohongshu");
const fs = require("fs");
const path = require("path");
/**
* 打印帮助信息
*/
function printHelp() {
console.log(`
用法: node scripts/search.js <关键词> [选项]
选项:
--keyword \t<关键词> \t搜索关键词
--type \t<类型> \t搜索类型, 0: 全部(默认), 1: 视频, 2: 图文
--sort \t<排序> \t排序依据, 0: 综合(默认), 1: 最新, 2: 最多点赞, 3: 最多评论, 4: 最多收藏
--limit \t<数量> \t搜索数量 (默认 10, 最大 60)
--output \t<格式> \t输出格式, json, markdown (默认 json)
--help \t显示帮助信息
示例1: node scripts/search.js AI
示例2: node scripts/search.js "AI 模型"
示例3: node scripts/search.js --keyword AI --type 0 --sort 0 --limit 10 --output json
示例4: node scripts/search.js --keyword "AI 模型" --type 1 --sort 2 --limit 20 --output markdown
注意:
- 关键词建议 2-50 个汉字,避免特殊符号
- 请确保环境变量 GUAIKEI_API_TOKEN 已配置
- 所有参数都会自动清洗和验证
`);
}
process.on("SIGTERM", () => {
utils.printWarn("OpenClaw 终止任务, 清理临时文件...");
const outputPath = path.join(__dirname, "last-search.json");
if (fs.existsSync(outputPath)) {
fs.unlinkSync(outputPath);
}
process.exit(0);
});
async function main() {
const startTime = Date.now();
const args = process.argv.slice(2);
if (args.length === 0) {
printHelp();
return;
}
let keyword = "",
type = 0,
sort = 0,
limit = 10,
output = "json";
args.forEach((arg, index) => {
if (arg === "--keyword") {
keyword = args[index + 1] || "";
} else if (arg === "--type") {
type = args[index + 1] || 0;
type = Number(type);
} else if (arg === "--sort") {
sort = args[index + 1] || 0;
sort = Number(sort);
} else if (arg === "--limit") {
limit = args[index + 1] || 10;
limit = Number(limit);
} else if (arg === "--output") {
output = args[index + 1] || "json";
} else if (arg === "--help" || arg === "-h") {
printHelp();
return;
} else if (arg.startsWith("--") === false && keyword === "") {
keyword = arg;
}
});
if (keyword === "") {
utils.printError(`未提供关键词`);
printHelp();
return;
}
utils.printBanner();
utils.printInfo(`原始关键词: ${keyword}`);
let isRight = xiaohongshu.notIdealFormat(keyword);
if (!isRight) {
return;
}
keyword = xiaohongshu.sanitizeKeyword(keyword);
utils.printInfo(`清洗后关键词: ${keyword}`);
[type, sort, limit, output] = xiaohongshu.optionFormat(
type,
sort,
limit,
output,
);
utils.printInfo(
`搜索类型: ${type}, 排序依据: ${sort}, 数量: ${limit}, 输出格式: ${output}`,
);
// 幂等性校验: 同一关键词+参数 2 分钟内不重复执行
const taskId = `${keyword}_${type}_${sort}_${limit}`;
const taskLockFile = path.join(__dirname, `.lock_${taskId}`);
if (fs.existsSync(taskLockFile)) {
const lockTime = fs.statSync(taskLockFile).mtimeMs;
if (Date.now() - lockTime < 2 * 60 * 1000) {
utils.printError(`同一任务 2 分钟内执行, 避免重复请求 API`);
process.exit(1);
} else {
fs.unlinkSync(taskLockFile);
}
}
// 创建锁文件
fs.writeFileSync(taskLockFile, Date.now().toString(), { mode: 0o600 });
const token = key.apiKey(process.env.GUAIKEI_API_TOKEN);
let searchTask = null;
try {
const status = await xiaohongshu.createWithRetry(
token,
keyword,
type,
sort,
limit,
);
if (status.errcode !== 0) {
throw new Error(
`搜索任务创建失败时, 遇到未知错误, 请反馈给开发者 ${status} - ${Date.now()}`,
);
}
utils.printSuccess(`搜索任务创建成功, 正在搜索中...`);
searchTask = await xiaohongshu.searchWithRetry(
token,
keyword,
type,
sort,
limit,
);
} catch (error) {
const errorOutput = {
status: "error",
keyword: keyword,
message: error.message,
error_code: error.code || "UNKNOWN",
type: type,
sort: sort,
limit: limit,
output_format: output,
timestamp: new Date().toLocaleString(),
results: [],
};
console.log(JSON.stringify(errorOutput, null, 2));
return;
} finally {
// 删除锁文件
if (fs.existsSync(taskLockFile)) {
fs.unlinkSync(taskLockFile);
}
}
if (!searchTask || !Array.isArray(searchTask) || searchTask.length === 0) {
utils.printError(`搜索任务没有返回结果, 请稍后重试或联系开发者`);
const emptyOutput = {
status: "empty",
keyword: keyword,
message: "没有找到匹配的视频或图文内容",
type: type,
sort: sort,
limit: limit,
output_format: output,
timestamp: new Date().toLocaleString(),
results: [],
};
console.log(JSON.stringify(emptyOutput, null, 2));
return;
}
// 输出搜索结果
const finalOutput = {
status: "success",
keyword: keyword,
message: "搜索任务完成",
type: type,
sort: sort,
limit: limit,
output_format: output,
total: searchTask.length,
timestamp: new Date().toLocaleString(),
openclaw_metadata: {
skill_version: "1.1.1",
runtime_version: process.versions.node,
execution_time: Date.now() - startTime,
},
results: searchTask,
};
if (output === "markdown") {
const message = xiaohongshu.formatMessage(keyword, searchTask);
utils.printInfo(message);
utils.printSuccess(`搜索任务完成, 共返回 ${searchTask.length} 条结果`);
} else {
console.log(JSON.stringify(finalOutput, null, 2));
utils.printSuccess(`搜索任务完成, 共返回 ${finalOutput.total} 条结果`);
}
// 保存搜索结果到文件
const outputPath = path.join(__dirname, "last-search.json");
fs.writeFileSync(outputPath, JSON.stringify(finalOutput, null, 2));
utils.printSuccess(` → 已保存到 ${outputPath}`);
}
main().catch((error) => {
utils.printError(error);
process.exit(1);
});
{
"schema_version": "2.0",
"meta": {
"generated_at": "2026-04-09T12:16:43.389Z",
"slug": "um-why-xiaohongshu-search",
"source_url": "https://github.com/um-why/xiaohongshu-openclaw-skill/tree/main/",
"source_ref": "main",
"model": "claude",
"analysis_version": "3.0.0",
"source_type": "community",
"content_hash": "bcf5bed5432cbdc9dde9037907e1b4d4be5a86c2f7e4cbbff7f420214ee7b76e",
"tree_hash": "fd453ff093a1085ccda180f897dd1426924a07a8b2ef2f917998e283d7b83ec8"
},
"skill": {
"name": "xiaohongshu-search",
"description": "小红书笔记搜索工具。通过 Guaikei API 获取小红书热门笔记数据,支持关键词搜索、内容筛选、排序和格式化输出。",
"summary": "小红书笔记数据搜索工具,支持关键词查询和热门内容筛选",
"icon": "📕",
"version": "1.0.0",
"author": "um-why",
"license": "MIT",
"tags": [
"xiaohongshu",
"social-media",
"data-analysis",
"content-discovery"
],
"supported_tools": [
"claude",
"codex",
"claude-code"
],
"risk_factors": [
"network",
"filesystem",
"env_access"
]
},
"security_audit": {
"risk_level": "medium",
"is_blocked": false,
"safe_to_publish": true,
"summary": "Evaluated 7 files (734 lines). Static findings contained multiple false positives: ANSI color codes misidentified as obfuscation, Node.js HTTPS requests misidentified as Ruby backtick execution, and array slicing misidentified as path traversal. Confirmed legitimate use of network requests to third-party API (guaikei.com), environment variable access for API authentication, and file system operations for caching. Primary concern is hardcoded MD5-hashed default API token which poses credential security risk. Skill functionality is platform scraping for business analytics purposes.",
"critical_findings": [],
"high_findings": [],
"medium_findings": [
{
"title": "Hardcoded Default API Token with Weak Hash",
"description": "lib/key.js:20 contains hardcoded MD5 hash 'e10adc3949ba59abbe56e057f20f883e' (MD5 of '123456') as default API token fallback. This is a credential security concern as default tokens should not be reused across installations.",
"locations": [
{
"file": "lib/key.js",
"line_start": 20,
"line_end": 20
}
],
"confidence": 0.75,
"confidence_reasoning": "Confirmed hardcoded default token in source code. MD5 is cryptographically weak, though this serves as a fallback placeholder when no token is configured."
}
],
"low_findings": [
{
"title": "Third-Party API Dependency",
"description": "Skill depends on external Guaikei API (www.guaikei.com) for data access. This creates availability and privacy dependencies beyond the skill author's control.",
"locations": [
{
"file": "lib/xiaohongshu.js",
"line_start": 6,
"line_end": 6
}
],
"confidence": 0.9,
"confidence_reasoning": "Hardcoded API hostname confirmed. Skill will not function if third-party service is unavailable."
}
],
"dangerous_patterns": [
{
"title": "Static Analysis False Positives",
"description": "58 external_commands flags (Ruby backtick), hex-encoded obfuscation flags, and path traversal flags were incorrectly detected. Actual code uses: 1) ANSI terminal color codes (\\x1b[XXm), 2) Node.js https.request() for network, 3) Array slice operations (not filesystem paths). These are legitimate patterns misidentified by pattern matching.",
"locations": []
}
],
"files_scanned": 7,
"total_lines": 734,
"audit_model": "claude",
"audited_at": "2026-04-09T12:16:43.389Z",
"risk_factor_evidence": [
{
"factor": "network",
"evidence": [
{
"file": "lib/xiaohongshu.js",
"line_start": 159,
"line_end": 159
},
{
"file": "lib/xiaohongshu.js",
"line_start": 257,
"line_end": 257
},
{
"file": "lib/xiaohongshu.js",
"line_start": 271,
"line_end": 271
},
{
"file": "lib/xiaohongshu.js",
"line_start": 278,
"line_end": 278
}
]
},
{
"factor": "filesystem",
"evidence": [
{
"file": "scripts/search.js",
"line_start": 39,
"line_end": 39
},
{
"file": "scripts/search.js",
"line_start": 107,
"line_end": 107
},
{
"file": "scripts/search.js",
"line_start": 113,
"line_end": 113
},
{
"file": "scripts/search.js",
"line_start": 117,
"line_end": 117
},
{
"file": "scripts/search.js",
"line_start": 160,
"line_end": 160
},
{
"file": "scripts/search.js",
"line_start": 210,
"line_end": 210
}
]
},
{
"factor": "env_access",
"evidence": [
{
"file": "scripts/search.js",
"line_start": 119,
"line_end": 119
}
]
}
]
},
"content": {
"user_title": "Search Xiaohongshu notes with keyword filtering",
"value_statement": "Need to find trending content on Xiaohongshu? This tool queries the Guaikei API to retrieve and filter popular notes by keywords, content type, and engagement metrics.",
"seo_keywords": [
"xiaohongshu search",
"小红书搜索",
"claude code xiaohongshu",
"social media analytics",
"content discovery tool",
"claude codex",
"note trending analysis",
"claude ai",
"red book search",
"chinese social media"
],
"actual_capabilities": [
"Search Xiaohongshu notes by keyword with real-time API query",
"Filter results by content type: all, videos only, or image-text posts",
"Sort by relevance, recency, likes, comments, or bookmarks",
"Format output as JSON or Markdown for easy integration",
"Configure result limit from 1 to 60 notes per search",
"Idempotency check prevents duplicate API calls within 2 minutes"
],
"limitations": [
"Requires valid GUAIKEI_API_TOKEN environment variable for full access",
"Limited to 60 results per search query",
"Depends on third-party Guaikei API for data retrieval",
"May be rate-limited by the upstream API service"
],
"use_cases": [
{
"title": "Content Creator Research",
"description": "Find trending topics and high-engagement posts for content ideation. Search by keyword to discover what resonates with Xiaohongshu audiences.",
"target_user": "Content creators and influencers"
},
{
"title": "Marketing Analytics",
"description": "Monitor keyword trends and competitor performance. Track engagement metrics like likes, comments, and shares for specific topics.",
"target_user": "Marketing teams and brand managers"
},
{
"title": "KOL Discovery",
"description": "Identify popular posts and creators in specific niches to find potential collaboration partners for marketing campaigns.",
"target_user": "MCN agencies and brand partnerships teams"
}
],
"prompt_templates": [
{
"title": "Basic Note Search",
"prompt": "Search for Xiaohongshu notes with keyword \"{keyword}\" and return 10 results in JSON format",
"scenario": "Simple keyword search with default settings"
},
{
"title": "Video Content Filter",
"prompt": "Search Xiaohongshu for video content about \"{topic}\", sorted by most liked, limit 20 results",
"scenario": "Filter by video content type and sort by engagement"
},
{
"title": "Markdown Report",
"prompt": "Get the top 30 most popular Xiaohongshu notes for \"{keyword}\" in markdown format",
"scenario": "Generate formatted report for sharing"
},
{
"title": "Multi-Parameter Search",
"prompt": "Search Xiaohongshu notes: keyword \"{keyword}\", type image-text, sort by bookmarks, return 15 results",
"scenario": "Advanced search with specific filters"
}
],
"output_examples": [
{
"input": "Search for notes with keyword 'AI tutorial'",
"output": "Returns 10 notes with title, author, publish time, URL, engagement counts (likes, comments, bookmarks, shares), and cover images in JSON or Markdown format"
},
{
"input": "Search videos about 'travel' sorted by recent",
"output": "Lists latest 10 video posts about travel, formatted with timestamps and video metadata"
}
],
"best_practices": [
"Set GUAIKEI_API_TOKEN environment variable before running searches for optimal performance",
"Use descriptive keywords (2-50 Chinese characters) for more accurate results",
"Implement appropriate rate limiting when running multiple searches in sequence"
],
"anti_patterns": [
"Do not include URLs or special characters in search keywords",
"Avoid searching the same keyword multiple times within 2 minutes (idempotency lock will trigger)",
"Do not exceed 60 results per query to avoid API errors"
],
"faq": [
{
"question": "How do I configure the API token?",
"answer": "Set the GUAIKEI_API_TOKEN environment variable before running. Without it, a default token is used with limited functionality."
},
{
"question": "What keyword formats are supported?",
"answer": "Keywords should be 2-50 Chinese characters or alphanumeric text. Avoid special characters, URLs, or symbols."
},
{
"question": "How many results can I retrieve per search?",
"answer": "You can request 1 to 60 results per search. The default is 10 results."
},
{
"question": "What content types can I filter by?",
"answer": "Type 0 returns all content, Type 1 returns only videos, and Type 2 returns only image-text posts."
},
{
"question": "How do I sort the search results?",
"answer": "Sort 0 is comprehensive, Sort 1 is newest, Sort 2 is most liked, Sort 3 is most commented, and Sort 4 is most bookmarked."
},
{
"question": "What output formats are available?",
"answer": "Use --output json for machine-readable JSON or --output markdown for human-readable formatted text."
}
]
},
"file_structure": [
{
"name": "lib",
"type": "dir",
"path": "lib",
"children": [
{
"name": "key.js",
"type": "file",
"path": "lib/key.js",
"lines": 29
},
{
"name": "utils.js",
"type": "file",
"path": "lib/utils.js",
"lines": 33
},
{
"name": "xiaohongshu.js",
"type": "file",
"path": "lib/xiaohongshu.js",
"lines": 321
}
]
},
{
"name": "scripts",
"type": "dir",
"path": "scripts",
"children": [
{
"name": "search.js",
"type": "file",
"path": "scripts/search.js",
"lines": 218
}
]
},
{
"name": "package.json",
"type": "file",
"path": "package.json",
"lines": 27
},
{
"name": "readme.md",
"type": "file",
"path": "readme.md",
"lines": 2
},
{
"name": "SKILL.md",
"type": "file",
"path": "SKILL.md",
"lines": 104
}
]
}
Related skills
FAQ
What data does it access?
Only publicly visible Xiaohongshu content, with output desensitized and no personal user information.
What does it need to run?
Node.js 16+ and a GUAIKEI_API_TOKEN environment variable.