无障碍树驱动的 UI 自动化
无障碍树驱动的 UI 自动化
学习目标
读完本章后,你将能够:
- 理解为什么 Accessibility Tree 比 DOM 选择器更适合 AI Agent 的 UI 操作
- 掌握 AXNode 到 Agent 可用标识符的转换方法
- 设计稳定的元素引用生命周期(UID 管理)
- 对比三种 UI 导航方案的优劣
为什么不用 DOM 选择器?
AI Agent 操作网页时,需要一种稳定的方式引用页面元素。传统的选择器方案存在以下问题:
| 方案 | 问题 |
|---|---|
| CSS 选择器 | .btn-primary:nth-child(3) 脆弱且对人类不友好,Agent 难以理解语义 |
| XPath | /html/body/div[2]/section/form/button[1] 冗长且随 DOM 变化失效 |
| 坐标 (x, y) | 需要视觉模型,且受 DPI、缩放、滚动位置影响 |
| Accessibility Tree | 包含语义信息(role、name、state),稳定且人类可读 |
Accessibility Tree 的优势
- 语义丰富:每个节点包含
role(按钮、链接、输入框等)和name(文本标签) - 结构扁平化:去除了纯装饰性的 DOM 节点,保留有意义的 UI 元素
- 跨框架一致:无论前端用 React、Vue 还是原生 HTML,AXNode 结构一致
- 人类可读:
{role: "button", name: "Submit"}对 Agent 和人都直观
Chrome 无障碍树的结构
Chrome DevTools Protocol (CDP) 通过 Accessibility.getFullAXTree 提供完整的无障碍树。
AXNode 核心字段
{ "nodeId": "AXNodeId_123", "role": { "value": "button" }, "name": { "value": "Submit" }, "description": { "value": "" }, "ignored": false, "properties": [ { "name": "disabled", "value": { "type": "boolean", "value": false } } ], "childIds": ["AXNodeId_456", "AXNodeId_789"]}注意:nodeId 是 CDP 内部 ID,不稳定——每次 AXTree 刷新都会变化。Agent 需要一个稳定的引用标识符。
UID 管理:稳定的元素引用
核心挑战:AXNode 的 nodeId 会随 AXTree 更新而变化。Agent 在收到快照后引用一个元素,需要这个引用在后续操作(如 click)中仍然有效。
设计模式:UID 映射生命周期
关键生命周期:
- 快照生成时:为每个 AXNode 生成稳定的 UID(基于位置 hash 或自增计数器)
- UID 到后端节点的映射:将 AXNode 的
backendNodeId(CDP DOM 节点 ID,相对稳定)存储到uniqueBackendNodeIdToMcpId映射中 - 操作执行时:通过 UID → backendNodeId →
DOM.performSearch/DOM.resolveNode获取ElementHandle - 快照更新时:旧的 UID 失效,Agent 需要重新获取快照
陷阱:UID 复用
当页面 DOM 变化时,旧的 UID 可能指向不存在的元素:
- 对策 1:每次操作前验证 UID 是否仍然有效
- 对策 2:提供清晰的错误信息(如
Element with uid "abc123" no longer exists on the page) - 对策 3:在
take_snapshot后建议 Agent 尽快完成操作,避免 DOM 变化
三种 UI 导航方案对比
| 维度 | 无障碍树 + UID | 坐标 (x, y) | DOM 选择器 |
|---|---|---|---|
| 稳定性 | 高(快照内稳定) | 低(受滚动/缩放影响) | 中(SPA 变化后失效) |
| 语义 | 丰富(role + name) | 无 | 弱(需解析 class/id) |
| 动态内容 | 需重新快照 | 实时 | 可实时查询 |
| 多模态需求 | 无需视觉模型 | 需要视觉模型 | 无需 |
| 人类可读 | 是 | 否 | 部分 |
| 适用范围 | 所有有语义的 UI | 所有可见元素 | 所有 DOM 元素 |
何时选择坐标方案?
坐标方案(如 click_at(x, y))适用于:
- Canvas 或 WebGL 内容(无 AXNode)
- 自定义渲染的 UI 组件(无标准 ARIA role)
- 配合视觉模型(computer-use)使用
设计决策框架
陷阱与对策
| 陷阱 | 后果 | 对策 |
|---|---|---|
| AXTree 未更新 | Agent 操作到旧元素或找不到元素 | 每次关键操作前重新 take_snapshot |
| UID 跨页面复用 | Agent 点击了错误的元素 | UID 在页面导航后失效,需要新快照 |
| 动态内容未捕获 | waitFor 期间出现的元素不在快照中 | 提供 wait_for 工具等待特定文本出现后再快照 |
| 隐藏元素在快照中 | Agent 尝试操作不可见元素 | 过滤 ignored 为 true 或 hidden 的节点 |