| name | xhs-publisher |
| description | 自动发布小红书图文笔记。使用 Playwright CLI 操作浏览器完成登录、上传图片、填写标题正文(20字以内)、设置隐私(默认仅自己可见)、点击发布等完整流程。触发关键词:"发小红书"、"发布小红书笔记"、"小红书自动发布"、"发布笔记到小红书" |
小红书自动发布技能
使用 Playwright CLI 自动将图文内容发布到小红书创作者平台。
前置要求
-
已安装 playwright-cli
npm install -g @playwright/cli
-
首次使用需登录
- 使用有头模式
--headed --persistent 扫码登录
- 登录状态会保存,下次无需重复扫码
发布流程(按照实际成功案例)
Step 1: 后台打开浏览器并自动检测登录
使用 --persistent 保存登录状态,下次无需重复扫码。
必须后台启动浏览器。 playwright-cli open 会保持浏览器会话,不会立即退出;agent 不要用前台命令等待它结束,也不要给 open 设置长超时。长时间等待只用于后面的登录检测脚本。
Start-Process -FilePath "playwright-cli" -ArgumentList @("open", "https://www.xiaohongshu.com", "--browser=chrome", "--headed", "--persistent")
playwright-cli open https://www.xiaohongshu.com --browser=chrome --headed --persistent >/tmp/xhs-publisher-browser.log 2>&1 &
自动检测登录状态脚本:
playwright-cli run-code "async (page) => {
const MAX_WAIT = 120000; // 最多等待120秒
const CHECK_INTERVAL = 2000; // 每2秒检测一次
const checkLogin = async () => {
const currentUrl = page.url();
// 检测是否已登录:检查是否存在用户头像或用户名元素
const isLoggedIn = await page.evaluate(() => {
// 小红书登录后的特征元素
const hasAvatar = document.querySelector('.avatar img') !== null ||
document.querySelector('[class*="avatar"]') !== null ||
document.querySelector('img[src*="avatar"]') !== null;
const hasUserInfo = document.querySelector('.user-info') !== null ||
document.querySelector('[class*="user-name"]') !== null;
return hasAvatar || hasUserInfo;
});
return isLoggedIn;
};
// 轮询检测登录状态
for (let waited = 0; waited < MAX_WAIT; waited += CHECK_INTERVAL) {
const isLoggedIn = await checkLogin();
if (isLoggedIn) {
return { success: true, message: '登录成功' };
}
await page.waitForTimeout(CHECK_INTERVAL);
}
return { success: false, message: '等待登录超时,请手动扫码后重新执行' };
}"
如果返回登录成功,继续下一步;如果超时,需要用户手动扫码后重新执行流程。
Step 2: 导航到发布页面
playwright-cli goto "https://creator.xiaohongshu.com/publish/publish"
Step 3: 切换到图文模式
使用 JavaScript 点击"上传图文"按钮:
playwright-cli eval "document.querySelectorAll('span.title').forEach(el => { if(el.textContent.trim() === '上传图文') el.click(); })"
Step 4: 上传图片
-
触发文件选择器:
playwright-cli eval "document.querySelector('input[type=file]')?.click()"
-
上传封面图:
playwright-cli upload "path/to/cover.png"
-
继续上传其他图片(每上传一张需重新触发文件选择器):
playwright-cli eval "document.querySelector('input[type=file]')?.click()"
playwright-cli upload "path/to/card_1.png"
Step 5: 填写标题(截断至20字)
playwright-cli fill "textbox '填写标题会有更多赞哦'" "你的标题"
注意:小红书限制标题不超过20个字,超过部分会被导致发布失败。
Step 6: 填写正文
playwright-cli click "textbox[contenteditable]"
playwright-cli type "正文内容..."
Step 7: 添加话题标签(可选)
playwright-cli click "button '话题'"
playwright-cli type "RAG"
playwright-cli press Enter
Step 8: 设置为仅自己可见
-
点击可见性设置:
playwright-cli eval "document.querySelector('div:contains(\"公开可见\")').click()"
-
选择"仅自己可见":
playwright-cli eval "document.querySelector('text=仅自己可见').click()"
Step 9: 点击发布按钮(CDP 穿透 shadow DOM)
使用 run-code 执行 CDP 脚本点击发布按钮:
playwright-cli run-code "async page => {
const client = await page.context().newCDPSession(page);
const { root } = await client.send('DOM.getDocument', { depth: -1, pierce: true });
let targetId = null;
const walk = (n) => {
if (!n) return;
if (n.nodeName === 'BUTTON') {
const cls = (n.attributes || []).join(' ');
if (cls.includes('bg-red')) targetId = n.nodeId;
}
for (const c of (n.children || [])) walk(c);
if (n.shadowRoots) for (const s of n.shadowRoots) walk(s);
};
walk(root);
if (!targetId) throw new Error('未找到发布按钮');
const { model } = await client.send('DOM.getBoxModel', { nodeId: targetId });
const p = model.content;
const cx = (p[0] + p[2] + p[4] + p[6]) / 4;
const cy = (p[1] + p[3] + p[5] + p[7]) / 4;
await page.mouse.click(cx, cy);
await page.waitForTimeout(2000);
return { success: true };
}"
Step 10: 验证发布成功
检查页面 URL 是否变为 /publish/success:
playwright-cli eval "document.location.href"
重要约束
标题长度限制
小红书强制要求标题 不超过20个字:
- 超长标题会导致发布失败
- 优先在标点符号处截断,保持语义完整
- 建议在准备内容时控制标题长度
图片要求
- 格式:png, jpg, jpeg, webp
- 大小:单张不超过 32MB
- 数量:最多 18 张
发布按钮定位
发布按钮位于 closed shadow DOM 内,普通选择器无法选中,必须使用 CDP 协议:
- 通过
DOM.getDocument({ pierce: true }) 穿透 shadow DOM
- 查找 class 包含
bg-red 的 BUTTON 元素
- 通过
DOM.getBoxModel 获取坐标后点击
参考