腾讯开源AI浏览器自动化:复用已登录浏览器,让AI真正干活
1. 这个项目到底解决了什么问题1.1 从“AI 能聊天”到“AI 能干活”的那道坎过去两年大家手里的 AI 工具基本停留在“你问我答”的阶段。你让它写一段代码、翻译一篇文章、总结一份文档它干得挺漂亮。但你要是说“帮我把后台那个报表导出来顺便把数据填进系统里”它立马就哑火了。原因很简单AI 没有手它碰不到你的浏览器更碰不到你浏览器里已经登录好的那些账号。这个痛点其实非常具体。我们日常工作中大量操作都发生在浏览器里——后台管理系统、云服务控制台、内部工单系统、数据看板。这些系统有个共同特点必须登录才能用而且很多还绑定了二次验证、短信验证码、企业 SSO。你让 AI 去操作第一步就卡在登录上。就算你把账号密码给它验证码那一关也过不去。腾讯这次开源的这个项目核心思路就一句话不跟登录较劲直接借用你已经登录好的浏览器。它通过浏览器扩展或者调试协议把当前这个已经带着你登录态Cookie、Session、Token的浏览器实例暴露给 AI Agent 去调用。AI 不需要知道你的密码也不需要过验证码它就像坐在你旁边用你的鼠标和键盘一样操作。1.2 谁最需要这个东西我梳理了一下下面这几类人看到这个项目应该会眼前一亮做后台自动化的开发每天重复登录、点菜单、填表单、导数据这些活儿完全可以交给 AI 去跑。做 AI Agent 方向的工程师之前 Agent 只能调 API现在可以操作真实网页了能力边界一下子拓宽了。做测试和运维的需要频繁在多个系统之间切换、验证功能、抓取状态这个方案能省掉大量手工操作。做数据采集和分析的很多数据在后台页面里没有开放 API只能靠浏览器操作来获取。注意这个方案的前提是你本人已经合法登录了目标系统并且操作行为符合该系统的使用条款。不要用它去绕过任何访问控制。1.3 为什么“复用已登录浏览器”比“模拟登录”聪明传统自动化方案遇到登录环节通常有三种做法一是硬编码账号密码走登录接口二是用验证码识别服务硬闯三是维护一套复杂的 Cookie 池。这三种做法都有明显缺陷——密码会变、验证码会升级、Cookie 会过期维护成本极高。而“复用已登录浏览器”这个思路本质上是把登录这件事交还给人类。你正常登录登录态天然存在于浏览器里AI 只是借用这个已经存在的会话。这就好比你不会把家门钥匙配一把给快递员而是让他在你在家的时候按门铃进来。安全性、稳定性、合规性都更好。2. 核心技术原理拆解2.1 浏览器调试协议是底层基石这个项目能跑起来靠的是 Chrome 浏览器提供的DevTools Protocol简称 CDP。你可以把它理解成浏览器对外开放的一套“遥控接口”。平时开发者按 F12 打开的那个开发者工具本身就是通过 CDP 跟浏览器通信的。CDP 能做的事情非常多打开新标签页、导航到指定 URL、点击页面元素、输入文字、执行 JavaScript、截取页面截图、监听网络请求、读取 DOM 结构。基本上你在浏览器里手动能做的操作CDP 都能用代码触发。关键点在于CDP 连接的是一个正在运行的浏览器实例。这个实例里有什么有你登录好的所有网站会话。所以 AI 通过 CDP 操作这个浏览器时天然就带着你的登录态不需要额外处理认证问题。2.2 扩展与调试端口两种接入方式根据我的实测和社区反馈这类项目通常提供两种接入路径第一种是浏览器扩展方式。安装一个扩展扩展在浏览器内部运行可以直接调用浏览器的各种 API同时通过 WebSocket 跟外部的 AI 服务通信。这种方式的优点是权限控制相对清晰扩展可以声明自己需要哪些权限用户安装时能看到。缺点是扩展的能力受限于浏览器扩展 API 的边界。第二种是远程调试端口方式。启动 Chrome 时加上--remote-debugging-port9222参数浏览器会开放一个本地调试端口。任何能访问这个端口的程序都可以通过 CDP 控制浏览器。这种方式能力最全因为 CDP 的接口比扩展 API 丰富得多。缺点是启动参数需要调整而且端口开放期间要注意本机安全。两种方式各有适用场景。如果你只是想做一些轻量的页面操作扩展方式更省事。如果你需要深度控制比如拦截网络请求、修改响应内容、执行复杂的页面脚本那调试端口方式更合适。2.3 AI 如何“看懂”页面并决定下一步浏览器控制只是手段真正的核心是 AI 怎么知道该点哪里、该填什么。这里涉及一个关键环节页面状态的语义化。原始的 HTML 对 AI 来说太啰嗦了一个按钮可能嵌套十几层 div还带着一堆看不懂的 class 名。所以项目通常会在中间做一层转换把页面元素提取成 AI 能理解的结构化描述。比如{ elements: [ {type: button, text: 提交订单, selector: #submit-btn, visible: true}, {type: input, label: 收货地址, selector: #address, value: }, {type: link, text: 返回首页, selector: a.home-link, visible: true} ] }AI 拿到这份“页面地图”后结合用户的任务描述就能推理出下一步该操作哪个元素。比如用户说“帮我提交订单”AI 看到有个“提交订单”按钮就会决定点击它。这个环节的难点在于页面元素可能动态加载、可能有多个相似元素、可能被遮挡不可见。所以好的实现会做元素可见性判断、唯一性校验、操作后状态确认。这些细节直接决定了自动化流程的稳定性。2.4 任务编排与多步操作的状态管理单步操作好做难的是多步流程。比如“登录后台 - 进入订单管理 - 筛选今天的订单 - 导出 Excel - 把文件保存到指定目录”这是一个有状态、有依赖的任务链。项目需要维护一个任务上下文记录当前进行到哪一步、上一步的结果是什么、下一步的前置条件是否满足。如果某一步失败了还要决定是重试、跳过还是终止整个流程。我见过的一些实现会用一个简单的状态机来管理每个步骤定义清楚输入、输出和失败处理策略。更复杂的会用上任务队列和优先级调度。对于大多数日常自动化场景状态机已经够用了。3. 实操落地从零跑通一个自动化流程3.1 环境准备与依赖安装假设我们要做一个实际的任务自动登录某后台系统抓取今日订单数据并导出。下面是我实测下来比较稳的一套流程。首先确认你的 Chrome 版本。打开浏览器地址栏输入chrome://version/看一下版本号。CDP 的接口在不同版本间会有细微差异建议用最近半年内的稳定版。太老的版本可能缺少某些接口太新的测试版可能有兼容性问题。然后准备 Python 环境。我习惯用虚拟环境隔离依赖python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install websocket-client requests如果你用的项目封装了更上层的库可能还需要装它自己的包。具体看项目 README 里的说明我这里给的是最基础的通信层依赖。3.2 启动带调试端口的浏览器这一步是整个流程的关键。你不能直接双击 Chrome 图标启动那样不会开放调试端口。需要用命令行启动并且指定一个独立的用户数据目录避免跟你日常用的浏览器配置冲突。Windows 下大概是这样的C:\Program Files\Google\Chrome\Application\chrome.exe ^ --remote-debugging-port9222 ^ --user-data-dirC:\chrome-debug-profilemacOS 下/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \ --remote-debugging-port9222 \ --user-data-dir/tmp/chrome-debug-profile启动后在浏览器里手动登录你的目标系统。登录完成后这个浏览器实例就带着你的登录态了。此时访问http://localhost:9222/json应该能看到当前打开的标签页列表说明调试端口工作正常。注意调试端口只监听本机不要把它暴露到公网。操作完成后及时关闭这个浏览器实例。3.3 连接浏览器并获取页面上下文下面是一段最简的连接代码用 Python 通过 WebSocket 跟 CDP 通信import requests import websocket import json # 获取当前标签页列表 resp requests.get(http://localhost:9222/json) tabs resp.json() # 找到目标页面 target None for tab in tabs: if 你的目标系统域名 in tab.get(url, ): target tab break if not target: raise Exception(没有找到目标页面请确认已登录并打开) # 建立 WebSocket 连接 ws websocket.create_connection(target[webSocketDebuggerUrl]) def send_command(method, paramsNone): msg {id: 1, method: method, params: params or {}} ws.send(json.dumps(msg)) result json.loads(ws.recv()) return result # 获取页面标题验证连接 title send_command(Runtime.evaluate, {expression: document.title}) print(当前页面标题:, title)这段代码跑通说明你的程序已经能“看到”浏览器里的页面了。接下来就是让 AI 根据页面内容决定操作。3.4 页面元素提取与 AI 决策实际项目中不会让 AI 直接读原始 HTML。通常会先做一轮元素提取把可交互的元素整理成结构化数据。下面是一个简化的提取脚本// 在页面中执行的 JS提取可交互元素 function extractInteractiveElements() { const selectors button, a, input, select, textarea, [rolebutton]; const elements document.querySelectorAll(selectors); const result []; elements.forEach((el, index) { const rect el.getBoundingClientRect(); const visible rect.width 0 rect.height 0; if (!visible) return; result.push({ index: index, tag: el.tagName.toLowerCase(), type: el.type || , text: (el.innerText || el.value || el.placeholder || ).trim().slice(0, 50), id: el.id || , name: el.name || , className: el.className || }); }); return result; }把这份结果连同用户的任务描述一起发给 AIAI 就能推理出操作序列。比如用户说“导出今天的订单”AI 看到有个“导出”按钮和一个日期筛选框就会生成“先设置日期为今天再点击导出”这样的操作计划。3.5 执行操作与结果验证AI 给出操作计划后程序通过 CDP 执行。点击操作可以用Input.dispatchMouseEvent输入文字可以用Input.insertText也可以用Runtime.evaluate直接执行 JS 来触发点击。我实测下来用 JS 触发点击更稳定因为不受元素坐标和滚动位置影响# 通过 JS 点击指定元素 click_script (function() { const el document.querySelector(%s); if (el) { el.click(); return clicked; } return not found; })() % selector result send_command(Runtime.evaluate, {expression: click_script})操作执行后一定要做结果验证。比如点击导出后等待几秒检查页面上是否出现了“导出成功”的提示或者检查下载目录里是否多了文件。没有验证的自动化就是耍流氓出了问题你都不知道。4. 踩坑记录与常见问题排查4.1 元素定位失败的几种典型情况做浏览器自动化十次失败有八次是元素定位问题。我整理了一个排查表现象可能原因排查方法找不到元素页面还没加载完加等待用document.readyState判断找到多个元素选择器不够精确用更具体的 id 或组合选择器元素不可点击被弹窗遮挡先关闭弹窗或检查 z-index点击没反应元素是动态绑定的改用触发事件的方式或模拟真实鼠标事件输入框填不进去有输入掩码或校验先 focus再逐字符输入我踩过最坑的一次是页面上有两个“提交”按钮一个在表单里一个在页面底部。用文本匹配选到了底部那个点了半天没反应。后来改成用表单的 id 做父级限定才定位准确。4.2 登录态失效与页面跳转的处理即使复用了已登录浏览器登录态也可能中途失效。比如 Session 超时、被其他端踢下线、系统强制重新认证。这时候页面会跳转到登录页你的自动化脚本如果还在傻等原来的元素就会一直超时。处理办法是在每个关键步骤前先检查当前 URL 和页面特征。如果发现跳到了登录页就暂停流程并通知人工处理。不要试图自动重新登录那会把事情搞复杂。def check_login_status(): url send_command(Runtime.evaluate, {expression: window.location.href}) if login in url.get(result, {}).get(result, {}).get(value, ): raise Exception(登录态已失效请手动重新登录)4.3 动态加载与异步渲染的等待策略现代前端框架大量使用异步渲染页面刚打开时元素可能还不存在。硬编码sleep(3)是最蠢的做法快了会失败慢了浪费时间。更好的策略是轮询等待设置一个超时上限import time def wait_for_element(selector, timeout10): start time.time() while time.time() - start timeout: result send_command(Runtime.evaluate, { expression: fdocument.querySelector({selector}) ! null }) if result.get(result, {}).get(result, {}).get(value): return True time.sleep(0.5) return False这个模式我用了很多次比固定等待靠谱得多。超时时间根据页面复杂度调整一般 10 到 30 秒够用。4.4 多标签页与 iframe 的坑有些系统会在新标签页打开功能或者把内容嵌在 iframe 里。CDP 默认只控制当前标签页遇到 iframe 需要先获取 frame 的上下文。多标签页的处理方式是监听Target.targetCreated事件发现新标签页后切换过去。iframe 则需要用Page.getFrameTree拿到 frame 列表再用Runtime.evaluate时指定contextId。这两个坑我都踩过尤其是 iframe元素明明在页面上能看到但就是选不到折腾了半天才发现是在 iframe 里。4.5 性能与资源占用的平衡浏览器自动化跑起来之后内存和 CPU 占用会明显上升。如果同时开多个标签页跑任务机器可能会卡。我的经验是单个浏览器实例同时只跑一个任务流不要并发操作多个标签页。任务完成后及时关闭不需要的标签页释放内存。如果任务量大用多个浏览器实例分担每个实例用独立的用户数据目录。定期重启浏览器实例避免长时间运行导致的内存泄漏。5. 这个方向还能怎么扩展5.1 结合定时任务做无人值守把自动化脚本挂到定时任务上比如每天早上九点自动登录后台抓取前一天的订单数据生成报表发到指定邮箱。这种场景下浏览器需要保持登录态。可以设置浏览器开机自启或者用脚本定期检查登录状态并提醒。5.2 多系统串联的复合流程单个系统的自动化只是起点。真正的效率提升来自于跨系统串联。比如从 A 系统导出数据处理后导入 B 系统再把结果同步到 C 系统。这种流程以前需要人工在多个系统之间切换现在可以串成一条自动化链路。关键是要处理好系统之间的数据格式转换和异常传递。任何一个环节失败都要能定位到具体是哪个系统出了问题。5.3 与 AI 能力深度结合目前大多数实现还是“AI 决策 脚本执行”的模式。更进一步的做法是让 AI 在每一步都能看到执行结果并根据结果动态调整策略。比如点击按钮后页面报错AI 能读懂错误信息并尝试其他操作路径。这就从“自动化”升级到了“智能化”。我在实际使用中的体会是这套方案最大的价值不是省了多少点击而是把人的注意力从重复操作中解放出来。你只需要描述目标剩下的交给 AI 去执行。当然前提是你要把边界划清楚哪些操作可以自动做哪些必须人工确认这个分寸得把握好。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →