AI 如何理解和操作网页

AI 不能直接“看懂网页”。

人类打开网页时,会自然综合文字、布局、颜色、按钮、输入框、滚动、弹窗和上下文。模型本身并没有浏览器感官。要让 AI 理解和操作网页,工程系统必须先把网页转换成模型可用的观察结果,再把模型决策转换成受控的浏览器动作。

这就是 Browser Agent 的核心:把 Web 页面变成一个可观察、可操作、可验证的环境。

对前端工程师来说,这个过程并不神秘。它本质上是 DOM 解析、可访问性语义、浏览器自动化、状态等待和结果断言的组合,只是中间多了一个模型来参与决策。

一个最小闭环

AI 操作网页不是“一次 prompt 生成一段脚本”。更可靠的方式是循环。

这个闭环里,每一步都很重要。

Observe 决定模型能看到什么。Act 决定系统能做什么。Verify 决定它是否真的完成了任务。Recover 决定它在真实网页里能不能活下来。

如果缺少 verify,Agent 只是一个会乱点的自动化脚本。如果缺少 observe,模型只能靠猜。如果缺少 recover,页面稍微变化就会失败。

AI 观察网页的四类信息

一个 Browser Agent 通常会综合四类观察来源:DOM、accessibility tree、screenshot 和浏览器运行信息。

DOM:网页的结构基础

DOM 是网页的结构树。它包含元素、属性、文本、表单值、层级关系和部分状态。

对 Agent 来说,DOM 的价值在于它可精确定位、可读取、可操作。

例如一个输入框:

<label for="email">邮箱</label>
<input id="email" name="email" type="email" required />

从 DOM 里可以知道它是一个输入框、字段名可能是 email、类型是 email、必填,并且和“邮箱”这个 label 关联。

但是 DOM 也有问题。真实页面的 DOM 可能非常庞大,包含大量布局节点、隐藏元素、埋点节点和框架内部结构。直接把完整 DOM 发给模型,通常成本高、噪声大、效果差。

更好的做法是抽取与任务相关的 DOM 摘要:

type DomElementSummary = {
  elementId: string;
  tagName: string;
  role?: string;
  text?: string;
  label?: string;
  value?: string;
  href?: string;
  disabled?: boolean;
  visible: boolean;
  selectorHint: string;
};

这个摘要不追求还原页面全部细节,而是让模型知道“页面上有哪些可理解、可操作的东西”。

Accessibility Tree:更接近用户语义

Accessibility tree 是浏览器根据 DOM、ARIA 和可见文本生成的语义树。屏幕阅读器依赖它,Browser Agent 也很适合使用它。

它的优势是更接近用户感知:

  • button 叫什么。
  • textbox 对应哪个 label。
  • link 的可访问名称是什么。
  • dialog 当前是否打开。
  • checkbox 是否选中。
  • heading 和 landmark 如何组织页面。

对 AI 来说,getByRole('button', { name: '提交' }).btn.primary:nth-child(3) 更有意义,也更稳定。

一个语义良好的页面,可以让 Agent 通过 role 和 name 操作:

await page.getByRole('textbox', { name: '邮箱' }).fill('dev@example.com');
await page.getByRole('button', { name: '提交' }).click();

这也是为什么前端工程师应该重新重视可访问性。它不只是合规要求,也会成为 AI 使用 Web 的基础设施。

Screenshot:补充视觉信息

截图让模型看到布局、颜色、图标、遮挡、canvas、图表和视觉状态。

在这些场景里,截图很重要:

  • 页面主要内容是图片、图表、地图或 canvas。
  • DOM 语义缺失,无法知道某个图标的含义。
  • 需要判断元素是否被遮挡、是否在视口中。
  • 需要理解视觉布局,例如“右上角的导出按钮”。
  • 需要做执行回放和人工审计。

但截图也有天然缺陷。它是像素,不是结构。通过截图点击坐标,容易受视口大小、缩放比例、滚动位置、弹窗遮挡和动画影响。

