从 RAR 到华为云博客:AI Agent 全自动发布图文的技术实践

举报
华为云训练营小助手 发表于 2026/07/09 11:57:38 2026/07/09
【摘要】 从 RAR 到华为云博客:AI Agent 全自动发布图文的技术实践 本文详细记录了用 Hermes Agent(AI 编程助手)从微信 RAR 文件提取文章素材、自动上传图片到华为云 CDN、最终一键发布到华为云社区博客的全过程,以及过程中遇到的 23 个坑与解决思路。 --- 一、背景 收到同事分享的一个 case-article.rar 文件,里面是一篇关于「用华为云码道 CLI/TUI

从 RAR 到华为云博客:AI Agent 全自动发布图文的技术实践

本文详细记录了用 Hermes Agent(AI 编程助手)从微信 RAR 文件提取文章素材、自动上传图片到华为云 CDN、最终一键发布到华为云社区博客的全过程,以及过程中遇到的 23 个坑与解决思路。


一、背景

收到同事分享的一个 case-article.rar 文件,里面是一篇关于「用华为云码道 CLI/TUI 开发幸运跑马灯抽奖网页」的实践案例文章,含 8 张操作截图。需求:读取 RAR → 提取 Markdown + 图片 → 发布到华为云社区博客

目标很明确,但坑全在路上。下面用「发生了什么 → 怎么解决的」的方式记录每个环节。


二、完整流程总览

微信 RAR → 解压 → 读取 Markdown / PNG 图片
         → 启动 Edge 浏览器
         → 打开华为云博客编辑器
         → 获取 CSRF Token
         → 获取上传授权码 (auth_code)
         → 8 张图片逐一上传 FileServer (获得 CDN URL)
         → Markdown 转 HTML (嵌入 CDN URL)
         → 填充标题 / 内容 / 摘要 / 标签
         → 调用 window.saveBlog() 发布
         → 检测 /processcomplete 重定向确认成功

三、分步骤详解

3.1 解压 RAR 文件

Windows 没有预装 unrar / 7z,GitHub 下载被墙。解决:通过 npm 安装 win-7zip 包,其中自带 7z.exe。

npm install -g win-7zip
/c/Users/33808/AppData/Roaming/npm/node_modules/win-7zip/7zip-lite/7z.exe \
  x "D:\...\case-article.rar" -o"D:\extracted" -y

3.2 启动浏览器并等待登录

使用 Playwright + Edge 浏览器:

const br = await chromium.launch({ headless: false, channel: 'msedge' });
const pg = await br.newPage();
await pg.goto('https://bbs.huaweicloud.cn/blogs/article', { waitUntil: 'load' });

:必须用 waitUntil: 'load' 而非 networkidle,华为云登录页有持续的心跳请求。

3.3 图片上传(最曲折的部分)

尝试 A:TinyMCE 粘贴自动上传 ❌

在编辑器中插入 base64 data URL 图片,期望 TinyMCE 自动上传到 CDN。等了 60 秒没反应。原因是华为云的 TinyMCE 没有配置 images_upload_handler

尝试 B:WebUploader UI 上传 ❌

找到了页面中的文件输入框 input.webuploader-element-invisible,用 Playwright 的 setInputFiles() 选择文件。WebUploader 确实发起了上传,但图片没有插入到编辑器中。

尝试 C:直接调用 FileServer API ✅

拦截 WebUploader 的网络请求,发现了完整的 API 链:

Step 1:获取 CSRF Token

华为云的 CSRF cookie 是 HttpOnly 的(document.cookie 不可见)。通过 Playwright 的 page.route() 拦截 WebUploader 的真实请求:

await page.route('**/bisic/get-auth-code', async (route) => {
  const headers = route.request().headers();
  csrfToken = headers['csrf'];
  await route.continue();
});

Step 2:获取上传授权码

POST https://devdata.huaweicloud.cn/rest/developer/fwdu/rest/developer/user/hdblogservice/v1/bisic/get-auth-code
Content-Type: application/json
csrf: <captured_token>

{"scene_type": "1", "file_postfix": "png"}

坑 1:必须用 POST,GET 返回 HD.92311001 parameter is error

坑 2:必须传 JSON body {"scene_type":"1","file_postfix":"png"},空 body 返回 HD.92309999 internal error

Step 3:上传文件到 FileServer

POST https://fileserver.developer.huaweicloud.cn/FileServer/uploadFile
Content-Type: multipart/form-data

file: <binary>
authCode: <from step 2>

:参数名是 authCode(驼峰),不是 auth_code 也不是 authcode。用错返回 HD.77701201 Required request parameter 'authCode'

Step 4:获得 CDN URL

{
  "result": {
    "resultCode": "0",
    "UploadFileRsp": {
      "fileInfoList": [{
        "fileDestUlr": "https://fileserver.developer.huaweicloud.cn/FileServer/getFile/...png"
      }]
    }
  }
}

重复 8 次,得到全部图片的 CDN URL。

3.4 Markdown 转 HTML

