Hermes 驱动 CodeArts Agent 发布华为云博客完整流程

举报
华为云训练营小助手 发表于 2026/07/08 12:25:22 2026/07/08
【摘要】 Hermes 驱动 CodeArts Agent 发布华为云博客完整流程 本文完整记录 Hermes Agent 通过 Playwright + CodeArts Agent 驱动华为云社区博客发布的全部流程、架构、16个踩坑及修复方案。 --- 一、总体架构 核心原则: 单次浏览器会话完成所有操作,不保存 cookies 不重启。 --- 二、环境准备 2.1 项目目录 2.2 依赖

Hermes 驱动 CodeArts Agent 发布华为云博客完整流程

本文完整记录 Hermes Agent 通过 Playwright + CodeArts Agent 驱动华为云社区博客发布的全部流程、架构、16个踩坑及修复方案。


一、总体架构

Hermes Agent
    │
    ├── Playwright (浏览器自动化)
    │   └── Edge 浏览器
    │       ├── 打开 bbs.huaweicloud.cn/blogs/article
    │       ├── 用户登录(手动)
    │       ├── 填充标题 / 内容 / 摘要 / 标签
    │       └── 调用 window.saveBlog(submitData)
    │
    └── CodeArts Agent CLI (码道命令行)
        └── codearts-agent chat --mode ask|agent

核心原则: 单次浏览器会话完成所有操作,不保存 cookies 不重启。


二、环境准备

2.1 项目目录

C:\Users\33808\IDEProjects\hermestest1\
├── package.json
├── publish-once.mjs          # 推荐发布脚本
├── blog-codearts-api-publish.md  # 博客内容(Markdown源文件)
└── *.mjs                     # 各种版本的历史脚本

2.2 依赖

npm install playwright

2.3 CodeArts Agent CLI

codearts-agent chat --mode ask  "只学习不执行"
codearts-agent chat --mode agent "自主执行任务"
codearts-agent chat --mode edit  "编辑代码"

注意: codearts-agent chat 退出码 0 = 消息已送达,但 stdout 为空。输出在 IDE 聊天界面而非终端。


三、发布流程(12步详解)

第1步:清理残留进程

taskkill -f -im msedge.exe 2>/dev/null
taskkill -f -im msedgewebview2.exe 2>/dev/null

反复调试会产生大量 Edge 进程(曾达 28 个),用户会被多个窗口混淆。

第2步:启动浏览器

const br = await chromium.launch({headless:false, channel:'msedge'});

必须 headless:false(用户需手动登录),使用系统 Edge。

第3步:加载页面

await pg.goto(BLOG_URL, {waitUntil:'load', timeout:30000});

必须用 waitUntil:'load',不能用 networkidle。华为云登录页有持续网络活动,networkidle 永远无法完成。

第4步:等待登录(双保险)

for(let i=0;i<300;i++){
  const u=pg.url();
  const t=await pg.evaluate(()=>!!document.querySelector('#blogTitle'));
  if(!u.includes('login')&&!u.includes('auth')&&t) break;
  if(i%30===29) await pg.goto(BLOG_URL,{waitUntil:'load',timeout:15000});
  await sleep(2000);
}

同时检查 URL 和 #blogTitle 元素存在。每 60 秒刷新一次页面。

第5步:填充标题

const ti = await pg.$('#blogTitle');
if(ti) { await ti.click(); await ti.fill(''); await ti.fill(TITLE); }

第6步:填充内容(关键!)

不要tinyMCE.activeEditor.setContent()!华为云 custom eco-tinymce.js 插件在 setContent() 内部抛出:

TypeError: Cannot read properties of undefined (reading 'map')

正确做法: 通过 iframe body 直接写入:

await pg.evaluate(h => {
  for(const f of document.querySelectorAll('iframe')) try {
    const d = f.contentDocument || f.contentWindow.document;
    const b = d.querySelector('body');
    if(b && (b.getAttribute('contenteditable')==='true'
        || b.classList.contains('mce-content-body'))) {
      b.innerHTML = h;
      if(typeof tinymce!=='undefined' && tinymce.editors?.length) {
        tinymce.editors[0].fire('change');
        tinymce.editors[0].save();
      }
      return;
    }
  } catch(e) {}
}, html);

第7步:Markdown → HTML

const lines = md.replace(/\r\n/g, '\n').replace(/\r/g, '').split('\n');

必须优先处理 Windows \r\n 换行符,否则标题正则 $ 无法匹配。支持:标题、代码块、表格、列表、引用、分隔线、加粗、行内代码、链接。

第8步:填充摘要