所以在 Web 场景里,推荐顺序通常是:

  1. 能用 role 和 name 定位,就用可访问性定位。
  2. 能用稳定 DOM 属性定位,就用 DOM 定位。
  3. 需要视觉判断时,再使用截图。
  4. 坐标点击作为最后手段,并且必须验证结果。

浏览器运行信息:URL、网络、存储和控制台

网页不只有界面,还有运行时状态。

Browser Agent 可以读取:

  • 当前 URL 和 history。
  • network 请求与响应。
  • console error。
  • localStorage、sessionStorage、cookie。
  • 页面加载状态。
  • 下载、弹窗、新标签页。

这些信息能帮助 Agent 判断页面是否真的完成操作。

例如点击“保存”后,界面没有变化,但 network 返回了 500。这时只看截图可能误判,只看 DOM 也可能看不出失败。结合 network 和 toast 才能更可靠。

从观察到动作

模型不能直接执行浏览器动作。它应该输出结构化 action,由执行器校验后执行。

type BrowserAction =
  | { type: 'navigate'; url: string }
  | { type: 'click'; targetId: string }
  | { type: 'fill'; targetId: string; value: string }
  | { type: 'select'; targetId: string; value: string }
  | { type: 'press'; key: string }
  | { type: 'extract'; targetId?: string; schema: unknown }
  | { type: 'waitFor'; condition: string };

这里的 targetId 不应该是模型随便编的 CSS selector,而应该来自 observe 阶段生成的元素编号。

例如观察结果给出:

{
  "id": "el_12",
  "role": "button",
  "name": "搜索",
  "selectorHint": "role=button[name='搜索']"
}

模型只需要说:

{
  "type": "click",
  "targetId": "el_12"
}

执行器再负责把 el_12 映射到真实 locator,并处理点击、等待和错误。

这样做有三个好处。

第一,模型输出更简单,不需要生成脆弱 selector。

第二,执行器可以检查目标是否存在、是否可见、是否 disabled。

第三,所有动作都能被记录和回放。

动作执行器要做什么

Browser Agent 的执行器不能只是 page.click() 的薄封装。它应该像一个安全网。

执行动作前,至少要检查:

  • action 类型是否允许。
  • 参数是否符合 schema。
  • 目标元素是否来自当前 observation。
  • 元素是否可见、可用、未被遮挡。
  • 当前动作是否高风险。
  • 是否需要用户确认。

执行动作后,至少要记录:

  • 动作类型和参数。
  • 使用的 locator。
  • 执行前后的 URL。
  • 执行前后的截图或 DOM 摘要。
  • 耗时。
  • 错误信息。

这让 Browser Agent 从“黑盒自动点击”变成可审计系统。

Verify:最容易被忽视的一步

很多 Browser Agent Demo 看起来很酷,但不可靠,原因通常是没有认真做验证。

例如任务是“把用户昵称改成 Alex”。Agent 点击保存后,不能直接说完成。它应该验证:

  • 昵称输入框当前值是否为 Alex。
  • 页面是否出现保存成功提示。
  • 是否出现字段错误。
  • 后端请求是否成功。
  • 刷新后昵称是否仍为 Alex。

不同任务的 verify 不一样。

信息提取任务要验证字段完整性和来源。表单填写任务要验证每个字段值。搜索任务要验证结果与查询相关。写操作要验证提交成功且没有错误提示。

一个可用的 verify 结构可以这样设计:

type VerificationResult = {
  passed: boolean;
  confidence: 'low' | 'medium' | 'high';
  evidence: Array<{
    type: 'text' | 'element' | 'url' | 'network' | 'screenshot';
    value: string;
  }>;
  missing?: string[];
  nextSuggestion?: string;
};

Verify 不一定全靠模型。很多验证应该用规则做:

  • URL 是否匹配。
  • 元素是否可见。
  • 字段值是否等于目标值。
  • 成功 toast 是否出现。
  • network status 是否为 200。
  • JSON schema 是否通过。

