AI 工具

自媒体半自动发布:从浏览器自动化到一行脚本

2026-04-12 · myster

自媒体半自动发布:从浏览器自动化到一行脚本

博客写完了,小红书卡片也生成了,但每次发布还得手动打开创作者中心、上传图片、复制粘贴文案、加标签……这些重复操作应该自动化掉。

目标

半自动:浏览器帮我填好所有内容,我只需要检查一遍然后点「发布」。不做全自动——万一填错了发出去就尴尬了。

目标平台四个:小红书、微信公众号、掘金、知乎。先从小红书开始,因为产物链最完整(图片卡片 + 文案都有了)。

第一版:浏览器自动化

Claude Code 有个 chrome 浏览器控制工具(claude-in-chrome),可以像操作 Selenium 一样控制 Chrome。思路很直接:

  1. 打开小红书创作者中心
  2. 切换到「上传图文」tab
  3. 上传 6 张卡片 PNG
  4. 填标题、填正文、加标签
  5. 停在发布按钮前

合规检查先行

发布前必须做内容合规检查。国内平台审核严格,我之前一篇 VPS 代理的文章在掘金直接被拒。所以设计了三层检查:

层级检查内容动作
第一层VPN/代理/翻墙关键词直接拦截,不打开浏览器
第二层广告法违禁词(最好、第一、100%)警告 + 替代建议
第三层平台限流词(买它→入手,便宜→价格友好)优化提示

第二三层的敏感词库用了 cn-content-matrix 这个 skill 自带的 sensitive-words.md,覆盖了广告法、各平台引流违禁词、限流词,还附带替代表达。

图片上传的坑

小红书创作者中心是 HTTPS 页面,浏览器安全策略不允许从 HTTP localhost 加载内容(混合内容拦截)。

第一次用 python3 -m http.server 起了个本地服务器,fetch 直接报错。原因是没加 CORS 头。

解决方案:写一个带 CORS 头的静态服务器,用 JavaScript 从本地服务器 fetch 图片,转成 File 对象注入到 <input type="file">

// 在小红书页面中执行
const resp = await fetch('http://127.0.0.1:18899/card-01.png');
const blob = await resp.blob();
const file = new File([blob], 'card-01.png', { type: 'image/png' });

const dt = new DataTransfer();
dt.items.add(file);
document.querySelector('input[type="file"]').files = dt.files;
// 触发 change 事件让框架识别
input.dispatchEvent(new Event('change', { bubbles: true }));

这样 6 张图就注入进去了,完全不需要用户手动拖拽。

填标题的坑

小红书标题限制 20 个字。我一开始填了 26 个字,页面显示红色的 26/20。需要在代码里预先截断。

实测发现中英文混合时,限制比较宽松——英文字母虽然显示为 1 个字符,但实际能放更多。最终把警告阈值设为 30 字。

验证结果

整个流程跑通了:6 张图上传、标题填好、正文 339 字、3 个话题标签。右侧手机预览看着没问题,点发布就行。

问题:Token 消耗太高

跑完一看 token 用量,浏览器自动化这步消耗巨大。原因是每次 screenshot 都是一张图片进上下文,图片 token 比文本贵 5-10 倍。这次操作截了 8 张图,加上 read_pagefind 等交互,光这一步就吃掉了大量 token。

这不可持续。每次发一篇文章都要这么多 token,成本太高。

第二版:沉淀为 Playwright 脚本

回想之前做小红书卡片截图时的经验:一开始也是 Claude 现场写 Playwright 代码,后来沉淀成了 scripts/xhs-screenshot.mjs,Claude 一行 node scripts/xhs-screenshot.mjs 就搞定,零 token 消耗。

同样的思路,把浏览器发布操作固化为脚本:

node scripts/post-xhs.mjs karpathy-knowledge-vault

脚本核心设计

// 1. 启动带持久化 profile 的 Chromium(复用登录态)
const ctx = await chromium.launchPersistentContext('.browser-profile/xhs/', {
  headless: false,  // 必须有头,用户要检查内容
  viewport: { width: 1400, height: 900 },
});

// 2. 打开创作者中心
await page.goto('https://creator.xiaohongshu.com/publish/publish');

// 3. 如果需要登录,等待用户完成
if (url.includes('login')) {
  console.log('请在浏览器中登录...');
  await page.waitForURL('**/publish/**', { timeout: 120000 });
}

// 4. 通过本地 CORS 服务器上传图片
const server = startCorsServer(xhsDir, 18899);
await page.evaluate(async ({ baseUrl, files }) => {
  // fetch → blob → File → DataTransfer → input.files
}, { baseUrl, files: pngFiles });

// 5. 填标题和正文
await page.locator('[placeholder*="标题"]').fill(title);

// 6. 等用户关闭浏览器
console.log('请检查内容后手动点击「发布」');
await new Promise(resolve => ctx.on('close', resolve));

关键特性

持久化 profile:登录态保存在 .browser-profile/xhs/ 目录,首次登录后后续不用再登。这个目录加到 .gitignore 里(含敏感信息)。

