CodeArts Agent实战:API直调发布华为云博客的踩坑与修复

举报
华为云训练营小助手 发表于 2026/07/08 11:46:24 2026/07/08
【摘要】 CodeArts Agent实战:API直调发布华为云博客的踩坑与修复 本文记录了使用华为云码道(CodeArts)代码智能体,通过 Playwright 浏览器自动化 + API 逆向分析,实现博客自动发布的完整过程。详细记录了从 UI 自动化到 API 直调的演进中遇到的 6 个关键问题及修复方案。 --- 背景 在上一篇博客 用 AI Agent 自动发布华为云博客:从踩坑到成功的完整实

CodeArts Agent实战:API直调发布华为云博客的踩坑与修复

本文记录了使用华为云码道(CodeArts)代码智能体,通过 Playwright 浏览器自动化 + API 逆向分析,实现博客自动发布的完整过程。详细记录了从 UI 自动化到 API 直调的演进中遇到的 6 个关键问题及修复方案。


背景

在上一篇博客 [用 AI Agent 自动发布华为云博客:从踩坑到成功的完整实战](https://bbs.huaweicloud.cn/blogs/481268) 中,我们实现了基于 Playwright UI 自动化 + 后端 API 直调的博客发布方案。

但在后续的实践中,将这篇博客整理成 Markdown 后再次发布时,遇到了新的问题——UI 自动化踩过的坑在 API 直调时又换了一种形式出现。本文记录了再次踩坑与修复的完整过程。


整体流程

用户登录 → CSRF Token获取 → Markdown转HTML → 构造请求体 → 调用API发布

踩坑记录

坑1:TinyMCE 内容注入后发表按钮仍然禁用

问题: 使用 tinyMCE.activeEditor.setContent() 注入 Markdown 内容后,#submit-btn 按钮始终带有 write-blog-publish-btn-no 禁用样式类,无法点击。

原因: 华为云博客编辑器的前端验证逻辑无法感知通过 TinyMCE API 设置的内容和标签。编辑器内部维护了一套独立的状态管理,直接操作 DOM 无法触发验证状态更新。

尝试过的方案:

  • 手动移除禁用 CSS 类 → 按钮可点击但不触发提交
  • 触发 changeinput 事件 → 无效
  • 调用 tinyMCE.activeEditor.save() → 无效

最终方案: 放弃前端 UI 交互,改为直接调用后端发布 API。这是最彻底的解决方案。


坑2:Markdown 格式错乱

问题: 将 Markdown 原文直接传入 TinyMCE 后,代码块显示为单反引号、列表未格式化、表格显示为纯文本、标题未渲染。

原因: TinyMCE 接收的是 HTML 而非 Markdown。直接传递 bold## Title 这类 Markdown 语法,编辑器不会自动转换。

修复: 编写完整的 Markdown → HTML 解析器,逐行解析:

标题 (# → <h1-6>)
代码块 (``` → <pre><code>)
表格 (| → <table><th><td>)
列表 (-/1. → <ul>/<ol><li>)
引用 (> → <blockquote>)
行内格式 (** → <strong>, ` → <code>)
分隔线 (--- → <hr>)
链接/图片 ([text](url) → <a>/<img>)

特别注意 Windows \r\n 换行符问题:split('\n') 后每行末尾残留 \r,导致标题正则 /^(#{1,6})\s+(.+)$/ 中的 $ 无法匹配。需在解析前统一处理:

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

坑3:API 域名错误导致 404

问题: 调用发布 API 返回 404。

POST https://bbs.huaweicloud.cn/rest/developer/fwdu/... → 404

原因: 登录后的页面域名为 bbs.huaweicloud.cn,但博客发布 API 的服务端点在 devdata.huaweicloud.cn 域名下。两个域名指向不同的后端服务。

修复: 将 API 请求域名硬编码为 https://devdata.huaweicloud.cn

正: https://devdata.huaweicloud.cn/rest/developer/fwdu/... → 200
误: https://bbs.huaweicloud.cn/rest/developer/fwdu/... → 404

坑4:CSRF Token 缺失导致 403

问题: 域名修正后,API 返回 403。

{"error":"no request_csrf found"}

原因: 华为云的 API 要求在请求头中携带 CSRF Token,用于防跨站请求伪造。初始脚本未携带任何 CSRF 信息。

修复: 从浏览器 Cookie 中提取 CSRF Token:

const cookies = await context.cookies();
const csrfCookie = cookies.find(c =>
  c.name === 'csrf' || c.name === 'hd-csrf');
const csrfToken = csrfCookie ? csrfCookie.value : '';

然后将 Token 放入请求头:

headers: {
  'Content-Type': 'application/json',
  'csrf': csrfToken,
}

关键细节: Cookie 的名称是 hd-csrf,但请求头的字段名是 csrf(不是 hd-csrf)。使用错误的 header 名称同样会返回 no request_csrf found


坑5:API 请求体字段名

问题: 构造请求体时,直观地使用 titlecontentlabel 作为字段名,但 API 返回错误。

修复: 通过逆向分析前端 JS 源码 window.saveBlog.toString(),找到正确的字段名映射:

前端显示API 字段名
标题titleData
正文 HTMLcontentData
摘要introData
标签tagNameData
是否锁定isLock: 0
是否原创isOriginal: 1
资源来源blogResource: 1
允许转载isReship: 1

坑6:浏览器登录等待超时

问题: page.waitForURL() 等待登录跳转时,如果登录后页面 URL 未按预期变化,会抛出 Timeout 异常。

修复: 改用轮询机制,同时检查 URL 变化和 DOM 元素存在:

for (let attempt = 0; attempt < 120; attempt++) {
  const u = page.url();
  // 检查 URL 是否已离开登录页
  if (!u.includes('login') && !u.includes('passport')) {
    loggedIn = true; break;
  }
  // 同时检查编辑器元素是否出现
  const hasEditor = await page.evaluate(() =>
    !!document.querySelector('#blogTitle'));
  if (hasEditor) { loggedIn = true; break; }
  await sleep(2000);
}

最终方案

完整的自动发布流程如下:

步骤

  1. Playwright 启动 Edge 浏览器,导航到博客发布页
  2. 用户手动登录华为云账号
  3. 提取 CSRF Token(从 hd-csrf Cookie)
  4. Markdown → HTML 转换(逐行解析,支持完整语法)
  5. 构造请求体(使用正确的 API 字段名 titleData/contentData/introData/tagNameData
  6. 发送 POST 请求https://devdata.huaweicloud.cn/rest/developer/fwdu/rest/developer/user/hdblogservice/v1/blog/blogging
  7. 解析响应,提取 blogId,验证发布结果

核心代码

const submitData = {
  titleData: title,
  contentData: contentHtml,
  introData: introText.substring(0, 200),
  tagNameData: 'AI Agent,华为云,大模型',
  isLock: 0,
  blogResource: 1,
  isReship: 1,
  disclaimerFlag: 1,
  blogType: 0,
  isOriginal: 1,
  source: 1,
};

const resp = await fetch(apiUrl, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'csrf': csrfToken,
  },
  body: JSON.stringify(submitData),
  credentials: 'include',
});

成功响应

{
  "code": "HD.92300000",
  "msg": "success",
  "blogId": "9fbb669737044bbd983572ce6d9b2025"
}

经验总结

  1. UI 自动化有上限:当组件内部状态与 DOM 不同步时,直接操作 DOM 往往无效。此时应转向 API 层面。
  2. Cookie 名 ≠ Header 名:CSRF 的 Cookie 名为 hd-csrf,但 HTTP Header 名为 csrf。两者不同,需要仔细区分。
  3. API 域名可能不同于页面域名bbs.huaweicloud.cn 是前端展示域,devdata.huaweicloud.cn 是后端 API 域。
  4. 逆向 JS 源码:通过 function.toString() 或搜索页面内嵌脚本,可以快速定位 API 端点、字段名和参数格式。
  5. Windows 换行符坑\r\n 会导致 Markdown 解析器的正则失效,务必先统一换行符。
  6. Markdown 转 HTML 需要逐行解析:简单的正则替换无法正确处理多层嵌套结构(如代码块内的 Markdown 语法)。

完整代码

完整脚本已开源在项目目录:

  • C:\Users\33808\IDEProjects\hermestest1\publish-api.mjs — API 直调版
  • C:\Users\33808\IDEProjects\hermestest1\playwright-publish.mjs — UI 自动化版

运行方式:

cd C:\Users\33808\IDEProjects\hermestest1
npm run api       # API 直调版(推荐)
npm run agent     # UI 自动化版

总结

从最初的 Playwright UI 自动化,到最终的后端 API 直调,这个过程展示了当前端自动化遇到瓶颈时,如何通过 API 逆向分析找到根本解决方案。6 个坑涵盖了域名、认证、数据格式、状态同步等多个维度,是 Web 自动化实战的典型案例。

最终实现的 API 直调方案稳定可靠,无需处理 UI 状态同步问题,是博客自动发布的推荐方式。


*本文由 CodeArts Agent 协助撰写并自动发布到华为云社区。* *发布时间:2026年7月8日*

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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