browser-use 实战:让大模型自己操作浏览器的自动化新范式 最近有几个做自动化测试的同行跟我吐槽说规则脚本越写越累目标网站一改版CSS 选择器就全废了又要花半天调 xpath。我特别理解这种状态因为我自己也经历过类似周期写脚本、上线、跑俩月、网站改版、脚本报废、再改。后来我开始关注一个叫 browser-use 的开源库思路完全不一样——它让大模型自己“看”网页、自己决定下一步点哪里、填什么而不是把每一步都写死在代码里。这篇文章就把我对这个库的理解、原理拆解、跑通 Demo 的经过以及实测中踩过的坑和调优思路完整分享出来。如果你是做爬虫、做 RPA、做 AI Agent 的开发者或者只是好奇“AI 操作浏览器到底是怎么实现的”这篇内容应该能给你一个比较系统的参考。1. browser-use 到底是什么当自动化脚本不再“写死规则”1.1 它解决的核心痛点规则脚本的维护成本传统浏览器自动化的典型做法是告诉程序“先找到 ID 为 email 的输入框输入 A再点击 class 为 btn-login 的按钮”。这种写法本身没毛病问题在于页面一改版ID 变成 nameclass 变成>pip install browser-use playwright playwright install chromium第一行是装库本身第二行是给 Playwright 下载 Chromium 浏览器内核。很多人只执行第一步运行时报错找不到浏览器才想起来第二步。我建议用 Python 3.10 或 3.11 的虚拟环境来装。之前我在 3.13 的环境里装时遇到个别依赖编译失败虽然最后也能装上但浪费了不少时间。Windows 用户如果装完启动浏览器被杀毒软件拦截记得把项目目录加白名单这个库会临时创建浏览器实例有些安全软件会误报。3.2 最小可用示例下面这个代码是我跑通的最小可复现版本。功能非常简单打开一个网页把一个指定的页面内容读出来。import asyncio from langchain_openai import ChatOpenAI from browser_use import Agent, Browser, BrowserConfig async def main(): browser Browser(configBrowserConfig(headlessTrue)) agent Agent( task打开 https://example.com把页面上标题和第一段正文内容提取出来, llmChatOpenAI(modelyour-model-id, temperature0), browserbrowser, max_steps5, ) history await agent.run() print(history.final_result()) await browser.close() asyncio.run(main())注意几点modelyour-model-id需要换成你自己有权限调用的模型 ID这里我故意用占位符避免给你一个过时的具体模型名。ChatOpenAI来自 LangChain 的模型封装只要你的模型服务接口兼容 OpenAI 风格换成本地部署的模型也可以传进来。headlessTrue表示无头模式浏览器在后台跑不弹窗。第一次调试建议设为False你可以亲眼看模型每一步在干嘛。3.3 第一次运行你会看到什么跑起来之后控制台会输出一大段“内心戏”大致是模型的推理过程它先分析当前页面有哪些可用元素然后决定点击哪个、输入什么执行之后又看到新状态再继续决策。第一次看的同学可能会觉得信息量很大但别慌你只需要重点看两样东西它是否朝着目标前进比如先找到搜索框再输入关键词最后final_result()返回的内容是不是你想要的。如果你的模型服务配好了但任务一直卡住不动最常见的原因是模型输出格式和库不兼容或者max_steps给太少模型还没做完就被掐断。我一般查询类任务给 10表单类给 20足够它折腾。4. 实战拆解一个带登录、填表、数据提取的完整任务4.1 任务描述怎么写才不容易翻车普通的“打开网页读取标题”Demo 太温和了我们上一个真实一点的任务登录一个系统进入数据页面提取表格内容。我一开始的任务描述是“登录后查看数据看板把表格内容给我”结果模型到处瞎逛因为“表格内容”范围太大。后来我改成这样打开 https://example.com/login 在用户名字段输入 demo_user密码字段输入 demo_pass点击登录按钮。登录后进入“数据总览”菜单找到第一个表格把表格最后一列所有数值按顺序提取出来返回成列表。这样模型每一步都清楚去哪、做什么、什么时候停。在实际执行中它可能会先找“用户名输入框”而不是直接找输入框这是好事——说明它在通过语义理解来定位而不是瞎猜顺序。任务描述里如果包含账号密码建议用变量从外部读取而不是直接写死在源码里提交到仓库。我习惯用环境变量注入这样就算任务日志外泄也不会直接泄露凭据。4.2 执行过程中的常见行为观察跑这种登录类任务时你会看到模型偶尔“犹豫”它可能点了一个不是登录按钮的按钮发现没反应又看了一遍页面状态重新找按钮。这种自我纠错能力是最能体现 Agent 价值的地方。但也要注意模型有时会陷入重复动作同一类点击重复执行好几次看起来像在循环。我遇到这种情况通常调整max_actions_per_step或把任务重新拆细让每一轮决策只做一件小而明确的事。另外登录后经常有跳转、加载动画、异步渲染模型在页面还没稳定时就去点容易失败。如果网络慢可以考虑在关键节点给模型更多上下文比如“点击登录后如果显示登录成功跳转到看板页再继续下一步”。这算是提示词工程层面的一个有效套路。4.3 回放与取证history、截图和录屏的价值调试 Agent 类项目最怕的就是“它不动了但我不知道为什么”。browser-use 提供了历史记录机制agent.run()返回的 history 对象里记录了每一轮的思考、动作、执行结果。你可以把历史导出来看定位它在哪一步出了问题。还有两个非常实用的调试选项截图和录屏。开启录屏后它会保存整个浏览器操作过程的视频文件我排查复杂问题基本都是开着录屏跑的犯错之后直接回放视频一眼就能看出模型当时把鼠标点到了哪个位置。这比看日志直观太多了。我的建议是任何需要上生产环境跑的任务调试阶段必须留记录否则出了问题你只能靠猜。这个习惯帮我省了大量排查时间。5. 实测踩过的坑和调优思路5.1 Token 消耗太猛怎么办这类方案最大的隐性成本是模型 token。每轮循环都要把页面状态发给模型页面稍复杂一点一轮就是几万 token一个任务跑十几轮费用肉眼可见地上涨。我刚开始跑一个中等复杂度任务用了几十个步骤账单让我心疼。优化方向主要有这几个优化手段做法效果关闭视觉use_visionFalse不传截图只传文本树省约一半 token纯文本任务足够限制步数合理设置max_steps不要无脑给 50避免模型瞎逛浪费额度拆分任务一个大任务拆成几个小 Agent 串行执行每个 Agent 上下文更短失败重跑成本低用便宜模型简单任务用低成本模型复杂任务才用强模型成本可降低一个量级我自己的原则是能用文本树搞定的绝不开启视觉能拆的任务一定要拆。比如“搜索资料然后整理成报告”这种任务我会拆成“搜集资料”和“报告撰写”两个 Agent前者用便宜模型跑多步收集后者用强模型一次性整理。5.2 登录验证码、弹窗和 iframe 的边界处理验证码是这个方案最大的痛没有之一。模型确实可以“看”验证码图片然后尝试猜但成功率和稳定性都不够尤其是复杂扭曲的图形验证码猜错两次就可能触发账号保护机制。我建议的稳妥做法是登录这类敏感环节用传统方式解决例如手动登录一次导出 cookie 给 Agent 复用或者先用普通脚本完成登录再把登录后的会话交给 Agent 执行后续流程。这相当于把最不可控的部分剥离出去。弹窗和 iframe 也会干扰模型。弹窗出现时页面可访问性树会被弹窗内容占据模型有时会忽略背后的主页面。我遇到这种情况会在任务描述里明确写“如果出现弹窗先按 Esc 关闭再继续”。iframe 里的元素通常也能被读出来但层级较复杂时模型容易定位到错误的同名元素描述里加上 iframe 的上下文会好一些。5.3 模型选型与参数配置的实战心得用哪种模型直接决定这个方案能不能落地。我个人的感觉是简单任务查标题、翻页、点击几个链接用廉价型号完全可以胜任中长链路任务登录、填表、提取用主流闭源大模型的中档版本比较稳便宜型号容易在中间步骤忘掉任务目标需要理解复杂文案或者页面结构非常混乱的场景才需要上更强的模型。temperature一定要调低最好接近 0否则模型有时会“灵光一闪”做出不可复现的额外动作。我见过一次温度没改模型顺手把页面上某个开关给打开了排查了很久。max_steps的把握需要一点经验。给太少任务完不成给太多模型会在简单任务上反复横跳浪费钱。我的习惯是先给一个中间值比如 15跑一遍看历史记录里实际用了几步再按实际值上下浮动调整。5.4 混合模式脚本和 Agent 分工协作最稳妥用久了你会发现browser-use 并不是用来替代 Playwright 的它更适合用在“环境变化频繁”的决策节点上。我在生产项目里的做法是固定不变的步骤全部用 Playwright 脚本比如登录、打开页面、上传文件变化较多的操作交给 Agent比如页面元素的动态定位、内容理解、异常信息读取。这样分工的好处是固定部分速度快、成本低、稳定性高动态部分利用模型的泛化能力不会被网站改版轻易击穿Agent 只处理少量关键节点token 消耗也会小很多。如果你想把这套东西真正用于实际业务我非常推荐从这种混合模式起步而不是上来就让 Agent 接管一切。6. 适用边界与后续可以怎么扩展6.1 什么场景我不建议直接用 browser-use说实话这种方案并不是银弹。我会避开以下几类场景第一高频、低延迟的接口数据抓取。直接调 API 或用 requests 更高效开一个浏览器让模型去读网页属于杀鸡用牛刀。第二高并发批量任务。每个任务都启动浏览器实例资源占用非常重而且容易被目标站点的风控识别。我看到有人拿它跑几十个并发抓取结果 IP 被限制得很快。第三对交互精度要求极高的操作。比如 Canvas 画布内拖拽、WebGL 场景操作模型很难精确控制不如写专用脚本。第四涉及高价值账号的关键操作。我不建议让模型直接操作支付、核心配置等场景万一它在一个确认弹窗上点击了错误选项后果不可控。遇到这些场景我更推荐前面说的混合模式或者干脆用传统自动化方案。6.2 几个值得尝试的扩展方向如果你已经玩转了基本用法下面这几个方向我觉得性价比很高。让 Agent 生成 Playwright 代码而不是直接运行浏览器。思路是你让模型先分析页面、生成一段目标操作的 Python 代码人工审查后再执行。这样既保留了模型的灵活性又把最终执行控制权收回到确定性代码手里安全性和可维护性都更高。多 Agent 协作也可以尝试。一个 Agent 负责读取信息另一个负责填写表单它们通过消息队列传递结果各自上下文更小、专注度更高。本地小模型配合远程模型做两级调度简单任务永远走小模型遇到复杂页面再升级到更强模型能在成本上实现比较好的平衡。7. 关于方案落地我最后想分享的个人体会实测了一段时间之后我最大的体会是不要把 browser-use 当成一个全能的“AI 替身”它更像是一个“具备了自我纠错能力的自动化框架”。它最适合的场景不是替代你解决所有问题而是把规则脚本最脆弱的那部分——页面变化后的重新定位、动态内容的语义判断——接管过来让整个自动化链条变得更有韧性。调试阶段多花一点时间把任务描述打磨清楚收益非常明显。我现在每次新建一个任务都会先在录屏和历史记录的双重观察下跑一遍模型自己的“思路”然后根据它的实际行为反向调整任务描述直到它能在最少的步数内完成任务。这种调试方式比一开始就追求复杂的代码逻辑有效得多。最后再分享一个小技巧如果你是在一个长期运行的服务里用 browser-use建议给每个任务设置独立的会话、独立的浏览器实例任务结束就及时关闭避免浏览器进程残留导致的资源泄漏。我在早期跑批量任务时吃过这个亏浏览器进程越堆越多最后整个机器卡到无响应。把这些细节处理好这套方案完全可以在实际项目中稳定承担一部分自动化工作。