文案自动解析:从 小红书文案.md 提取最新一篇的标题、正文、标签。支持 --title 手动覆盖。

Dry-run 模式--dry-run 只检查文件和文案是否就绪,不打开浏览器。

$ node scripts/post-xhs.mjs karpathy-knowledge-vault --dry-run
 找到 6 张图片
 标题: Claude Code 搭建知识库|四个命令搞定
 正文: 笔记越攒越乱?...
 标签: #ClaudeCode #知识管理 ...
 dry-run 完成,文件和文案均就绪

三级优化回顾

这是第三次走「三级优化」路径了:

级别含义小红书截图小红书发布
Level 1命令定义流程/xhs 命令/post 命令
Level 2LLM 现场执行Claude 写 PlaywrightClaude 操作浏览器
Level 3固化为脚本xhs-screenshot.mjspost-xhs.mjs

Level 2 是验证阶段——让 Claude 用浏览器自动化跑一遍,确认流程可行。Level 3 才是生产模式——把验证过的操作写成脚本,Claude 只需要一行命令调用。

Token 消耗对比:

  • Level 2(浏览器自动化):~8 张截图 + 多次 DOM 交互 ≈ 高消耗
  • Level 3(脚本调用):一行 node 命令 ≈ 几乎零消耗

顺便装的工具

在做发布之前,顺手调研并安装了两个工具:

mcp-trends-hub:一个 MCP 服务器,聚合 20+ 平台的热搜数据(微博、知乎、抖音、B站、36kr、掘金等)。写文章前先看看什么在火,不需要 API key,直接抓公开数据。配置加到 .mcp.json 就行。

cn-content-matrix:一个 Claude Code skill,支持同一主题生成四个平台风格的内容(小红书的闺蜜分享风、公众号的专业分析风、抖音的短平快风、B站的深度技术风)。内置三级敏感词库,做合规检查很方便。

四个平台全部跑通

小红书验证完后,用同样的套路写了掘金、知乎、微信公众号的脚本。每个平台踩的坑不一样:

掘金:编辑器用的是 CodeMirror,通过 cm.CodeMirror.setValue() 注入 Markdown。第一次失败是因为编辑器异步加载,2 秒等待不够——加了轮询等待编辑器元素出现后解决。

知乎:富文本编辑器(contenteditable),需要把 Markdown 转成 HTML 再注入。登录后页面跳转会销毁 JS 执行上下文——加了 try-catch 和重新导航逻辑。

微信公众号:最难搞。编辑器是旧版 UEditor + iframe,URL 带动态 token,盲猜选择器效率极低。最终方案:从登录后的首页 URL 提取 token → 拼接编辑器 URL 直接跳转 → 在预览页 Cmd+A/Cmd+C → 切回编辑器 Cmd+V。浏览器原生粘贴反而比 JS 注入更可靠,排版完整保留。

一键全发

最后写了个 post-all.mjs 串起来:

node scripts/post-all.mjs blog/2026-04-06-xxx.md

输出:

📋 发布计划: 2026-04-06-xxx.md

🟢 小红书: ✓ 就绪
🟢 掘金: ✓ 就绪
🟢 知乎: ✓ 就绪
🟢 微信公众号: ✓ 就绪

流程: 依次打开每个平台 → 你检查并发布 → 关闭浏览器 → 下一个

四个平台依次弹出浏览器,每个自动填好内容,你检查后点发布,关闭浏览器自动进下一个。也支持 --skip wechat--only juejin,zhihu

登录态持久化

每个平台的浏览器 profile 保存在 .browser-profile/{platform}/。首次使用需要手动登录一次,之后脚本复用登录态。微信公众号的登录态有效期较短(约 24 小时),其他平台可以保持很久。

当前完整的发布流水线

写文章 /blog

生成卡片 /xhs(HTML → Playwright 截图 → PNG + 文案 + 微信 HTML)

合规检查 /post(三层敏感词扫描)

一键全发 node scripts/post-all.mjs blog/xxx.md
    ├→ 小红书: 上传图片 + 填标题正文标签
    ├→ 掘金: 填标题 + Markdown 正文
    ├→ 知乎: 填标题 + 正文
    └→ 微信: 提取 token + 跳转编辑器 + 复制粘贴 HTML

总结

核心收获:浏览器自动化是验证手段,不是生产方案

用 claude-in-chrome 跑一遍确认流程可行,然后立刻沉淀为 Playwright 脚本。这样既省 token,又更稳定——脚本不会因为 Claude 理解偏差而点错按钮。

每个平台的编辑器结构都不同,没有银弹:小红书靠 CORS 服务器绕过混合内容限制,掘金靠 CodeMirror API,知乎靠 HTML 注入,微信靠浏览器原生复制粘贴。但统一的模式是:持久化 profile + 等待编辑器加载 + 多策略探测 + 用户手动发布

M

关于作者

专注于内容创作、产品策略与设计实践。欢迎交流合作。

← 上一篇