1. 引言
你有没有想过,AI 是怎么像人一样打开网页、点击按钮、填写表单、翻页浏览的?这背后靠的并不是什么魔法,而是一套「让大模型接管浏览器」的工程方案。本文以 browser use 这类开源项目为例,拆解 AI 操作浏览器的完整实现原理,从整体架构到每一步的细节,带你彻底看懂这条链路。
2. 整体架构:AI 与浏览器之间的「翻译官」
要让 AI 操作浏览器,核心问题是:大模型只懂文本,浏览器只认 DOM 和事件。两者之间必须有一个「翻译官」来打通。
整体架构通常分为四层:
- 浏览器控制层:负责真实启动浏览器、执行点击/输入/滚动等动作,常见方案是 Playwright 或 Puppeteer。
- 状态提取层:把当前页面转成 AI 能理解的文本描述,包括 DOM 树、可交互元素、URL、标题等。
- 决策层:大模型根据当前页面状态和用户目标,输出下一步动作(点击哪个元素、输入什么内容)。
- 执行与反馈层:把模型输出的动作翻译成浏览器 API 调用,执行后把新页面状态再次喂给模型,形成循环。
#mermaid-svg-hfCnxnly5adX8JCe{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-hfCnxnly5adX8JCe .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-hfCnxnly5adX8JCe .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-hfCnxnly5adX8JCe .error-icon{fill:#552222;}#mermaid-svg-hfCnxnly5adX8JCe .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hfCnxnly5adX8JCe .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-hfCnxnly5adX8JCe .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hfCnxnly5adX8JCe .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hfCnxnly5adX8JCe .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-hfCnxnly5adX8JCe .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hfCnxnly5adX8JCe .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hfCnxnly5adX8JCe .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hfCnxnly5adX8JCe .marker.cross{stroke:#333333;}#mermaid-svg-hfCnxnly5adX8JCe svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hfCnxnly5adX8JCe p{margin:0;}#mermaid-svg-hfCnxnly5adX8JCe .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-hfCnxnly5adX8JCe .cluster-label text{fill:#333;}#mermaid-svg-hfCnxnly5adX8JCe .cluster-label span{color:#333;}#mermaid-svg-hfCnxnly5adX8JCe .cluster-label span p{background-color:transparent;}#mermaid-svg-hfCnxnly5adX8JCe .label text,#mermaid-svg-hfCnxnly5adX8JCe span{fill:#333;color:#333;}#mermaid-svg-hfCnxnly5adX8JCe .node rect,#mermaid-svg-hfCnxnly5adX8JCe .node circle,#mermaid-svg-hfCnxnly5adX8JCe .node ellipse,#mermaid-svg-hfCnxnly5adX8JCe .node polygon,#mermaid-svg-hfCnxnly5adX8JCe .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-hfCnxnly5adX8JCe .rough-node .label text,#mermaid-svg-hfCnxnly5adX8JCe .node .label text,#mermaid-svg-hfCnxnly5adX8JCe .image-shape .label,#mermaid-svg-hfCnxnly5adX8JCe .icon-shape .label{text-anchor:middle;}#mermaid-svg-hfCnxnly5adX8JCe .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-hfCnxnly5adX8JCe .rough-node .label,#mermaid-svg-hfCnxnly5adX8JCe .node .label,#mermaid-svg-hfCnxnly5adX8JCe .image-shape .label,#mermaid-svg-hfCnxnly5adX8JCe .icon-shape .label{text-align:center;}#mermaid-svg-hfCnxnly5adX8JCe .node.clickable{cursor:pointer;}#mermaid-svg-hfCnxnly5adX8JCe .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-hfCnxnly5adX8JCe .arrowheadPath{fill:#333333;}#mermaid-svg-hfCnxnly5adX8JCe .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-hfCnxnly5adX8JCe .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-hfCnxnly5adX8JCe .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hfCnxnly5adX8JCe .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-hfCnxnly5adX8JCe .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hfCnxnly5adX8JCe .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-hfCnxnly5adX8JCe .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-hfCnxnly5adX8JCe .cluster text{fill:#333;}#mermaid-svg-hfCnxnly5adX8JCe .cluster span{color:#333;}#mermaid-svg-hfCnxnly5adX8JCe div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-hfCnxnly5adX8JCe .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-hfCnxnly5adX8JCe rect.text{fill:none;stroke-width:0;}#mermaid-svg-hfCnxnly5adX8JCe .icon-shape,#mermaid-svg-hfCnxnly5adX8JCe .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hfCnxnly5adX8JCe .icon-shape p,#mermaid-svg-hfCnxnly5adX8JCe .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-hfCnxnly5adX8JCe .icon-shape .label rect,#mermaid-svg-hfCnxnly5adX8JCe .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hfCnxnly5adX8JCe .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-hfCnxnly5adX8JCe .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-hfCnxnly5adX8JCe :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户目标
状态提取层
大模型决策
动作执行
浏览器页面变化
3. 状态提取:把网页变成 AI 能读的「文本」
浏览器页面本质是一棵 DOM 树,但大模型无法直接「看」这棵树。因此第一步是把页面转成结构化的文本描述。
3.1 提取可交互元素
不是页面上所有元素都值得给模型看。browser use 会优先提取可交互元素,例如:
- 按钮(button)
- 输入框(input、textarea)
- 链接(a)
- 下拉框(select)
- 可点击的 div
每个元素会被分配一个唯一索引,并提取其关键属性:标签名、文本内容、aria 标签、id、class 等。
3.2 生成元素描述
提取到的元素会被格式化成类似下面的文本:
text
[1] <button> 登录
[2] <input> 用户名
[3] <input> 密码
[4] <button> 提交
这样模型看到的就是一份「带编号的页面清单」,而不是原始的 HTML。
3.3 控制上下文长度
一个复杂页面可能有几百个可交互元素,全部塞给模型会超出上下文窗口。因此 browser use 会做截断和过滤:
- 只保留视口内可见的元素;
- 过滤掉隐藏元素(display:none、visibility:hidden);
- 对超长列表做截断,优先保留与任务相关的部分。
4. 决策:大模型如何决定「下一步点哪里」
拿到页面状态后,大模型需要输出一个结构化的动作。browser use 采用「ReAct 模式」:模型先思考(Reason),再行动(Act)。
4.1 动作类型
模型可以输出的动作通常包括:
click_element(index):点击某个编号的元素input_text(index, text):向某个输入框填入文本scroll(direction):向上或向下滚动go_to(url):跳转到指定网址select_option(index, value):选择下拉选项wait():等待页面加载stop():任务完成,结束
4.2 结构化输出
为了让动作可被程序解析,模型输出必须是严格的 JSON 格式,例如:
json
{
"thought": "用户需要先登录,所以点击登录按钮",
"action": "click_element",
"index": 1
}
browser use 通过约束模型输出格式(如使用 JSON Mode 或函数调用)来保证解析稳定。
4.3 多步推理
复杂任务往往需要多步操作。模型每执行一步,都会拿到新的页面状态,再决定下一步,直到任务完成或达到最大步数限制。
5. 执行:把动作翻译成浏览器 API 调用
模型输出的动作是「高层指令」,浏览器控制层负责把它翻译成真实的浏览器操作。
5.1 元素定位
模型输出的是元素编号,但浏览器需要的是真实 DOM 节点。browser use 在状态提取时,会为每个编号的元素保存对应的 DOM 引用(如 XPath 或 Playwright 的 locator),执行时直接映射过去。
5.2 动作执行
以 Playwright 为例,click_element(1) 会被翻译成:
python
await page.locator(selector_map[1]).click()
input_text(2, "hello") 会被翻译成:
python
await page.locator(selector_map[2]).fill("hello")
5.3 等待与重试
页面加载是异步的,直接执行动作可能失败。因此 browser use 会:
- 等待元素出现(显式等待);
- 等待网络空闲;
- 动作失败时自动重试或重新提取页面状态。
6. 反馈循环:让 AI 看到「操作后的结果」
执行完动作后,页面状态已经改变。browser use 会重新提取页面状态,连同之前的对话历史一起喂给模型,让模型判断:
- 操作是否生效?
- 是否出现弹窗、验证码等意外情况?
- 下一步该做什么?
这个「观察 → 决策 → 执行 → 再观察」的循环,就是 AI 操作浏览器的核心机制。
#mermaid-svg-wowCGBOH3fugVB4X{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-wowCGBOH3fugVB4X .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-wowCGBOH3fugVB4X .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-wowCGBOH3fugVB4X .error-icon{fill:#552222;}#mermaid-svg-wowCGBOH3fugVB4X .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-wowCGBOH3fugVB4X .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-wowCGBOH3fugVB4X .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-wowCGBOH3fugVB4X .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-wowCGBOH3fugVB4X .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-wowCGBOH3fugVB4X .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-wowCGBOH3fugVB4X .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-wowCGBOH3fugVB4X .marker{fill:#333333;stroke:#333333;}#mermaid-svg-wowCGBOH3fugVB4X .marker.cross{stroke:#333333;}#mermaid-svg-wowCGBOH3fugVB4X svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-wowCGBOH3fugVB4X p{margin:0;}#mermaid-svg-wowCGBOH3fugVB4X .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-wowCGBOH3fugVB4X .cluster-label text{fill:#333;}#mermaid-svg-wowCGBOH3fugVB4X .cluster-label span{color:#333;}#mermaid-svg-wowCGBOH3fugVB4X .cluster-label span p{background-color:transparent;}#mermaid-svg-wowCGBOH3fugVB4X .label text,#mermaid-svg-wowCGBOH3fugVB4X span{fill:#333;color:#333;}#mermaid-svg-wowCGBOH3fugVB4X .node rect,#mermaid-svg-wowCGBOH3fugVB4X .node circle,#mermaid-svg-wowCGBOH3fugVB4X .node ellipse,#mermaid-svg-wowCGBOH3fugVB4X .node polygon,#mermaid-svg-wowCGBOH3fugVB4X .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-wowCGBOH3fugVB4X .rough-node .label text,#mermaid-svg-wowCGBOH3fugVB4X .node .label text,#mermaid-svg-wowCGBOH3fugVB4X .image-shape .label,#mermaid-svg-wowCGBOH3fugVB4X .icon-shape .label{text-anchor:middle;}#mermaid-svg-wowCGBOH3fugVB4X .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-wowCGBOH3fugVB4X .rough-node .label,#mermaid-svg-wowCGBOH3fugVB4X .node .label,#mermaid-svg-wowCGBOH3fugVB4X .image-shape .label,#mermaid-svg-wowCGBOH3fugVB4X .icon-shape .label{text-align:center;}#mermaid-svg-wowCGBOH3fugVB4X .node.clickable{cursor:pointer;}#mermaid-svg-wowCGBOH3fugVB4X .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-wowCGBOH3fugVB4X .arrowheadPath{fill:#333333;}#mermaid-svg-wowCGBOH3fugVB4X .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-wowCGBOH3fugVB4X .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-wowCGBOH3fugVB4X .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wowCGBOH3fugVB4X .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-wowCGBOH3fugVB4X .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wowCGBOH3fugVB4X .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-wowCGBOH3fugVB4X .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-wowCGBOH3fugVB4X .cluster text{fill:#333;}#mermaid-svg-wowCGBOH3fugVB4X .cluster span{color:#333;}#mermaid-svg-wowCGBOH3fugVB4X div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-wowCGBOH3fugVB4X .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-wowCGBOH3fugVB4X rect.text{fill:none;stroke-width:0;}#mermaid-svg-wowCGBOH3fugVB4X .icon-shape,#mermaid-svg-wowCGBOH3fugVB4X .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wowCGBOH3fugVB4X .icon-shape p,#mermaid-svg-wowCGBOH3fugVB4X .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-wowCGBOH3fugVB4X .icon-shape .label rect,#mermaid-svg-wowCGBOH3fugVB4X .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wowCGBOH3fugVB4X .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-wowCGBOH3fugVB4X .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-wowCGBOH3fugVB4X :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 提取页面状态
模型决策
执行动作
页面变化
7. 关键难点与工程优化
7.1 动态页面
现代网页大量使用 JavaScript 动态渲染,DOM 随时在变。browser use 通过等待网络空闲、重试机制和重新提取状态来应对。
7.2 弹窗与验证码
弹窗、验证码、Cookie 同意框会打断任务流程。工程上通常需要额外的规则处理,或让模型识别并处理这些干扰。
7.3 上下文管理
多步操作会产生大量历史记录,容易撑爆上下文窗口。browser use 会做历史压缩,只保留最近几步的关键信息。
7.4 安全性
AI 操作浏览器可能触发危险操作(如删除数据、提交订单)。工程上需要加白名单、人工确认、操作审计等安全机制。
8. 总结
AI 操作浏览器的本质,是把「网页状态」和「用户目标」都转成文本,交给大模型做决策,再把决策翻译成真实的浏览器操作,并通过循环反馈不断逼近目标。
核心链路可以概括为四步:
- 提取:把 DOM 转成带编号的文本清单;
- 决策:大模型输出结构化的下一步动作;
- 执行:把动作翻译成 Playwright/Puppeteer 调用;
- 反馈:重新提取状态,循环直到任务完成。
理解了这条链路,你就能看懂 browser use 这类工具的源码,也能自己动手实现一个简化版的「AI 浏览器助手」。