自己写了一个轻量级 Markdown 解析器,支持:

  • # 标题
  • ` 代码块
  • | 表格
  • - 无序列表 / 1. 有序列表
  • > 引用
  • --- 分隔线
  • bold / ` code / link`
  • [图:alt] 图片(替换为 CDN URL)

关键:先统一处理 Windows 的 \r\n 换行符(坑:不处理的话标题正则匹配不到)。

3.5 填入编辑器并发布

标题

Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value').set 设值,绕过 UI 点击被弹窗拦截的问题。

内容

绕过 TinyMCE API(它会抛 TypeError: Cannot read properties of undefined (reading 'map')),直接写入 iframe body:

for (const f of document.querySelectorAll('iframe')) {
  const d = f.contentDocument || f.contentWindow.document;
  const b = d.querySelector('body');
  if (b && b.getAttribute('contenteditable') === 'true') {
    b.innerHTML = html;
    if (typeof tinymce !== 'undefined' && tinymce.editors?.length) {
      tinymce.editors[0].fire('change');
    }
  }
}

摘要

#summarytextarea(HTMLTextAreaElement),不是 HTMLInputElement。用 input 的 setter 会报 Illegal invocation。直接用 s.value = t 即可。

标签

模拟 Enter 事件需要同时传 key: 'Enter'keyCode: 13(部分 tagator 实现只认 keyCode)。

发布

调用页面的原生发布函数:

window.saveBlog({
  titleData: title,
  contentData: html,
  introData: intro,
  tagNameData: tags,
  isLock: 0,
  blogResource: 1,
  isReship: 1,
  disclaimerFlag: 1,
  blogType: 0,
  isOriginal: 1,
  source: 1,
});

检测成功:页面 URL 重定向到 /processcomplete?type=blog


四、23 个踩坑全记录

#问题现象原因解决
1发表按钮禁用灰色不可点前端验证不感知 API 注入调 saveBlog() 绕过
2TinyMCE 抛错setContent() 报 map 错误eco-tinymce.js 插件 bugiframe body 直接写入
3saveBlog 不可用调用时 undefined异步加载轮询等待(30 次×2s)
4弹窗遮挡点击超时 30s.developer-modal 拦截 pointer eventsdisplay:none 事先隐藏
5API 404请求 404用了 bbs 域名用 devdata.huaweicloud.cn
6blogResource 越界HD.92311001值不在 1-3限制 1=原创
7标签无效HD.92320035非有效 product-item用已验证标签
8字段名错API 不识别title 非 titleData用正确字段名
9CSRF header 错403 no request_csrfheader 名应为 csrf用 csrf 非 hd-csrf
10cookies 过期登录跳转会话短单次会话完成
11Markdown 乱标题不渲染\r\n 未处理先转 \n
12Edge 进程残留多窗口混淆反复重启先 taskkill
13saveBlog 无参isLock 错误未传 submitData必须传完整参数
14推广弹窗阻断重定向登录后推广界面发布前隐藏
15product 错误HD.92320035标签无效用 AI Agent,华为云
16草稿恢复失败saveId 未设置CSRF 校验失败手动填充内容
17摘要 type 错误Illegal invocation#summary 是 textarea直接 s.value = t
18图片自动上传失败无 CDN URLTinyMCE 无 upload handlerFileServer API 直调
19弹窗拦截点击click() 超时modal-cover 遮挡display:none + evaluate
20标签 Enter 事件标签不生成缺 keyCode同时传 key + keyCode
21get-auth-code 需 POSTHD.92311001默认用 GET改为 POST + JSON body
22参数名需驼峰HD.77701201auth_code 非 authCode用 authCode
23CSRF token 不可读403HttpOnly cookieroute 拦截 WebUploader 请求

五、最终效果

  • 文章:「用华为云码道 CLI/TUI 从零开发「幸运跑马灯抽奖」网页应用」
  • 正文:6,849 字符 Markdown → 10,705 字符 HTML
  • 图片:8 张截图全部上传到华为云 CDN
  • 标签:AI Agent, 华为云, CodeArts, 大模型
  • 发布状态:✅ 成功

六、经验总结

  1. 能调 API 就别点按钮:前端 UI 自动化有上限,后端 API 直调更可靠。发表用 saveBlog(),图片用 FileServer API。
  1. 用页面原生函数window.saveBlog() 比手动 fetch() 更可靠(自动处理 CORS、CSRF、状态管理)。
  1. CSRF 是隐形杀手:HttpOnly cookie 不可 JS 读取,但通过 page.route() 拦截可获取。正确 CSRF 是一切 API 调用的前提。
  1. 先粗后精调试:先发布纯文字版确认流程通顺,再补图片。避免图片上传失败拖垮整体发布。
  1. evaluate 替代点击:弹窗遮挡 + 按钮禁用使 page.click()/fill() 不可靠。用 page.evaluate() 通过 DOM setter 直接设值更稳定。
  1. POST body 不能省get-auth-code API 看似简单,但 scene_typefile_postfix 缺一不可。
  1. 参数命名是细节魔鬼authCode 不是 auth_codetitleData 不是 title。一个字母差就是 API 不识别。

七、相关资源

  • 华为云博客:https://bbs.huaweicloud.cn/blogs
  • 码道 CLI 文档:https://support.huaweicloud.cn/usermanual-cli/codeartsagent_cli_0001.html
  • Playwright:https://playwright.dev
  • 最终发布脚本upload-all.mjs(捕获 CSRF → 上传图片 → saveBlog 发布 全自动)

本文本身也是通过 Hermes Agent 自动发布的——即用本文描述的方法发布了这篇文章。这是一种递归验证(笑)。

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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