☰
AI Agent 自主发稿实战:browser-skill 227 次操作与 9 个坑复盘
2026/10/8 11:15:07 网站建设 项目流程

1. 项目缘起与整体设计思路

1.1 为什么要让 AI 自己去社区发稿

先说清楚这个项目到底在干什么。简单讲,我搭了一套基于browser-skill(后面简称bsk)的自动化流程,让一个 AI Agent 自己打开浏览器,登录腾讯云社区,完成从选题、写稿、排版、上传封面到点击发布的全流程。整个过程没有人工干预,Agent 一共执行了227 次操作,耗时4.3 小时,踩了9 个坑,最终把稿子发出去了。

你可能会问,发一篇文章而已,手动复制粘贴十分钟的事,为什么要折腾四个多小时?这个问题我在动手之前也问过自己。答案在于:我真正想验证的不是"能不能发一篇文章",而是"AI 能不能独立完成一个需要跨多个界面、处理多种交互、应对各种意外情况的端到端任务"。发稿只是一个载体,它天然包含了登录态维持、富文本编辑、文件上传、表单提交、状态确认这几个典型环节,几乎覆盖了 Web 自动化的所有难点。把这套流程跑通,意味着同样的能力可以迁移到任何"需要人坐在浏览器前点来点去"的场景。

适合读这篇复盘的人有三类:一是正在做浏览器自动化、想了解真实项目里会遇到什么问题的开发者;二是对 AI Agent 落地感兴趣、想知道当前能力边界在哪的产品或技术负责人;三是单纯好奇"让 AI 自己干活"到底靠不靠谱的同行。不管你是哪一类,我都会把每一步的操作意图、参数选择、踩坑细节讲透,让你能直接抄作业。

1.2 技术选型:为什么是 browser-skill 而不是别的方案

做浏览器自动化,市面上的路子无非几条:纯 Selenium/Playwright 脚本、基于 CDP 的底层控制、或者像 bsk 这种把浏览器操作封装成"技能"给 Agent 调用的方案。我选browser-skill的核心理由是它和 Agent 的协作模式最自然。

传统的 Playwright 脚本,你得把每一步都写死:找到这个元素、点它、等它加载、再找下一个。问题是腾讯云社区的页面结构会变,弹窗会出现,加载速度会波动,写死的脚本极其脆弱。而 bsk 的思路是把"点击""输入""截图""读取页面"这些原子操作暴露给 Agent,由 Agent 根据当前页面状态自己决定下一步做什么。这就像一个是照着菜谱做菜,一个是给你一口锅和一堆食材让你自由发挥——后者显然更能应对意外。

具体到工具链,我用的是browser-skill作为浏览器控制层,配合一个具备视觉理解能力的模型来"看"页面截图并做决策。这里有个关键取舍:要不要让模型直接读 DOM?我的结论是截图为主、DOM 为辅。原因很实在——DOM 里全是 class 名和嵌套结构,模型读起来又长又容易迷失;而截图是"所见即所得",模型看到按钮在哪就能点哪,更接近人的操作方式。只有在需要精确定位输入框、读取表单值时,才去查 DOM。

提示:选型阶段最容易犯的错是追求"全自动无脑跑"。实际上给 Agent 保留一定的"观察-决策"空间,比写死流程的鲁棒性高得多,代价是 token 消耗和耗时增加,这个后面会细说。

1.3 整体流程拆解:227 次操作都花在哪了

把 4.3 小时、227 次操作拆开看,大致分布是这样的:

阶段操作次数(约)耗时占比主要动作
启动与环境准备155%打开浏览器、加载登录态、进入社区
登录态确认208%检查是否已登录、处理可能的验证
进入创作页124%导航到写文章入口
正文撰写与排版9040%输入标题、正文、调整格式
封面上传3518%选择文件、等待上传、确认预览
分类标签设置2512%选择专栏、填标签
发布与确认3013%点发布、处理弹窗、确认成功

