基于 OpenCLI 浏览器自动化,在抖音创作中心发布内容。
要求 Node.js >= 21。检查版本:
node --version
npm install -g @jackwener/opencli
验证安装:
opencli doctor
本 Skill 依赖 OpenCLI 的配套 Skill,Claude Code 需要它们来理解 opencli browser 命令体系。
必装(核心):
# OpenCLI 主 Skill — 提供 opencli 全部命令知识
npx skills add jackwener/opencli
# OpenCLI 浏览器 Skill — 提供 browser 子命令参考(state/click/fill/upload/eval/wait 等)
npx skills add opencli-browser
推荐安装:
# OpenCLI 适配器开发 Skill — 需要调试/修改适配器时使用
npx skills add opencli-adapter-author
# OpenCLI 自动修复 Skill — 适配器命令失败时自动修复
npx skills add opencli-autofix
# OpenCLI 快速参考 Skill — 所有命令和站点的速查表
npx skills add opencli-usage
验证已安装的 Skill:
npx skills list
在 Chrome/Chromium 中安装 OpenCLI 扩展(Chrome Web Store 搜索 OpenCLI)。
或者手动安装:
opencli-extension-v{version}.zipchrome://extensions,启用开发者模式在已安装扩展的浏览器中打开 https://creator.douyin.com 并登录。
opencli douyin 命令)将适配器文件放入 ~/.opencli/clis/douyin/ 目录:
~/.opencli/clis/douyin/
├── article.js # 文章发布适配器
├── image-post.js # 图文发布适配器
├── _shared/
│ ├── creation-id.js
│ └── timing.js
draft.js(视频草稿)已内置在 OpenCLI 中。
OpenCLI 1.7.18 存在一个 bug:多次调用 browser upload / browser fill 时 const 变量重复声明导致 SyntaxError。
找到 OpenCLI 安装目录下的 dist/src/browser/base-page.js(全局安装通常在 {npm 全局目录}/node_modules/@jackwener/opencli/dist/src/browser/base-page.js)。
查看 npm 全局目录:
npm root -g
找到 evaluateWithArgs 方法(约第 76 行),将:
return this.evaluate(`${declarations}\n${js}`);
改为:
return this.evaluate(`(() => {\n${declarations}\nreturn (${js});\n})()`);
| 类型 | 方式 | 复杂度 |
|---|---|---|
| ------ | ------ | -------- |
| 文章 | 浏览器手动操作 / opencli douyin article | 高 — Semi Design 封面上传 |
| 图文 | 浏览器手动操作 / opencli douyin image-post | 低 — 标准文件上传 |
| 视频 | 浏览器手动操作 | 中 — 需等待上传/转码 |
opencli browser --session dy open "<url>"
如果 URL 含 &,Windows 命令行会将其截断,使用不含查询参数的基础 URL。
(function(){
var t=['我知道了','知道了','关闭','确定'];
for(var i=0;i<t.length;i++){
var b=Array.from(document.querySelectorAll('button,[role=button]')).find(function(e){
return (e.textContent||'').trim()===t[i];
});
if(b) b.click();
}
})()
(function(){
var b=Array.from(document.querySelectorAll('button')).find(function(x){
var t=(x.textContent||'').trim();
return t==='发布';
});
if(b) b.click();
})()
抖音创作中心使用 React 17+(fiber 模式),DOM 元素没有 __reactProps$。
browser fill 可正确处理 React 输入:
opencli browser --session dy fill "input[placeholder*=\"<部分占位符>\"]" "<文本>"
不要用 \n — 会被当作字面量。用 eval 注入 HTML 段落:
(() => {
var editor = document.querySelector('[contenteditable="true"][role="textbox"]');
// 图文用: document.querySelector('[contenteditable="true"]')
var html = '<p>段落一</p>' + '<p>段落二</p>';
var desc = Object.getOwnPropertyDescriptor(Element.prototype, 'innerHTML');
if (desc && desc.set) {
desc.set.call(editor, html);
} else {
editor.innerHTML = html;
}
editor.dispatchEvent(new Event('input', { bubbles: true }));
editor.dispatchEvent(new Event('change', { bubbles: true }));
})()
browser fill 对此类输入无效,用原生 setter:
var input = document.querySelector('input[type="number"][placeholder="请输入验证码"]');
var setter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value').set;
setter.call(input, '<验证码>');
input.dispatchEvent(new Event('input', { bubbles: true }));
input.dispatchEvent(new Event('change', { bubbles: true }));
# 1. 导航
opencli browser --session dy open "https://creator.douyin.com/creator-micro/content/upload"
# 2. 等待并关闭弹窗
opencli browser --session dy wait time 3
opencli browser --session dy eval "弹窗关闭代码"
# 3. 切换到图文 Tab(先用 state 查看索引)
opencli browser --session dy state
opencli browser --session dy click <N> # "发布图文"
# 4. 上传图片
opencli browser --session dy upload "input[type=file][accept*=image]" "<图片路径>"
# 5. 等待编辑器加载
opencli browser --session dy wait time 4
# 6. 填写标题
opencli browser --session dy fill "input[placeholder*=填写作品标题]" "<标题>"
# 7. 填写正文(用 eval 注入 <p> 标签,见上方)
# 8. 发布
opencli browser --session dy eval "点击发布代码"
# 9. 等待结果
opencli browser --session dy wait time 5
# 1. 导航
opencli browser --session dy open "https://creator.douyin.com/creator-micro/content/post/article"
# 2. 等待并关闭弹窗
opencli browser --session dy wait time 3
opencli browser --session dy eval "弹窗关闭代码"
# 3. 填写标题
opencli browser --session dy fill "input[placeholder*=文章标题]" "<标题>"
# 4. 填写正文(用 eval 注入 <p> 标签,见上方)
# 5. 上传封面(见下方封面上传章节)
文章页使用 Semi Design 组件,其文件输入通过 document.createElement 创建但不挂载到 DOM。必须用 monkey-patch 拦截。
第 1 步:设置拦截并点击触发按钮
(function(){
var oc=document.createElement.bind(document);
var ocl=HTMLInputElement.prototype.click;
document.createElement=function(t,o){
var e=oc(t,o);
if(t.toLowerCase()==='input') window.__ci=e;
return e;
};
HTMLInputElement.prototype.click=function(){
if(this.type==='file'){
window.__ft=this;
this.setAttribute('data-oc-cov','1');
if(!this.isConnected) (document.querySelector('#root')||document.body).appendChild(this);
return;
}
return ocl.call(this);
};
var t=Array.from(document.querySelectorAll('span')).find(function(s){
return (s.textContent||'').trim()==='点击上传封面图';
});
if(t) t.click();
})()
第 2 步:上传文件
opencli browser --session dy upload "input[data-oc-cov=\"1\"]" <封面路径>
第 3 步:触发 change 事件
(()=>{
var i=document.querySelector('input[data-oc-cov="1"]');
i.dispatchEvent(new Event('change',{bubbles:true,composed:true}));
i.dispatchEvent(new Event('input',{bubbles:true,composed:true}));
})()
第 4 步:点击"完成"(必须执行,否则封面不生效)
opencli browser --session dy wait time 3
opencli browser --session dy eval "(function(){var b=Array.from(document.querySelectorAll('button')).find(function(x){return (x.textContent||'').trim()==='完成';});if(b)b.click();})()"
发布可能触发短信验证弹窗(显示脱敏手机号 + 验证码输入框 + "获取验证码" + "验证"按钮)。
browser fill 对 type=number 无效)# 1. 导航(默认即视频 Tab)
opencli browser --session dy open "https://creator.douyin.com/creator-micro/content/upload"
# 2. 上传视频
opencli browser --session dy upload "input[type=file][accept*=video]" "<视频路径>"
# 3. 等待处理(视频需要时间)
opencli browser --session dy wait time 15
# 4. 填写标题
opencli browser --session dy fill "input[placeholder*=填写作品标题]" "<标题>"
# 5. 发布(可在上传进行中发布)
opencli browser --session dy eval "点击发布代码"
如果已安装 douyin 适配器,可以一行命令完成发布:
# 图文发布
opencli douyin image-post "<图片路径>" --title "标题" --caption "正文"
# 文章发布
opencli douyin article --title "标题" --content "正文" --cover "<封面路径>"
# 视频保存草稿
opencli douyin draft "<视频路径>" --title "标题"
适配器文件见环境搭建第 6 步。
| 现象 | 原因 | 解决方法 |
|---|---|---|
| ------ | ------ | --------- |
Extension not connected | 浏览器扩展未运行 | 确保 Chrome 已打开且扩展已启用,运行 opencli doctor 检查 |
正文 \n 显示为字面量 | 通过 eval 传文本时未用 HTML | 用 innerHTML 注入 标签 |
browser upload 报 SyntaxError | evaluateWithArgs 重复声明 const | 应用上述 base-page.js 修复 |
| 上传后封面未生效 | 没有点"完成"按钮 | 上传后必须点击"完成" |
| 验证码输入 fill 失败 | type=number 不支持 fill | 用原生 value setter 填写 |
selector_not_found | placeholder 不匹配 | 用 opencli browser --session dy state 查看当前页面 |
URL 含 & 被截断 | Windows cmd 解析问题 | 使用不含查询参数的基础 URL |
| Node API 报错 / 缺少 fetch | Node.js 版本过低 | Node.js >= 21 是强制要求 |
Unauthorized | 登录态过期 | 在浏览器中重新登录 creator.douyin.com |
共 1 个版本