ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Computer Use 与 Browser Use 实战:用 Playwright+CDP 搭建界面感知到自动化执行链路

Computer Use 与 Browser Use 实战:用 Playwright+CDP 搭建界面感知到自动化执行链路 1. 从截图坐标到元素定位为什么需要 PlaywrightCDPComputer Use 和 Browser Use 经常被混着讲但落到工程上它们解决的是两个不同层次的问题。Computer Use 面向的是整个操作系统界面Agent 看到的是屏幕像素决策输出的是坐标点击Browser Use 面向的是网页Agent 拿到的是 DOM 结构、无障碍语义和浏览器内部状态决策输出的是“点击那个叫登录的按钮”这类语义化指令。两者共享同一个循环读取状态、模型决策、程序执行、检查结果。区别在于“状态”从哪来、“执行”往哪去。Computer Use 靠截图加辅助功能树执行靠 pyautogui 这类系统级自动化库Browser Use 靠 DOM 快照加 CDP 暴露的浏览器能力执行靠 Playwright 这类浏览器自动化库。我试过纯截图方案跑网页任务最直接的坑是分辨率适配。同一套坐标在 1080p 上点得准换到 2K 屏就偏了页面滚动后坐标全废。而 Playwright 的定位器查询的是当前 DOM页面重新渲染后同一个getByRole还能重新定位到对应元素稳定性完全不是一个量级。所以这篇要搭的链路是用 CDP 做底层感知截图、DOM 快照、网络事件用 Playwright 做元素定位和动作执行中间夹一层 Agent 调度逻辑。目标是跑通一个最小闭环——Agent 能“看到”页面、决定下一步、执行动作、再验证结果。适合谁看已经会用 Playwright 做基础自动化但想把 LLM 决策接进来的开发者或者在做 Browser Use 类产品需要一套可复制的感知-执行骨架。下面从环境准备开始一步步把链路搭起来。2. TaoToken 前置把模型决策接进链路Agent 循环里“模型决策”这一步需要一个能调用的 LLM 接口。TaoToken 在这里的角色是提供统一的模型调用入口让 Playwright 脚本里的决策函数不用关心底层是哪个模型。先拿 API Key。访问 https://taotoken.net/api-keys 创建密钥控制台在 https://taotoken.net/console 。拿到 key 后模型对话调试可以用 https://taotoken.net/model-chat 先验证接口通不通。如果你后面要做长期编码或 Agent 任务Coding Plan 页面 https://taotoken.net/coding-plan 有更完整的配额说明。接入文档在 https://taotoken.net/doc API 基址是https://taotoken.net/api。环境变量这样配export TAOTOKEN_API_KEYsk-你的密钥 export TAOTOKEN_BASE_URLhttps://taotoken.net/apiPython 侧装依赖pip install playwright openai playwright install chromiumplaywright install chromium会下载 Chromium 二进制后面 CDP 连接的就是这个浏览器实例。注意不要用系统自带的 Chrome版本对不上时 CDP 的某些域会报错。3. 可复制配置PlaywrightCDP 感知层骨架3.1 启动带 CDP 的浏览器实例Playwright 默认启动的浏览器已经开了 CDP但端口是随机的。要手动控制用launch时指定argsfrom playwright.sync_api import sync_playwright def launch_browser(): pw sync_playwright().start() browser pw.chromium.launch( headlessFalse, args[ --remote-debugging-port9222, --disable-blink-featuresAutomationControlled, ], ) context browser.new_context( viewport{width: 1280, height: 800}, user_agentMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, ) page context.new_page() return pw, browser, context, page--remote-debugging-port9222是关键后面可以用http://localhost:9222/json查看当前页面列表。--disable-blink-featuresAutomationControlled减少被网站识别为自动化的概率但别指望它能绕过所有检测。3.2 用 CDP 抓取页面快照Playwright 的page.content()拿的是完整 HTML对模型来说太长。更实用的做法是用 CDP 的Accessibility域拿无障碍树再配合DOM域做精简def get_page_snapshot(page): cdp page.context.new_cdp_session(page) cdp.send(Accessibility.enable) ax_tree cdp.send(Accessibility.getFullAXTree) nodes [] for node in ax_tree.get(nodes, []): role node.get(role, {}).get(value, ) name node.get(name, {}).get(value, ) if role in (button, link, textbox, checkbox) and name: nodes.append({role: role, name: name}) return nodes这个快照只保留可交互元素模型拿到的输入从几万字符降到几百字符。实测下来一个典型登录页的 AX 树精简后大概 15 个节点模型决策准确率比喂完整 HTML 高不少。3.3 截图感知作为补充有些元素 AX 树里没有比如 canvas 绘制的图表或自定义组件。这时候用 CDP 的Page.captureScreenshotdef capture_screenshot(page, pathsnapshot.png): cdp page.context.new_cdp_session(page) result cdp.send(Page.captureScreenshot, {format: png}) import base64 with open(path, wb) as f: f.write(base64.b64decode(result[data])) return path截图和 AX 树组合使用AX 树负责结构化定位截图负责兜底视觉理解。模型决策时优先用 AX 树找不到目标再让它看截图。4. Agent 调度示例从感知到执行的完整循环4.1 决策函数把页面快照和任务描述发给模型让它输出下一步动作。用 OpenAI 兼容接口调 TaoTokenfrom openai import OpenAI import json client OpenAI( api_keyos.environ[TAOTOKEN_API_KEY], base_urlos.environ[TAOTOKEN_BASE_URL], ) def decide_action(task, snapshot, history): prompt f任务{task} 当前页面可交互元素 {json.dumps(snapshot, ensure_asciiFalse, indent2)} 已执行动作{history} 请输出下一步动作JSON 格式 {{action: click|type|navigate|done, target: 元素名称, value: 输入内容}} 只输出 JSON。 resp client.chat.completions.create( modelgpt-4o, messages[{role: user, content: prompt}], temperature0, ) return json.loads(resp.choices[0].message.content)temperature0让输出稳定避免同一页面两次决策给出不同动作。4.2 执行函数把模型输出的语义动作翻译成 Playwright 调用def execute_action(page, action): act action[action] if act click: page.get_by_role(button, nameaction[target], exactFalse).click() elif act type: page.get_by_role(textbox, nameaction[target], exactFalse).fill(action[value]) elif act navigate: page.goto(action[value]) elif act done: return True page.wait_for_load_state(networkidle) return Falsewait_for_load_state(networkidle)等网络空闲再进入下一轮感知避免页面还没渲染完就抓快照。4.3 主循环def run_agent(task, max_steps10): pw, browser, context, page launch_browser() history [] try: page.goto(https://example.com/login) for step in range(max_steps): snapshot get_page_snapshot(page) action decide_action(task, snapshot, history) history.append(action) print(fStep {step}: {action}) if execute_action(page, action): print(任务完成) break finally: browser.close() pw.stop()跑起来后终端会打印每一步的决策页面会跟着动。这就是最小闭环感知AX 树→ 决策TaoToken 调模型→ 执行Playwright→ 再感知。5. 本篇常见错排查5.1 CDP session 报 “Target closed”原因通常是new_cdp_session之后页面被导航或关闭了。CDP session 绑定在特定 page 上页面一变就失效。解决每次感知前重新创建 session或者把 session 创建放在page.goto之后。5.2 getByRole 找不到元素先确认 AX 树里有没有这个节点。用get_page_snapshot打印出来看如果节点存在但 Playwright 找不到可能是exact参数太严。把exactFalse改成模糊匹配或者换get_by_text。另一个坑是 iframe。AX 树默认只抓主框架iframe 里的元素要单独处理frame page.frame_locator(iframe[namelogin]) frame.get_by_role(button, name登录).click()5.3 模型输出不是合法 JSON加一层容错import re def parse_action(text): match re.search(r\{.*\}, text, re.DOTALL) if match: return json.loads(match.group()) raise ValueError(f无法解析动作: {text})如果模型经常输出多余解释在 prompt 里加一句“不要输出任何解释只输出 JSON”。5.4 页面加载慢导致快照为空wait_for_load_state(networkidle)在 SPA 页面可能永远等不到。改成等具体元素page.wait_for_selector([rolebutton], timeout5000)或者用 CDP 的Page.loadEventFired事件做同步。5.5 TaoToken 接口返回 401检查TAOTOKEN_API_KEY环境变量有没有正确导出。在 Python 里打印os.environ.get(TAOTOKEN_API_KEY)确认。如果 key 没问题检查base_url是不是https://taotoken.net/api末尾不要加斜杠。6. 下一步把链路接到真实任务跑通最小闭环后可以往几个方向扩展。一是把感知层做厚除了 AX 树和截图再加 CDP 的Network域监听请求让 Agent 知道页面在加载什么数据。二是把执行层做稳给每个动作加超时和重试失败时自动重新感知再决策。三是把决策层做细用多轮对话让模型能追问“这个按钮点完之后页面变了没有”。长期跑编码或 Agent 任务的话Coding Plan 页面 https://taotoken.net/coding-plan 有配额和模型选择的说明。接入细节看文档 https://taotoken.net/doc 模型调试用 https://taotoken.net/model-chat 。API Key 在 https://taotoken.net/api-keys 管理。这套骨架的价值在于把“界面感知”和“自动化执行”解耦了。感知层换成语义树、截图或网络事件执行层换成 Playwright、CDP 或系统级库中间的决策循环不用大改。你可以先拿一个登录页跑通再换成自己业务里的表单填写或数据抓取逐步把链路调稳。
返回列表