可以看到,正文撰写与排版吃掉了四成时间,封面上传是第二大耗时项。这两个数字很说明问题:AI 写内容本身不慢,慢在"把内容塞进富文本编辑器"和"处理文件上传这种涉及系统对话框的操作"。这两块恰恰是后面踩坑最密集的地方。

2. 核心细节解析与实操要点

2.1 登录态维持:别每次都从头登

整个流程能不能跑起来,第一道坎就是登录。腾讯云社区要发稿必须登录,而登录往往涉及验证码、短信、扫码这些自动化极难处理的环节。我的做法是复用已有的浏览器用户目录,让 Agent 启动时就带着已登录的 Cookie 和本地存储。

具体操作上,bsk 启动浏览器时指定一个持久化的userDataDir,这个目录里保存着之前手动登录过一次的会话信息。这样 Agent 打开社区页面时,直接就是登录状态,省掉了整个登录流程。这个技巧看起来简单,但它是整个项目能"无人值守"的前提。

# 启动时指定持久化用户目录(示意) browser-skill launch --user-data-dir=/path/to/profile --headless=false

这里有个细节要注意:不要用无头模式。虽然无头模式跑得快,但很多社区页面会检测无头特征,而且无头模式下截图和实际渲染可能有差异,导致 Agent "看到"的页面和真实的不一样。我实测下来,带界面跑虽然慢一点,但稳定性高出一大截。

注意:登录态是有有效期的。我这次跑的时候登录态还在,但如果隔太久 Cookie 过期,Agent 会卡在登录页反复尝试。稳妥的做法是在流程开头加一个"登录态检查"步骤,发现没登录就停下来报警,而不是硬着头皮往下走。

2.2 富文本编辑:execCommand 是把双刃剑

正文输入是整个项目最核心也最折腾的部分。腾讯云社区的编辑器是富文本编辑器,不是简单的 textarea。你直接往里面塞纯文本,格式全丢;你想加粗、加标题、插代码块,就得跟编辑器的 API 打交道。

我一开始尝试的是模拟键盘输入,一个字一个字敲。结果发现两个问题:一是慢,一篇两千字的文章敲下来要好几分钟;二是容易丢字,编辑器在快速输入时会漏掉字符。后来改用execCommand来操作,效率高了很多。

execCommand是浏览器提供的一个老 API,虽然已经标记为废弃,但在富文本编辑器里依然好用。它的核心用法是:

// 在编辑器获得焦点后执行 document.execCommand('insertText', false, '要插入的文本'); document.execCommand('formatBlock', false, 'h2'); // 设置标题级别 document.execCommand('bold', false, null); // 加粗

用insertText一次性插入整段文字,比逐字敲快得多,也不容易丢字。设置标题、加粗这些格式,用formatBlock和bold命令,比去点工具栏按钮可靠——工具栏按钮的位置会变,而命令是稳定的。

但 execCommand 有个大坑:它依赖编辑器的焦点状态。如果编辑器没获得焦点,命令执行了也没反应,而且不报错。我踩的第一个坑就是这个——Agent 执行了插入命令,页面看起来没变化,它以为成功了,继续往下走,结果正文是空的。解决办法是在每次执行命令前,先点击编辑器区域确保获得焦点,执行后再截图确认内容真的进去了。

2.3 封面上传:upload 环节的隐藏陷阱

封面上传是我认为整个流程里最"反自动化"的一环。原因在于,点击"上传封面"按钮后,弹出的往往是系统级的文件选择对话框,而不是网页内的元素。系统对话框是操作系统的,浏览器自动化工具根本碰不到它。

解决这个问题的标准做法是:不要点那个触发系统对话框的按钮,而是直接找到页面里的<input type="file">元素,往它上面设置文件路径。这个 input 元素通常被隐藏了,但它在 DOM 里是存在的。

// 找到隐藏的文件输入框并设置文件 const fileInput = document.querySelector('input[type="file"]'); // 通过 bsk 的文件上传能力,把本地文件路径绑定到这个 input