const intro = raw.replace(/```[\s\S]*?```/g,'')
  .replace(/[#*>`|\[\]]/g,'').replace(/\n+/g,' ').trim().substring(0,200);

第9步:填充标签(关键的坑!)

无效标签会导致 HD.92320035 product do not exist。已验证有效的标签:AI Agent华为云CodeArts大模型博客自动化华为云码道 不是有效标签。

const setter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value').set;
setter.call(inp, tagText);
inp.dispatchEvent(new Event('input', {bubbles:true}));
inp.dispatchEvent(new KeyboardEvent('keydown', {key:'Enter', bubbles:true}));
inp.dispatchEvent(new KeyboardEvent('keyup', {key:'Enter', bubbles:true}));

第10步:等待 saveBlog 就绪

let sb=false;
for(let i=0;i<30;i++){
  sb = await pg.evaluate(()=>typeof window.saveBlog==='function');
  if(sb) break;
  await sleep(2000);
}

saveBlog 是华为云博客编辑器的原生发布函数,异步加载,不能立即可用。

第11步:调用 saveBlog 发布

await pg.evaluate(() => {
  window.saveBlog({
    titleData: title,
    contentData: contentHtml,
    introData: intro,
    tagNameData: tags,
    isLock: 0,
    blogResource: 1,       // 1=原创
    isReship: 1,
    disclaimerFlag: 1,
    blogType: 0,
    isOriginal: 1,
    source: 1,
  });
});

必须传参数! 直接 saveBlog()Cannot read properties of undefined (reading 'isLock')

第12步:检测结果

for(let i=0;i<60;i++){
  if(pg.url().includes('processcomplete')) {
    console.log('🎉 发布成功!');
    break;
  }
  await sleep(1000);
}

成功标志:页面重定向到 /processcomplete?type=blog


四、API 参考

POST https://devdata.huaweicloud.cn/rest/developer/fwdu/
    rest/developer/user/hdblogservice/v1/blog/blogging

Headers:
  Content-Type: application/json
  csrf: <从 /api/get-ainfo 或 hd-csrf cookie 获取>

Body:
{
  "titleData": "标题",
  "contentData": "<p>HTML 内容</p>",
  "introData": "摘要(最多200字)",
  "tagNameData": "标签1,标签2",
  "isLock": 0,
  "blogResource": 1,
  "isReship": 1,
  "disclaimerFlag": 1,
  "blogType": 0,
  "isOriginal": 1,
  "source": 1
}

发布结果码

码值含义
HD.92300000✅ 成功
HD.92320035❌ 标签无效(最常见的坑)
HD.92311001❌ blogResource 不在 1-3
HD.92320034❌ 发布太频繁
HD.92320038❌ 含敏感词,需二次确认

五、CodeArts Agent 集成方式

发送学习指令

codearts-agent chat --mode ask \
  --add-file blog.md \
  "请学习华为云博客发布的经验..."

发送执行指令

codearts-agent chat --mode agent \
  "请运行 node publish-once.mjs 发布博客..."

注意事项

  • Agent 的 stdout 始终为空(输出在 IDE 界面),不能通过终端读取执行结果
  • --reuse-window 复用已在运行的 CodeArts 实例
  • Agent 模式下可用工具:读文件、搜索、git、终端命令

六、踩坑全记录(16个)

#问题现象解决
1发表按钮禁用按钮灰色不可点调 saveBlog() 绕过
2TinyMCE 抛错setContent() 报 map 错误iframe body 直接写入
3saveBlog 不可用调用时不存在轮询等待
4弹窗删脚本saveBlog 丢失display:none 而非 remove
5API 404请求返回 404用 devdata.huaweicloud.cn
6blogResource 越界HD.92311001限制在 1/2/3
7标签无效HD.92320035用已验证标签
8字段名错API 不识别用 titleData/contentData
9CSRF header 错403header 名用 csrf 非 hd-csrf
10cookies 过期登录超时单次会话完成
11Markdown 乱标题不渲染先转 \n
12Edge 残留多窗口混淆先 taskkill
13saveBlog 无参isLock 错误必须传参数
14推广弹窗阻断重定向发布前隐藏
15product 错误HD.92320035标签须有效
16草稿恢复失败saveId 未设置手动填充内容

七、经验总结

  1. 能调 API 就别点按钮:前端 UI 自动化有上限,后端 API 直调更可靠。
  2. 用页面原生函数window.saveBlog() 比手动 fetch() 更可靠。
  3. 标签是隐形的坑HD.92320035 的错误信息 "product do not exist" 非常误导人——实际是标签与系统 product-item 不匹配。
  4. 单次会话:不保存 cookies,不跨会话复用,避免过期问题。
  5. 先清理后启动taskkill 清理残留 Edge 进程,避免用户困惑。
  6. 日志驱动调试pg.on('response') 监听 blogging API 响应是最快定位问题的方式。

*本文由 Hermes Agent 自动生成并通过 CodeArts Agent 发布到华为云社区。* *发布时间:2026年7月8日*

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。