资讯中心

AI操控浏览器提速10倍:结构化语义提取与分层决策架构实战

📅 2026/10/14 14:36:32
AI操控浏览器提速10倍:结构化语义提取与分层决策架构实战
1. 从7秒订票说起AI操控浏览器到底卡在哪前阵子我在一个技术群里看到有人吐槽说他用AI智能体帮忙订高铁票从发出指令到出票成功整整等了快两分钟。群里立刻有人接话两分钟算快的了我上次让它填个表单光等它思考就等了一分半。这个场景我太熟悉了——过去大半年我陆陆续续试过七八种不同的AI浏览器操控方案从最早的纯截图识别到后来的DOM解析再到最近开始流行的结构化指令架构踩过的坑能写满一个笔记本。但最近有个案例让我眼前一亮有人用一套新架构把订票全流程压到了7秒以内。7秒是什么概念你手动打开12306、选车次、填乘客信息、确认支付手速快的人也要三四十秒。AI用7秒完成意味着它不只是能操作而是操作得比人还利索。这背后的架构思路值得好好拆一拆。先说说为什么大多数AI操控浏览器会慢。核心原因有三个层面感知层的截图识别太耗时决策层的大模型推理链路太长执行层的每一步操作都要等页面完全加载。这三个问题叠加起来就像你让一个近视眼、反应慢、还非要等红绿灯读完秒才肯走的人去开车——不慢才怪。我拿自己实测的数据说话。用某款基于纯视觉方案的智能体订一张票各阶段耗时大致是这样的截图并上传给模型约1.2秒模型推理下一步动作约2.5秒执行点击后等待页面稳定约1.8秒循环往复平均需要12到15轮才能完成全流程。算下来就是(1.22.51.8)×13≈71.5秒再加上网络波动和重试两分钟真不夸张。那7秒的方案做对了什么简单说就是三件事把看的方式换了把想的链路短了把做的节奏提了。下面我逐层拆解。2. 感知层重构从截图识别到结构化语义提取2.1 为什么截图方案是性能杀手纯视觉方案的工作方式是截取当前页面→把图片传给多模态大模型→模型识别图中的按钮、输入框、文字→输出坐标→执行点击。这个流程听起来很直观但每一步都在烧时间。首先是截图本身。一个1080P的页面截图PNG格式大约2到4MB转成base64编码后体积膨胀约33%上传到模型服务端的耗时在0.8到1.5秒之间取决于网络状况。其次是模型处理图像。多模态模型对图像的编码和理解比纯文本慢得多一张图进去光是视觉编码器就要跑几百毫秒。最后是坐标输出的精度问题——模型给出的坐标经常有偏差点不中就得重来重来一次又是两三秒。我做过一个对比测试同一个订票任务纯截图方案平均需要13.7轮交互而结构化方案只需要4.2轮。轮次少了总耗时自然就降下来了。2.2 结构化语义提取的具体做法新架构的核心思路是不去看页面长什么样而是直接读页面的结构。浏览器本身就把页面组织成了一棵DOM树每个可交互元素都有标签、属性、文本内容。与其让模型去识别像素不如把这些结构化信息提取出来直接喂给模型。具体操作上我通常会在页面加载完成后注入一段提取脚本把页面上所有可交互元素整理成一个精简列表。这个列表包含每个元素的类型按钮、输入框、链接、下拉框、可见文本、关键属性如name、id、placeholder、aria-label、以及它在页面中的大致位置。一个典型的订票页面提取出来的可交互元素大约30到50个整理成JSON后体积只有几KB比截图小了三个数量级。这里有个关键细节不是所有元素都要提取。页面上有很多装饰性元素、隐藏元素、重复的导航链接这些对当前任务没有帮助反而会干扰模型判断。我的做法是加一层过滤规则只保留可见的display不为none、visibility不为hidden、可交互的有click事件或是指向表单元素、且在视口范围内或可通过滚动到达的元素。这样能把元素数量压缩60%以上。注意提取脚本要处理好iframe和Shadow DOM的情况。很多现代前端框架会把内容放在Shadow DOM里普通的querySelector查不到需要用shadowRoot递归遍历。iframe则要先切换到对应的frame上下文再提取。2.3 语义压缩与优先级排序提取出来的元素列表还需要进一步压缩。我的经验是给每个元素打一个任务相关度分数依据包括元素文本是否匹配当前任务的关键词、元素类型是否属于当前步骤需要的类型、元素是否在页面视觉重心区域。分数高的排在前面分数低的可以截断。举个例子订票任务进行到选择车次这一步时页面上最相关的是车次列表里的预订按钮其次是筛选条件再次是导航栏。把这三类元素的分数拉开模型只需要看前10个元素就能做出决策推理速度自然快。这套感知层的改造实测能把单轮感知耗时从1.2秒压到0.15秒左右而且因为信息更精准模型决策的准确率反而更高了。3. 决策层瘦身让大模型少想废话3.1 长链路推理的时间成本很多人以为大模型推理很快其实不然。一个70B参数的模型在消费级显卡上生成一个token大约需要50到100毫秒。如果模型每次决策要输出200个token的思考过程那就是10到20秒。就算用API调用云端大模型网络往返加上排队单次推理也要1到3秒。更麻烦的是很多智能体框架会让模型做链式思考——先分析当前页面状态再回忆任务目标再规划下一步再检查是否合理最后才输出动作。这套流程对复杂任务有帮助但对点击这个按钮这种简单动作来说纯属浪费时间。我见过一个极端的例子某个智能体在订票时每点一个按钮前都要输出一段我现在看到页面上有这些元素根据我的任务目标我应该点击XX按钮因为...的推理文本平均每次决策耗时4秒以上。13轮下来光决策就花了50多秒。3.2 分层决策架构的设计7秒方案的做法是分层决策把决策拆成快思考和慢思考两层。快思考层是一个轻量级的规则引擎或小模型负责处理高频、简单的决策。比如当前页面有下一步按钮且任务处于表单填写阶段→点击下一步这种决策不需要大模型参与规则匹配耗时在10毫秒以内。慢思考层才是大模型只在快思考层无法确定时才介入。比如页面出现了验证码、弹出了意外的对话框、或者任务需要根据页面内容做复杂判断时才调用大模型。这个架构的关键在于快思考层的规则要覆盖足够多的场景。我的做法是先把一个典型任务比如订票拆成若干步骤每个步骤列出可能遇到的页面状态和对应的动作形成一张决策表。这张表覆盖了80%以上的常见情况剩下20%的边角情况交给大模型兜底。实测下来一个订票任务平均只需要调用大模型1到2次其余决策都由规则引擎完成。决策层总耗时从原来的30秒以上压缩到了3秒以内。3.3 提示词精简与输出格式约束对于必须调用大模型的那部分决策提示词的设计也很关键。我总结了三条原则第一只给必要信息。不要把整个页面结构都塞给模型只给当前步骤相关的元素列表。第二约束输出格式。要求模型直接输出JSON格式的动作指令不要输出任何解释性文字。第三提供少样本示例。在提示词里放两三个输入→输出的示例让模型照着格式来减少格式错误导致的重试。一个精简后的提示词大概长这样{ task: 订票-选择车次, elements: [ {id: 1, type: button, text: 预订, context: G1234 北京南-上海虹桥}, {id: 2, type: button, text: 预订, context: G5678 北京南-上海虹桥} ], instruction: 选择出发时间在9:00-10:00之间的车次输出格式{\action\:\click\,\element_id\:N} }模型只需要输出{action:click,element_id:1}十几个token就搞定推理时间压到了0.5秒以内。4. 执行层提速别让等待成为瓶颈4.1 页面加载等待的优化传统方案在执行点击后会等待页面完全加载window.onload或networkidle再进行下一步。但现代网页的加载是异步的很多资源图片、广告、统计脚本跟当前任务无关等它们加载完纯属浪费。我的做法是按需等待点击后不等待整个页面加载完成而是等待特定条件满足。比如点击查询按钮后等待车次列表容器出现即可不用等页面底部的推荐内容加载完。具体实现上可以用MutationObserver监听目标元素的出现或者用轮询检查特定选择器是否存在超时时间设3秒超时就进入下一步。这个优化能把每轮执行的等待时间从1.8秒压到0.3到0.5秒。13轮下来省了将近20秒。4.2 并行操作与预加载有些操作其实可以并行。比如填写表单时多个输入框的填写不需要串行执行可以一次性把数据填进去再触发提交。再比如在等待当前页面响应的同时可以预判下一步可能需要的信息并提前准备。我试过一个更激进的优化在点击查询按钮的同时就开始提取页面上可能出现的车次列表容器的选择器这样等结果出来时提取脚本已经准备好了直接执行就行。这个预加载策略能再省0.2到0.3秒。4.3 浏览器层面的调优如果智能体是跑在本地浏览器上还有一些浏览器层面的优化空间。比如关闭图片加载对于纯结构化方案来说图片完全不需要、禁用不必要的插件、使用无头模式减少渲染开销。这些设置能让页面加载速度提升30%以上。提示关闭图片加载可以通过设置浏览器的启动参数实现也可以在请求拦截层面过滤掉图片类型的资源。但要注意有些网站的布局依赖图片尺寸关闭图片可能导致元素位置错乱需要配合CSS注入做兜底。5. 完整实操从零搭建一个快速订票智能体5.1 环境准备与工具选型要复现这套方案你需要准备以下工具浏览器自动化框架Playwright或Puppeteer。我选Playwright因为它对多浏览器支持更好API也更现代。大模型接口任意支持JSON输出的文本模型即可。我用的是本地部署的小模型做快思考云端大模型做慢思考兜底。规则引擎不需要专门的引擎用Python的字典和条件判断就够了。运行环境Python 3.10以上Node.js 18以上Playwright依赖。安装命令pip install playwright playwright install chromium5.2 感知层实现页面元素提取脚本这是整个方案的基础。我写了一个提取函数核心逻辑如下async def extract_interactive_elements(page): elements await page.evaluate( () { const results []; const walker document.createTreeWalker( document.body, NodeFilter.SHOW_ELEMENT ); let node; while (node walker.nextNode()) { const style window.getComputedStyle(node); if (style.display none || style.visibility hidden) continue; const tag node.tagName.toLowerCase(); const isInteractive [button, a, input, select, textarea].includes(tag) || node.onclick || node.getAttribute(role) button; if (!isInteractive) continue; const rect node.getBoundingClientRect(); if (rect.width 0 || rect.height 0) continue; results.push({ tag: tag, text: (node.innerText || node.value || ).trim().slice(0, 50), id: node.id || , name: node.name || , placeholder: node.placeholder || , ariaLabel: node.getAttribute(aria-label) || , x: Math.round(rect.x), y: Math.round(rect.y) }); } return results; } ) return elements这个脚本会返回页面上所有可见可交互元素的精简信息。实测一个订票页面返回30到50个元素JSON序列化后约3到5KB。5.3 决策层实现规则表与大模型兜底规则表的设计是核心。我以订票任务为例定义了一个状态机RULES { search_page: { condition: lambda els: any(出发 in e[placeholder] for e in els), action: fill_departure }, result_page: { condition: lambda els: any(预订 in e[text] for e in els), action: select_train }, confirm_page: { condition: lambda els: any(提交 in e[text] or 确认 in e[text] for e in els), action: submit_order } }每个状态对应一个条件判断和一个动作。条件判断基于提取出的元素列表动作则是具体的操作指令。当所有规则都不匹配时才调用大模型。大模型调用时提示词只包含当前元素列表和任务描述要求输出JSON格式的动作。我设置的最大输出token数为50确保模型不会输出长篇大论。5.4 执行层实现按需等待与操作执行执行层的核心是等待策略。我封装了一个wait_for_condition函数async def wait_for_condition(page, selector, timeout3000): try: await page.wait_for_selector(selector, timeouttimeout, statevisible) return True except: return False点击操作后根据下一步预期的元素选择器来等待而不是等整个页面加载。比如点击查询后等待车次列表的容器选择器出现即可。5.5 全流程串联与实测数据把三层串起来主循环大概是这样async def run_task(page, task): for step in range(20): # 最多20轮 elements await extract_interactive_elements(page) action decide(elements, task) # 规则优先大模型兜底 if action is None: break await execute_action(page, action) await wait_for_condition(page, action[next_selector]) return done我用自己的账号实测了10次订票任务平均耗时6.8秒最快一次5.2秒最慢一次9.1秒遇到了一次验证码。对比之前纯截图方案的71秒提速超过10倍。6. 常见问题与排查技巧实录6.1 元素提取不全或提取到隐藏元素这是最常见的问题。原因通常是页面用了懒加载或虚拟滚动当前视口外的元素没有被渲染。解决办法是提取前先滚动页面到底部再回到顶部触发所有元素的渲染。另外有些元素虽然可见但被其他元素遮挡这种也要过滤掉可以用document.elementFromPoint检查元素是否真的可点击。6.2 大模型输出格式错误导致解析失败即使提示词里给了格式示例模型偶尔还是会输出多余的文字或错误的JSON。我的做法是在解析前先做一次清洗用正则提取第一个{到最后一个}之间的内容再尝试解析。如果解析失败直接把原始输出和错误信息一起返回给模型让它重新生成最多重试两次。6.3 页面跳转导致元素引用失效点击一个按钮后页面跳转了之前提取的元素列表就全部失效了。这个问题在架构上已经规避了——每轮循环都重新提取元素不跨页面复用。但要注意如果点击后页面没有跳转而是局部刷新元素引用也可能失效所以每轮重新提取是必须的。6.4 验证码与风控拦截这是最棘手的问题。我的经验是不要试图绕过验证码而是设计一个降级流程——检测到验证码时暂停自动操作通知人工介入人工完成后继续。这样虽然牺牲了全自动化但保证了稳定性和合规性。问题类型典型表现排查思路解决方案元素提取不全找不到目标按钮检查是否在iframe或Shadow DOM中切换frame上下文或递归shadowRoot模型输出异常JSON解析失败查看原始输出正则清洗重试机制页面等待超时下一步元素迟迟不出现检查选择器是否正确改用更宽松的选择器或增加超时操作被拦截点击无响应检查是否有遮罩层先关闭弹窗或滚动到元素位置6.5 性能波动的排查方法如果发现某次任务特别慢我会在每轮循环里打时间戳记录感知、决策、执行三个阶段的耗时。通常波动来自两个地方一是网络请求慢导致页面加载久二是大模型API响应慢。前者可以通过增加本地缓存缓解后者可以切换到更快的模型或增加规则覆盖率来减少调用次数。7. 架构选型的几点个人体会这套方案我前后迭代了三个版本从最初的纯截图方案到后来的混合方案再到现在的结构化为主、视觉为辅。最大的体会是不要迷信大模型的能力能用规则解决的就不要用模型。规则引擎快、稳、可控大模型只适合处理规则覆盖不到的边角情况。另一个体会是感知层的优化收益最大。决策层和执行层的优化空间有限但感知层从截图换成结构化提取直接砍掉了80%的耗时。如果你也在做类似的智能体建议先把感知层做扎实。最后说一个容易被忽略的点任务拆解要足够细。订票任务拆成填出发地→填目的地→选日期→点查询→选车次→填乘客→提交订单七个步骤每个步骤的决策逻辑都很简单。如果把它当成一个大任务让模型一次性规划反而容易出错且慢。细粒度拆解配合规则引擎是目前我找到的最优解。这套架构不只适用于订票任何表单填写、信息查询、批量操作的场景都可以套用。核心思想就一句话让机器做机器擅长的事让模型做模型擅长的事别让模型去做机器能做的事。

看完文章,想为自己的企业也做一次专业网站诊断?

尧图顾问免费为您评估现有网站,并给出建站/改版建议与报价方案。

免费获取方案