bsk 提供了直接给 file input 设置文件的能力,绕过了系统对话框。这一步的关键是先定位到正确的 input。有些页面有多个 file input(比如头像上传、附件上传),得根据上下文找到封面那个。我的做法是先截图看页面上有几个上传入口,再结合 DOM 里 input 的accept属性(封面通常是image/*)来筛选。

上传之后还有一步容易忽略:等待上传完成并确认预览。文件选中不代表上传成功,尤其是图片较大的时候,需要等服务器返回。Agent 必须截图确认封面上出现了图片预览,才能继续。我在这里踩过坑——没等上传完就点了发布,结果发出去的文章没有封面。

2.4 分类与标签:看似简单实则磨人

选专栏、填标签这部分,操作本身不难,但特别磨人。腾讯云社区的发布表单里,专栏是一个下拉或弹层选择,标签是输入后从联想列表里选。这两块的共同问题是:选项是动态加载的,而且位置不固定。

我的处理策略是"先读后选":先截图或读 DOM,把当前可选的专栏、标签列出来,让 Agent 从中挑一个匹配的,再去点击。而不是盲目地按坐标点。标签输入后会出现联想下拉,需要等下拉出现、再点中匹配项,这个"等待"很关键,点早了下拉还没出来,点了个寂寞。

实操心得:凡是涉及"输入后出现联想列表"的场景,都要在输入和点击之间加一个"等待并截图确认列表出现"的步骤。这个等待时间不用写死,让 Agent 看到列表出现了再点,比 sleep 固定秒数靠谱得多。

3. 实操过程与核心环节实现

3.1 环境准备与启动参数

正式开跑之前,环境准备有几个必须确认的点。首先是浏览器版本和 bsk 的兼容性,我用的是较新的 Chromium 内核,bsk 版本要与之匹配,否则连接会失败。其次是用户目录的路径,要确保有读写权限,且这个目录没有被其他浏览器实例占用——同一个 userDataDir 不能同时被两个进程打开,否则会报锁冲突。

启动参数上,除了前面说的user-data-dir和关闭无头模式,我还加了窗口尺寸的设置。默认窗口可能很小,导致页面元素挤在一起,截图里按钮都看不清。我把它设成 1440x900,接近常见笔记本分辨率,页面布局正常,Agent 看截图也清楚。

browser-skill launch \ --user-data-dir=/path/to/profile \ --headless=false \ --window-size=1440,900

启动后第一件事不是直接冲进社区,而是先打开一个空白页,截图确认浏览器正常、Agent 能拿到画面。这一步是"冒烟测试",花几秒钟,能避免后面因为环境问题白跑半天。

3.2 正文撰写的完整操作序列

正文撰写我拆成了几个明确的子步骤,每个子步骤都以"截图确认"收尾。这个"操作-确认"的循环是整个项目稳定性的关键,虽然增加了操作次数,但避免了错误累积。

第一步是定位标题输入框并填入标题。标题框通常是页面上第一个明显的输入框,Agent 截图后能识别出来。填入标题后截图,确认文字出现在框里。

第二步是点击正文编辑区,确保获得焦点。这一步不能省,前面说过 execCommand 依赖焦点。点击后截图,看光标是否出现。

第三步是分段插入正文。我没有一次性把整篇文章塞进去,而是按段落来,每插一段截图确认一次。这样做的好处是,万一某段插入失败,能立刻发现并重试,而不是等到最后才发现正文缺了一大块。代价是操作次数多,但值得。

第四步是处理格式。标题用formatBlock设成 h2/h3,代码块用编辑器的代码块功能(有些编辑器有专门的插入代码按钮,需要点它而不是 execCommand),加粗用bold。每处理一种格式,截图确认渲染效果。

这里有个细节:代码块的处理要特别小心。富文本编辑器对代码块的支持各不相同,有的用<pre>,有的用自定义组件。我这次遇到的情况是,直接 execCommand 插入的代码没有语法高亮,得用编辑器工具栏里的"代码块"按钮。于是流程里加了一步:先点代码块按钮,再往生成的块里插入代码文本。

3.3 封面上传的完整流程与参数

封面上传我总结成"四步确认法":

  1. 定位上传入口:截图看页面,找到封面区域的上传按钮或占位区。
  2. 绑定文件到 input:通过 DOM 找到对应的input[type="file"],用 bsk 的文件能力设置本地图片路径。图片我提前准备好,尺寸控制在社区推荐的范围内(一般宽度 1200px 左右比较合适,太大上传慢,太小显示模糊)。
  3. 等待上传完成:设置文件后,截图轮询,直到封面上出现图片预览。这个等待我设了最长 30 秒,超时就报警。
  4. 确认预览正确:截图确认预览图就是我要的那张,没有传错或显示异常。
// 伪代码示意:绑定文件并等待 await bsk.setFileInput('input[type="file"][accept*="image"]', '/path/to/cover.png'); // 轮询截图直到出现预览 await bsk.waitForVisual('封面预览区域出现图片', { timeout: 30000 });

这里踩的坑是:有些页面的 file input 是动态创建的,你一开始在 DOM 里找不到它,得先点一下上传按钮(但又不触发系统对话框的那种点法),input 才会出现。我的应对是先尝试直接找 input,找不到就点一下上传区域再找。这个"先找后点"的逻辑,比死等某个元素出现灵活。

3.4 发布确认与状态校验

所有内容填好后,最后一步是点发布。但"点发布"不等于"发布成功"。腾讯云社区点发布后可能弹确认框,也可能直接跳转到文章页。Agent 需要判断当前处于哪个状态。

我的做法是:点发布后截图,如果出现确认弹窗,就点确认;如果跳转到了文章详情页,就说明成功了。判断成功的标志是页面上出现了文章标题和正文内容。这一步的校验很重要,因为有时候发布按钮点了没反应(比如某个必填项没填),Agent 如果不校验就会误以为成功。

注意:发布前一定要做一次"全表单校验"。我这次就遇到过一次,标签没选,点发布后页面提示"请选择标签",但提示很隐蔽,Agent 差点没看到。后来我在发布前加了一步:截图检查所有必填项是否都有值,确认无误再点发布。

4. 九个坑的完整复盘与排查技巧

4.1 坑一至坑三:焦点、丢字与静默失败

坑一:编辑器焦点丢失导致输入无效。前面提过,execCommand 不报错但没效果。排查方法是每次输入后截图,看内容有没有进去。解决方法是输入前先点击编辑区。

坑二:快速输入丢字。逐字模拟键盘输入时,编辑器处理不过来会漏字符。改用insertText一次性插入整段后解决。

坑三:静默失败最难查。有些操作执行了,工具返回成功,但页面没变化。这类问题只能靠"操作后截图确认"来兜底。我后来养成了习惯:任何关键操作后都截图,不信任工具的返回值,只信任画面。

4.2 坑四至坑六:上传、等待与元素定位

坑四:系统文件对话框无法操作。这是 upload 环节的经典问题,解法是绕过按钮直接操作 file input。

坑五:上传未完成就继续。表现为发布后没封面。解法是轮询截图等预览出现。

坑六:元素定位靠坐标不稳。页面滚动、弹窗都会让坐标失效。解法是尽量用 DOM 选择器或视觉识别定位,少用绝对坐标。

4.3 坑七至坑九:弹窗、标签与状态误判

坑七:意外弹窗遮挡操作。比如"是否离开页面"的提示。解法是每次操作前先截图看有没有弹窗,有就先关掉。

坑八:标签联想列表点不中。输入后列表还没出来就点,点空了。解法是输入后等列表出现再点。

坑九:发布状态误判。点了发布以为成功,其实失败了。解法是发布后校验页面是否出现文章内容。

4.4 常见问题速查表

问题现象可能原因排查方法解决技巧
输入后内容为空编辑器未获焦点截图看光标输入前点击编辑区
正文缺字漏段输入太快对比预期与实际分段插入并确认
操作成功但无变化静默失败操作后截图不信任返回值,只信画面
上传无反应碰到系统对话框看是否弹出系统窗口直接操作 file input
发布后无封面上传未完成检查预览区轮询等待预览出现
点击无效果元素位置变了重新截图定位用选择器而非坐标
标签选不中联想列表未出现看列表是否渲染输入后等待再点
发布失败必填项缺失检查表单发布前全表单校验

5. 效率与成本的真实账本

5.1 4.3 小时到底值不值

先把账算清楚。4.3 小时里,真正"干活"的时间其实不多,大部分耗在等待和确认上。每次操作后的截图、模型对截图的推理、等待页面响应,这些加起来占了七成以上。如果换成人工,同样的发稿操作熟练的话十五分钟能搞定。

那这 4.3 小时值不值?取决于你怎么看。如果只看"发一篇文章"这个结果,显然不值。但如果看"验证了一套可复用的自动化能力",那这 4.3 小时买到的是经验——我知道了哪些环节 AI 能独立搞定,哪些环节必须加人工兜底,哪些坑是必然会踩的。这些经验迁移到别的任务上,能省下大量重复试错的时间。

5.2 227 次操作背后的 token 消耗

227 次操作,意味着至少 227 次截图和模型推理。每次截图传给模型、模型分析后返回决策,都是一次 token 消耗。截图分辨率越高,token 越多。我一开始用全屏高清截图,token 消耗很快;后来改成只截关键区域,消耗降了不少。

这里有个平衡:截图太小,模型看不清细节,容易误判;截图太大,token 烧得快。我的经验是,关键操作区域单独截,全屏截图只在需要判断整体状态时用。比如填表单时只截表单区域,判断是否发布成功时才截全屏。

实操心得:如果你的预算有限,优先保证"关键节点"的截图质量,中间过程可以适当降低频率。但"操作后确认"这一步千万别省,省下来的 token 最后都会以"返工重跑"的形式加倍还回去。

5.3 稳定性与速度的取舍

整个项目里我反复在做的一个权衡就是:要快还是要稳。快意味着少截图、少等待、批量操作;稳意味着多确认、多等待、小步走。我最终选择了偏稳的方案,因为发稿这种任务,失败重来的成本比慢一点高得多。

具体体现:正文分段插入而不是一次性插入,每段确认;上传后轮询等待而不是固定 sleep;发布前全表单校验而不是直接点。这些选择让操作次数从预估的一百多次涨到了 227 次,但换来的是最终一次成功,没有中途崩掉重来。

6. 这套方案还能怎么扩展

6.1 迁移到其他内容平台

这套流程的核心能力——登录态复用、富文本编辑、文件上传、表单提交、状态校验——是通用的。换一个内容平台,主要改的是选择器和页面结构适配,整体框架不用动。我后来把它迁移到另一个平台测试,只花了不到一小时调整定位逻辑就跑通了。

迁移时的关键差异点在于:不同平台的编辑器 API 不同,有的支持 execCommand,有的得用平台自己的 JS API;上传入口的 DOM 结构也不同。所以迁移前先花十分钟摸清目标平台的编辑器类型和上传机制,能省很多事。

6.2 加入内容生成环节

目前这套流程是"给定内容去发布",下一步很自然的是把内容生成也接进来。让 Agent 先根据选题写一篇文章,再走发布流程。这样就是一个完整的"选题-写作-发布"闭环。内容生成这块要注意的是,生成的内容格式要提前规范好(标题、正文、代码块标记),方便后续往编辑器里塞。

6.3 多账号与定时发布

再往远一点想,可以做成多账号管理加定时发布。多账号的关键是每个账号独立的 userDataDir,互不干扰。定时发布则是在流程外面套一层调度,到点触发。这两块技术上都不难,难的是账号安全和平台规则,得谨慎处理,别把自动化玩成违规操作。

我个人在实际操作中的体会是,浏览器自动化这件事,工具能力只是一半,另一半是"对目标页面的理解"和"对意外情况的预案"。227 次操作里,真正难的不是点按钮,而是判断"现在该点哪个按钮"以及"点完之后到底成没成"。把这两个判断做扎实了,剩下的都是体力活。最后再分享一个小技巧:每次跑长流程前,先用一个最简单的任务(比如打开页面截个图)做冒烟测试,确认环境和登录态都正常,能避免很多"跑到一半发现根本没登录"的尴尬。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询