用浏览器扩展自动化采集 AI 平台回答:一次真实的豆包改版适配实录
豆包一次改版让探测脚本全线失效:aria-label 消失、按钮 DOM 重构、事件不被识别。三轮排查的完整记录,以及 AI 平台自动化采集的三个应对策略。
做 GEO 产品的都知道,核心链路第一步是向真实 AI 平台提问并采集回答——不是调 API,是像真人一样打开豆包/DeepSeek/千问的网页,输入问题,等回答。我们产品(UpGEO,国产 GEO 工具)的探测功能就是这么实现的。这篇记录一次豆包改版导致采集全线失效的完整排查过程。
背景:采集器的工作原理
扩展在豆包页面注入一段脚本,流程是:定位输入框并聚焦,用 document.execCommand('insertText') 往 contenteditable 编辑器写入文本,点击发送按钮,hook window.fetch 拦截响应流解析 SSE 增量拿到完整回答,最后回传后端做品牌提及分析。这套流程跑了半年没问题,直到豆包改版。
难题一:输入框的 aria-label 消失了
旧版豆包的输入框有 aria-label="发消息",我们用无障碍语义定位。改版后豆包把 textarea 换成了 tiptap/ProseMirror 富文本编辑器,而且 role="textbox" 的 div 上什么 aria 属性都没有——placeholder 被移到了内部 <p> 的 data-placeholder 上。
修复是加了一层兜底链:先按 data-placeholder 文案反查编辑器节点,找不到就取页面上唯一可见的 ProseMirror。另外 ProseMirror 的文本注入也得换姿势:execCommand 之后还要手动 dispatch 一个 InputEvent,否则 React 状态不更新。
难题二:发送按钮是「薛定谔的按钮」
这是最坑的一个。修完输入框后,文字能打进去了,但发送按钮点了没反应。
用 MutationObserver 盯着按钮区域观察,发现了真相:输入框有字和没字,是两个完全不同的 DOM 节点。空输入时是个语音按钮,有文字时 React 才插入真正的发送按钮。两个按钮长得几乎一模一样:都是圆形、都没文字、都没 aria-label。最初「找第一个空文案圆形按钮」的逻辑永远命中语音按钮——点了不发送也不报错,流程静默卡死。
修复:只认发送按钮独有的高亮底色 class(bg-dbx-fill-highlight),并且轮询等待——发送按钮是输入文字后 React 才插入的节点,输入完立刻查是查不到的,实测约 400ms 后节点才就位。对「状态驱动的动态节点」,静态选择器加一次性查询的组合是必挂的。
难题三:面板定位的层级陷阱
发送按钮的搜索范围是「输入面板」。最初实现是「从编辑器往上找第一个包含足够多 button 的层级」——在未登录的测试页上工作正常,登录态页面直接失效:登录后侧边栏多了大量按钮,某个中间层级恰好凑够数量但全是侧边栏的。修复是给面板识别加语义锚点:只有当这一层的按钮里出现「PPT 生成」「图像生成」这类输入面板独有的文案时,才认定找对了容器。数量会变,语义不会。
复盘:AI 平台自动化的脆弱性
这次修复花了三个迭代,每一版都以为修好了,每一版都在下一个坑里栽跟头。根本原因:我们依赖的 DOM 契约,对方随时可以单方面撕毁。
给做类似事情的同学几条实践建议:
- 语义锚点 > 结构匹配 > 数量启发式,aria-label 和按钮文案比 DOM 层级结构稳定得多
- 动态节点必须轮询或 MutationObserver 等待,别赌时序
- 测试环境要贴近真实——登录态、会员态、移动端,每个状态都是不同的页面
- 失败要可观测:这次能快速定位,靠的是把扩展的错误详情回传到服务端日志
这类「AI 平台适配器」的维护是 GEO 工具绕不开的成本——豆包这次改版我们三天修完,靠的就是日志回传加真实页面调试的闭环。如果你也在做 AI 平台自动化(采集、评测、监控),这些坑我们基本都踩过一遍了。
预约体验 UpGEO,体验基于真实页面采集的品牌可见性探测。