跳转到内容

无障碍树驱动的 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 的优势

  1. 语义丰富:每个节点包含 role(按钮、链接、输入框等)和 name(文本标签)
  2. 结构扁平化:去除了纯装饰性的 DOM 节点,保留有意义的 UI 元素
  3. 跨框架一致:无论前端用 React、Vue 还是原生 HTML,AXNode 结构一致
  4. 人类可读{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 映射生命周期

关键生命周期

  1. 快照生成时:为每个 AXNode 生成稳定的 UID(基于位置 hash 或自增计数器)
  2. UID 到后端节点的映射:将 AXNode 的 backendNodeId(CDP DOM 节点 ID,相对稳定)存储到 uniqueBackendNodeIdToMcpId 映射中
  3. 操作执行时:通过 UID → backendNodeId → DOM.performSearch / DOM.resolveNode 获取 ElementHandle
  4. 快照更新时:旧的 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 的节点

参考来源