欢迎回到《Nanobrowser 源码分析》系列。在上一篇中,我们探讨了 Nanobrowser 的多智能体协作架构。今天,我们将进入一个非常硬核的话题:视觉感知。
对于人类来说,看一眼网页就能找到“登录”按钮;但对于 AI 模型来说,面对动辄数万行的原始 HTML 代码,它会瞬间淹没在“噪声”中。Nanobrowser 是如何把复杂的网页“翻译”成 AI 能听懂的语言的?
一、 为什么 AI 不能直接读 HTML?
在深入源码之前,我们需要理解两个痛点:
-
Token 爆炸:一个普通的电商商品页,原始 HTML 往往超过 100KB。如果直接塞给 LLM,不仅成本极高,还会因为超过上下文长度导致模型“失忆”。
-
视觉噪音:HTML 中包含大量的
<script>、<style>、无意义的<div>嵌套以及隐藏的埋点代码。这些对 AI 定位核心操作毫无帮助。
Nanobrowser 的核心方案是:DOM 蒸馏(Distillation)与无障碍树(Accessibility Tree)映射。
二、 核心技术 1:DOM 树的“瘦身”艺术
Nanobrowser 在 src/content/ 目录下实现了一套精密的过滤机制。其目标是:保留交互性,删除装饰性。
2.1 常见的过滤策略
Nanobrowser 会遍历 DOM 树,并应用以下规则:
-
标签黑名单:直接剔除
script,style,svg,path,noscript等不影响功能逻辑的标签。 -
不可见元素过滤:通过
getComputedStyle检测display: none或visibility: hidden的元素。 -
属性清洗:只保留
id,class,href,placeholder,title以及以aria-开头的属性。
2.2 文本压缩
对于冗长的文本节点,Nanobrowser 会进行截断或去重,确保 AI 能获取关键信息(如按钮文字、标题),同时节省 Token。
三、 核心技术 2:基于无障碍树(A11y Tree)的感知
这是 Nanobrowser 聪明的地方。与其试图理解混乱的 <div> 布局,不如利用浏览器自带的无障碍树。
为什么选择 A11y Tree?
无障碍树是浏览器为屏幕阅读器(供视障人士使用)准备的。它天然地提取了页面的语义:哪个是按钮(Role: button),哪个是输入框(Role: textbox),哪个是导航栏(Role: nav)。
源码实现逻辑:
-
节点标注:Nanobrowser 会给页面上每一个“可交互元素”分配一个唯一的
nano-id。 -
语义提取:通过读取元素的
role属性和aria-label,为 AI 构建一个类似 JSON 的页面快照。
JSON
// AI 看到的简化快照示例
{
"nodeId": "12",
"role": "button",
"name": "提交订单",
"attributes": { "disabled": false }
}
四、 核心组件:快照(Snapshot)技术源码分析
在 src/content/vision/snapshot.ts(参考路径)中,Nanobrowser 实现了一个“快照生成器”。
4.1 坐标映射机制
为了让 AI 能够模拟点击,快照中不仅包含文本,还必须包含坐标(Bounding Box)。
-
计算位移:源码调用
getBoundingClientRect()获取元素在视口中的绝对位置。 -
坐标校准:考虑到滚动条的位置,Nanobrowser 会实时修正这些坐标,确保 Navigator 智能体发出的
click(x, y)指令精准无误。
4.2 变化检测
Nanobrowser 并不是每一秒都在重新解析页面。它利用了 MutationObserver API。
-
逻辑:只有当 DOM 发生重大变化(如 URL 跳转、弹窗弹出)时,才会触发新的快照生成。
-
意义:这极大地降低了本地 CPU 的占用,也减少了与 LLM 的通信频率。
五、 对比:原始 DOM vs 简化快照
| 特性 | 原始 HTML | Nanobrowser 快照 |
| Token 消耗 | 极高 (10,000+) | 低 (几百到一千) |
| 包含噪音 | 包含 CSS, JS, 统计代码 | 仅包含交互元素和语义文本 |
| AI 理解难度 | 难(需从杂乱代码中推理) | 易(结构化 JSON 或 Markdown) |
| 操作精度 | 模糊 | 精确到像素坐标 |
六、 总结:AI 的“眼睛”其实是语义
通过源码分析我们可以发现,Nanobrowser 并没有使用复杂的计算机视觉(CV)去识别图片,而是通过深度挖掘浏览器的无障碍语义,将视觉问题转化为了一个结构化的信息处理问题。
这种做法的优势在于:极速、廉价且极其精准。


被折叠的 条评论
为什么被折叠?