模型适合判断语义相似、页面内容是否满足目标、提取结果是否合理。规则适合判断确定性状态。

Recover:真实网页里的必需品

真实网页总会出问题。

常见情况包括:

  • 页面加载慢。
  • 弹窗遮挡目标元素。
  • 登录态过期。
  • 新标签页打开。
  • cookie banner 出现。
  • selector 失效。
  • 元素不在视口内。
  • 表单校验失败。
  • 页面语言变化。
  • 网络请求失败。

Recover 的目标不是让 Agent 永远成功,而是让它知道如何安全失败。

常见恢复策略包括:

  • 重新 observe 当前页面。
  • 滚动到目标区域。
  • 关闭可识别的弹窗。
  • 等待 loading 消失。
  • 改用其他定位方式。
  • 请求用户登录或输入验证码。
  • 将页面状态和失败原因返回给用户。
  • 超过最大步数后停止。

一个重要原则是:恢复动作也要受控。

Agent 可以关闭“订阅弹窗”,但不应该自动绕过验证码;可以重新填写草稿,但不应该在不确定时重复提交订单。

前端页面怎样变得更容易被 AI 操作

如果你正在开发一个希望被 Browser Agent 使用的 Web 应用,可以从这些地方开始。

使用语义 HTML

优先使用真实的 buttonainputselecttextareaform。不要用一堆 div 模拟所有控件。

语义 HTML 不仅让页面更可访问,也让自动化定位更稳定。

给控件明确名称

每个可交互控件都应该有清楚的可访问名称。

表单字段使用 label:

<label for="company">公司名称</label>
<input id="company" name="company" />

图标按钮使用 aria-label:

<button aria-label="导出报表">
  <DownloadIcon />
</button>

让状态变化可观察

不要只通过颜色表达状态。错误、成功、禁用、加载中、选中,都应该能从 DOM 或 a11y tree 中观察到。

例如表单错误可以关联字段:

<input id="email" aria-describedby="email-error" aria-invalid="true" />
<p id="email-error">请输入有效邮箱</p>

这能帮助用户,也能帮助 Agent 判断下一步。

为测试和 Agent 保留稳定锚点

在复杂业务系统里,可以为关键元素提供稳定的 data-testid 或业务语义属性。

但不要把它当成唯一方案。更好的顺序是语义优先,测试锚点补充。

常见坑

坑一:把完整 HTML 塞给模型

完整 HTML 通常又长又脏,包含很多无关结构。模型会被噪声干扰,成本也会升高。

应该抽取面向任务的 observation:当前页面、主要文本、可交互元素、表单字段、弹窗和错误状态。

坑二:让模型直接生成 CSS selector

模型生成 selector 看起来方便,但非常脆弱。class 名、层级、nth-child 都可能变化。

更稳的方式是 observe 阶段生成元素 ID,模型选择 ID,执行器映射到 locator。

坑三:只执行不等待

网页动作常常触发异步加载。如果 click 后马上 observe,可能读到旧状态。

执行器应该根据动作类型等待页面稳定,例如等待 URL 变化、元素出现、loading 消失、network idle 或特定 toast。

坑四:把截图坐标当万能方案

坐标操作在 Computer Use 里很常见,但在 Web 里不应该优先使用。DOM 和 a11y locator 更稳定、更可解释。

截图适合辅助视觉理解,不适合作为所有操作的基础。

坑五:没有用户确认

Agent 能点击,并不意味着它应该点击。

删除、提交、付款、发送、发布、修改权限等动作都应该进入确认流程。用户确认前,Agent 最多生成草稿或预览。

小结

AI 理解和操作网页,靠的不是模型突然拥有浏览器直觉,而是一套工程闭环:观察页面、生成结构化动作、受控执行、等待状态、验证结果、失败恢复。

DOM 和 accessibility tree 提供语义,截图提供视觉补充,Playwright 等自动化工具提供动作能力,Agent 状态机提供过程控制。

前端工程师理解这些底层机制,就能设计出更适合 AI 使用的网页,也能构建更可靠的 Browser Agent。