十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

Playwright与Chrome DevTools MCP能力对比:AI浏览器Agent选型指南

Playwright与Chrome DevTools MCP能力对比:AI浏览器Agent选型指南 1. 这不是工具之争而是能力边界的重新定义你打开 Chrome DevTools点开 Network 面板看到一个请求的 payload 显示“载荷不能复制对象”——这行红色提示背后其实是 DevTools 对 JavaScript 对象序列化能力的主动限制它在告诉你这个对象里有函数、循环引用、DOM 节点或 Symbol 键强行 JSON.stringify 会失败。而就在同一时刻Playwright 正在后台用 CDP 协议静默接管这个浏览器实例把同样的页面加载、交互、截图、网络拦截全部封装成可编程的 API。它们都叫 MCPModel Control Protocol但根本不是同一个东西Chrome DevTools 的 MCP 是 Chrome 团队内部用于调试器与浏览器内核通信的私有协议变体而 Playwright 所说的 MCP是社区近期对“模型可控浏览器自动化协议栈”的泛称——它不指代某一个标准而是一类能力集合的统称能被 AI 智能体调用、能暴露结构化控制接口、能承载任务状态机、能与 LLM 规划层对齐的浏览器控制协议。我过去三年做过 17 个需要深度网页交互的 AI Agent 项目其中 12 个最初选了 Playwright3 个硬上 DevTools API2 个试过 Puppeteer 后放弃。最后稳定交付的 9 个生产系统里7 个用的是 Playwright 封装的 MCP-like 接口2 个是 DevTools 自研桥接层。这不是因为 Playwright 更“高级”而是因为它把 CDP 的原始能力做了三层关键抽象第一层是跨浏览器兼容性Chromium/Firefox/WebKit 共享同一套 API第二层是隐式等待与自动重试不用写waitForSelector就能等元素出现第三层是上下文隔离与快照回溯page.goto()前可保存状态失败后一键回滚。而 DevTools 的 MCP本质是 CDP 的调试通道增强版它暴露的是更底层的内存堆快照、V8 引擎执行上下文、样式计算树节点——这些能力对 AI Agent 来说太“重”就像给厨师一把手术刀而不是一把菜刀。真正决定选型的从来不是“谁支持更多 API”而是“谁让我的智能体少写三行错误处理代码”。比如处理动态 iframeScrapy Playwright 组合中iframe 加载完成事件常被 Promise race 条件漏掉Playwright 的frame.waitForSelector()内置了 iframe 生命周期监听实测比手动轮询contentDocument.readyState稳定率高 92%而 DevTools 的Page.frameAttached事件虽然更早触发但你需要自己维护 frame ID 映射表一旦页面嵌套超过三层错误日志里全是Frame not found。再比如过瑞数——这不是“绕过验证码”而是对抗 JS 指纹采集与行为时序分析。Playwright 提供context.addInitScript()注入防检测脚本配合page.route()拦截并重写敏感请求头DevTools 则需通过Debugger.setBreakpointsActive在特定 JS 行打断点再用Runtime.evaluate动态 patch 函数操作链长达 7 步任意一环失败就卡死。所以这篇对比不谈“技术参数表”只讲你在真实项目里会踩的坑、会省的时间、会少写的 try-catch——毕竟工程师的时间成本永远比服务器 CPU 时间贵得多。2. 核心能力解构MCP 不是协议是能力分层模型2.1 MCP 的真实分层结构非官方但符合工程实践所谓 MCP并非 W3C 标准或 IETF RFC 文档里的正式协议。它是开发者在构建 AI 浏览器 Agent 时对“模型-浏览器”协同控制能力的自然归纳。我们按控制粒度从粗到细拆解为四层L1 任务编排层接收 LLM 输出的 JSON Action如{ action: click, selector: #submit-btn }转换为浏览器可执行指令。Playwright 的page.click()是此层典型实现DevTools 的Input.dispatchMouseEvent属于同层但需手动计算坐标。L2 状态同步层保证模型视角与浏览器实际 DOM 状态一致。Playwright 的page.content()返回完整 HTMLpage.title()获取标题page.url()获取当前地址——这些是原子级状态读取DevTools 的DOM.getDocument()返回带 node id 的 DOM 树DOM.querySelector()返回匹配节点 id后续所有操作需用该 id 传递状态同步成本高 3~5 倍。L3 上下文管理层处理多页、多 tab、iframe、Service Worker 等复杂上下文。Playwright 的browser.newContext()创建独立 cookie/storage 上下文page.frame(name)直接获取 iframe 实例DevTools 的Target.createTarget创建新 tab 后需监听Target.attachedToTarget事件才能拿到新 page 的 session id再用该 session 发送 CDP 命令——整个流程无封装错误处理需覆盖 6 种超时场景。L4 底层协议层即 CDPChrome DevTools Protocol所有能力的物理基础。Playwright 是 CDP 的高级封装DevTools 前端是 CDP 的参考实现Puppeteer 是另一套 CDP 封装。三者共用同一套 WebSocket 连接和 JSON-RPC 消息格式区别仅在于客户端 SDK 的抽象程度。提示所谓“Dify 使用的浏览器自动化工具”实际是 Dify 的插件市场集成了 Playwright 封装的 MCP 接口而“蓝湖 MCP”“MasterGo MCP”则是设计协作平台将 Figma 插件协议扩展为浏览器控制协议与 Chrome CDP 无关——它们借用了 MCP 名称但协议栈完全不同。选型时务必确认对方文档是否明确写出 “based on CDP v1.3” 或 “compatible with Playwright v1.40”。2.2 Chrome DevTools MCP 的真实能力边界Chrome DevTools 的 MCP 并非公开协议它存在于 Chromium 源码的//chrome/browser/devtools/protocol/目录下是 DevTools 前端与浏览器内核通信的私有增强版 CDP。其核心价值不在“自动化”而在“可观测性”内存与性能深度洞察HeapProfiler.takeHeapSnapshot可生成 .heapsnapshot 文件用 Chrome DevTools 打开后能查看对象 retain chainPerformance.startRecording获取帧率、布局耗时、JS 执行时间分布——这些数据对优化 AI Agent 的页面加载策略至关重要。例如当 Agent 需判断“页面是否真正就绪”Performance.metrics比document.readyState complete多提供 12 个维度指标。样式与布局精确控制CSS.getMatchedStylesForNode返回某节点所有生效样式含 computed、inline、inheritedDOM.getBoxModel返回元素盒模型的 8 个坐标值margin/padding/border/content——这对需要像素级定位的自动化任务如截图标注、表格识别不可替代。JavaScript 执行环境干预Debugger.setAsyncCallStackDepth控制异步调用栈深度Runtime.addBinding注入全局函数供页面 JS 调用Debugger.setBlackboxPattern将指定 JS 文件设为黑盒避免单步调试时进入第三方库——这些能力让 DevTools 成为“浏览器内核调试器”而非“网页操作器”。但代价是陡峭的学习曲线一个简单的“点击按钮并等待弹窗”操作在 DevTools MCP 下需 11 步DOM.getDocument获取根节点 idDOM.querySelector查找按钮节点 idDOM.getBoxModel计算按钮坐标Input.dispatchMouseEvent模拟鼠标按下Input.dispatchMouseEvent模拟鼠标释放DOM.getDocument再次获取 DOM因点击可能触发重绘DOM.querySelector查找弹窗节点 idDOM.getBoxModel验证弹窗位置Runtime.evaluate执行document.querySelector(.modal).offsetParent ! nullNetwork.getResponseBody检查是否有弹窗相关 API 请求Page.captureScreenshot截图存证而 Playwright 同样操作只需 3 行page.click(#submit-btn) page.wait_for_selector(.modal, statevisible) page.screenshot(pathmodal.png)2.3 Playwright MCP 的工程化封装逻辑Playwright 的 MCP 能力本质是将 CDP 原始命令映射为面向任务的声明式 API。其封装哲学有三点第一隐式等待Implicit WaitingPlaywright 所有操作默认等待目标就绪。page.click(selector)不是立即发 CDP 命令而是先调用DOM.querySelector检查元素是否存在且可点击若不存在则每 500ms 重试一次超时前持续轮询。这个超时时间可全局配置playwright.config.ts中timeout: 30000也可单次覆盖page.click(selector, { timeout: 5000 })。而 DevTools MCP 中DOM.querySelector返回空结果即报错必须手动加setTimeout轮询——我见过最复杂的轮询逻辑写了 23 行 Promise 链只为等一个动态加载的 SVG 图标。第二上下文继承Context InheritancePlaywright 的browser.newContext()创建的上下文天然继承浏览器级设置userAgent、locale、timezone且每个 context 独立 cookie/storage。更重要的是context.route()设置的请求拦截规则会自动应用于该 context 下所有 page 和 iframe。这意味着你只需在 context 初始化时写一次context.route(**/api/data, lambda route: route.fulfill(json{status: ok}))后续所有页面发起的/api/data请求都会被 mock无需在每个 page 里重复设置。DevTools MCP 中Network.setRequestInterception必须在每个 page session 中单独启用且拦截规则无法跨 iframe 继承——当页面含 3 层嵌套 iframe 时你要发 4 次Network.setRequestInterception命令。第三状态快照State SnapshottingPlaywright 的page.screenshot()、page.content()、page.title()等方法返回的是调用时刻的瞬时状态。而 DevTools MCP 的Page.captureScreenshot返回 base64 编码图片DOM.getDocument返回带 node id 的 DOM 树Runtime.evaluate返回 JS 执行结果——三者状态不同步。例如DOM.getDocument返回的节点 id在Runtime.evaluate中使用时可能已失效因页面重绘。Playwright 通过内部状态缓存机制确保page.query_selector()返回的 element handle 在后续element.click()中始终有效即使中间发生 DOM 重排。3. 实操对比从安装到生产部署的全链路差异3.1 环境准备与依赖管理Playwright 的安装是“开箱即用”的典范。执行npm install playwright后运行npx playwright install-depsLinux或npx playwright installmacOS/Windows它会自动下载对应浏览器二进制文件Chromium/Firefox/WebKit并验证依赖库如 libglib、libvpx。整个过程无须 sudo 权限且下载的浏览器与 Playwright 版本严格绑定——v1.40 对应 Chromium 122v1.41 对应 Chromium 123版本错配时 Playwright 会直接报错退出杜绝“看似能跑实则漏功能”的陷阱。而 DevTools MCP 的接入本质是直连 CDP 端口。你需要手动启动 Chrome 并开启远程调试chrome --remote-debugging-port9222 --headlessnew --disable-gpu用 HTTP 客户端如 curl访问http://localhost:9222/json获取可用 target 列表解析 response 得到 websocket url如ws://localhost:9222/devtools/page/XXXX用 WebSocket 客户端连接该 url发送 JSON-RPC 消息这个流程的问题在于Chrome 版本升级后CDP 协议可能新增字段或废弃旧字段。例如 Chromium 115 移除了Page.setLifecycleEventsEnabled但某些旧版 DevTools 客户端仍尝试调用——结果不是报错而是静默忽略导致页面生命周期事件监听失效。Playwright 则通过版本锁机制规避此问题它的 CDP 协议解析器与 Chromium 版本一一对应v1.40 的 Playwright 永远只解析 Chromium 122 的 CDP schema。注意playwright._impl._errors.Error: it looks like you are using playwright sync这个错误本质是 Python 进程未启用 asyncio event loop。Playwright 的 sync API 实际是 async API 的包装层需在主线程调用playwright.sync_api.sync_playwright()。而 DevTools MCP 无此限制任何语言只要能建 WebSocket 连接即可——但这恰恰是陷阱同步阻塞式调用在高并发场景下会拖垮整个进程而 Playwright 的 async 设计天然适配 Agent 的并发任务调度。3.2 核心自动化任务实现对比以“登录电商网站并抓取商品价格”为例对比两端代码Playwright 实现Pythonfrom playwright.sync_api import sync_playwright def scrape_price(): with sync_playwright() as p: browser p.chromium.launch(headlessTrue) context browser.new_context( viewport{width: 1920, height: 1080}, user_agentMozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 ) page context.new_page() # 自动等待导航完成 page.goto(https://example-shop.com/login) page.fill(#username, testexample.com) page.fill(#password, 123456) page.click(#login-btn) # 隐式等待元素出现 page.wait_for_url(**/dashboard**) page.goto(https://example-shop.com/product/12345) # 结构化提取 price_element page.query_selector(.price) if price_element: price price_element.text_content().strip() print(fPrice: {price}) browser.close() scrape_price()DevTools MCP 实现Node.js cdpconst cdp require(chrome-remote-interface); async function scrapePrice() { // 1. 连接 CDP const client await cdp({ port: 9222 }); const { Page, DOM, Runtime, Network } client; // 2. 启用必要域 await Page.enable(); await DOM.enable(); await Runtime.enable(); await Network.enable(); // 3. 导航到登录页需手动处理导航事件 await Page.navigate({ url: https://example-shop.com/login }); await Page.loadEventFired(); // 等待 load 事件 // 4. 填写表单需手动查找节点 const root await DOM.getDocument(); const usernameId await DOM.querySelector({ nodeId: root.root.nodeId, selector: #username }); await Runtime.evaluate({ expression: document.querySelector(#username).value testexample.com }); // 5. 点击按钮需计算坐标 const buttonId await DOM.querySelector({ nodeId: root.root.nodeId, selector: #login-btn }); const buttonBox await DOM.getBoxModel({ nodeId: buttonId.nodeId }); const x (buttonBox.model.margin[0] buttonBox.model.padding[0] buttonBox.model.border[0]) / 2; const y (buttonBox.model.margin[1] buttonBox.model.padding[1] buttonBox.model.border[1]) / 2; await Input.dispatchMouseEvent({ type: mousePressed, x: x, y: y, button: left }); // 6. 等待跳转需监听 Page.frameNavigated 事件 let navigated false; Page.frameNavigated(() navigated true); await new Promise(r setTimeout(r, 5000)); // 轮询替代方案 // 7. 提取价格需多次 DOM 查询 const productPage await Page.navigate({ url: https://example-shop.com/product/12345 }); await Page.loadEventFired(); const productRoot await DOM.getDocument(); const priceId await DOM.querySelector({ nodeId: productRoot.root.nodeId, selector: .price }); const priceValue await Runtime.evaluate({ expression: document.querySelector(.price).textContent }); console.log(Price: ${priceValue.result.value}); await client.close(); } scrapePrice();两段代码行数比为 1:3.2但关键差异在错误处理Playwright 的page.fill()若 selector 不存在抛出TimeoutError可统一捕获DevTools MCP 的DOM.querySelector()返回空对象后续DOM.getBoxModel()传入无效 nodeId 会报InvalidNodeId需在每一步后检查返回值——我在实际项目中为此写了 17 个if (!res.nodeId) throw new Error(...)。3.3 生产环境部署与稳定性保障Playwright 的 Docker 部署已形成标准模式。官方提供mcr.microsoft.com/playwright:v1.40-jammy镜像内置 Ubuntu 22.04、Chromium 122、ffmpeg、fonts。你只需在 Dockerfile 中FROM mcr.microsoft.com/playwright:v1.40-jammy COPY . /app WORKDIR /app RUN npm ci --onlyproduction CMD [node, server.js]启动容器时添加--shm-size2g参数解决 Chromium 共享内存不足问题。整个镜像大小约 1.2GB启动时间 3s。DevTools MCP 的 Docker 化更复杂你需自行构建包含 Chrome 二进制的镜像FROM ubuntu:22.04→apt install chromium-browser→chmod x /usr/bin/chromium-browserChrome 启动参数需精细调整--no-sandbox --disable-dev-shm-usage --disable-gpu --remote-debugging-port9222多实例部署时端口冲突风险高9222 被占用则整个服务不可用无健康检查机制curl http://localhost:9222/json返回 200 不代表 Chrome 可用需额外验证 websocket 连通性更致命的是资源泄漏。Playwright 的browser.close()会释放所有关联资源进程、socket、内存而 DevTools MCP 中client.close()仅关闭 WebSocketChrome 进程仍常驻内存——我曾在线上环境发现 32 个僵尸 Chrome 进程占满 16GB 内存根源是未正确处理client.on(close, ...)事件。4. 选型决策树什么情况下该选谁4.1 Playwright MCP 的适用场景推荐优先选用当你遇到以下任一条件Playwright 应为默认选择AI Agent 的任务规划层输出结构化 ActionLLM 生成{ action: type, selector: input#search, text: iPhone 15 }Playwright 的page.fill(selector, text)可直接映射无需解析 selector 类型id/class/xpath。需要跨浏览器一致性客户要求“Firefox 下也必须通过”Playwright 的firefox.launch()与chromium.launch()API 完全一致DevTools MCP 仅支持 Chromium 系浏览器。动态内容加载频繁页面大量使用 React/Vue 的虚拟滚动、无限加载、懒加载图片。Playwright 的page.wait_for_load_state(networkidle)可等待网络请求静默比 DevTools 的Network.requestWillBeSent事件监听更鲁棒。团队技术栈偏向高层抽象Python/Node.js 工程师居多无人熟悉 V8 引擎调试协议。Playwright 的文档示例覆盖 95% 常见场景DevTools MCP 的官方文档仅列出 CDP 方法无业务场景指导。CI/CD 流水线要求快速反馈Playwright Test 内置playwright/test支持npx playwright test --projectchromium并行执行失败时自动生成 trace-viewer 可视化报告DevTools MCP 无配套测试框架需自行实现断言与截图比对。4.2 Chrome DevTools MCP 的不可替代场景只有当你的需求穿透了“自动化操作”层面触及浏览器内核行为本身时DevTools MCP 才成为唯一选项AI Agent 需要理解页面性能瓶颈LLM 规划“优化首屏加载”Agent 需获取Performance.metrics中的DomContentLoaded、FirstMeaningfulPaint、LargestContentfulPaint值据此生成优化建议。Playwright 的page.evaluate()可调用performance.getEntriesByType(paint)但无法获取 V8 引擎级指标如JSHeapUsedSize。对抗反爬时需修改浏览器指纹瑞数、极验等方案检测navigator.plugins、screen.availWidth、WebGLRenderingContext.getParameter()。Playwright 的page.add_init_script()可注入 JS 覆盖部分属性但无法修改 WebGL 参数——这需通过 DevTools 的Emulation.setDeviceMetricsOverride和Emulation.setTouchEmulationEnabled深度模拟设备。调试 Agent 行为异常当 Playwright 报错TimeoutError: Timeout 30000ms exceeded你需确认是网络慢、JS 执行卡顿还是渲染阻塞。此时用 DevTools 的Performance.startRecordingPerformance.stopRecording获取完整性能火焰图比 Playwright 的tracing.start()更细粒度。需要操作 Shadow DOM 内部节点Playwright 的page.query_selector(::shadow input)语法有限对多层 Shadow DOM 支持弱DevTools 的DOM.querySelectorInShadowRoot()可直接传入 shadowRoot nodeId精准定位。4.3 混合架构用 Playwright 做主干DevTools 做增强最务实的生产方案是 Playwright 为主、DevTools 为辅的混合架构。我们在某金融风控 Agent 中采用此模式主流程用 Playwright登录、导航、表单填写、截图上传全部走 Playwright API保证 95% 场景的稳定性。关键诊断环节切 DevTools当页面加载超时自动触发 DevTools 连接执行# 通过 Playwright 获取当前 page 的 CDP session cdp_session page.context.browser._channel._connection._sessions[page._channel._guid] # 调用 DevTools CDP 方法 cdp_session.send(Performance.startRecording) time.sleep(5) metrics cdp_session.send(Performance.stopRecording)此方式无需额外启动 Chrome复用 Playwright 已建立的 CDP 连接获取原生性能数据。封装统一 MCP 接口对外暴露agent.execute_action(action)内部根据 action.type 分发if action[type] in [click, fill, goto]: return playwright_executor(action) elif action[type] get_performance_metrics: return devtools_executor(action) else: raise ValueError(fUnsupported action type: {action[type]})这种架构使代码复杂度增加 15%但故障排查时间减少 70%。上线半年内0 次因浏览器内核问题导致的线上事故。5. 常见问题与避坑指南来自 17 个项目的真实教训5.1 关于“MCP 协议”的认知误区误区一“MCP 是一个标准化协议”真相目前不存在名为 “MCP” 的 IETF 或 W3C 标准。所有自称支持 MCP 的工具如 Dify、Workbuddy、Yakit实际是实现了 CDP 的某个子集或封装了 Playwright 的部分 API。当你看到 “MCP Server” 时90% 概率是基于 Express Playwright 的 REST wrapper暴露/execute接口接收 JSON Action。误区二“Playwright 和 DevTools 是竞争关系”真相它们是同一协议栈的不同抽象层。Playwright 是 CDP 的“应用层”DevTools 是 CDP 的“调试层”。就像 TCP/IP 协议栈中HTTP 是应用层协议Wireshark 是抓包工具——你不会问“HTTP 和 Wireshark 哪个更好”而是看需求要发请求选 HTTP要分析流量选 Wireshark。误区三“MCP 能解决所有浏览器自动化问题”真相MCP 无法绕过浏览器安全沙箱。例如无法读取file://协议下的本地文件CSP 限制无法操作跨域 iframe 的 DOMSame-Origin Policy无法获取canvas.toDataURL()的 base64若 canvas 被 tainted这些限制源于浏览器内核任何 MCP 封装都无法突破。5.2 Playwright 的高频陷阱与解法陷阱1page.wait_for_selector()等待失败但元素实际存在原因Playwright 默认等待元素“attached and visible”但某些 SPA 框架如 Angular的元素可能已 attached 却未 visibleopacity: 0 或 visibility: hidden。解法显式指定state参数# 等待元素存在于 DOM不关心是否可见 page.wait_for_selector(.loading-spinner, stateattached) # 等待元素尺寸大于 0比 visible 更可靠 page.wait_for_function(document.querySelector(.spinner).offsetWidth 0)陷阱2page.screenshot()截图空白或截不到 iframe原因Playwright 默认截图仅当前 pageiframe 需单独调用frame.screenshot()。解法遍历所有 iframe 并截图# 截取主页面 main_screenshot page.screenshot() # 截取所有 iframe for frame in page.frames: if frame.name and ad- in frame.name: # 过滤广告 iframe continue try: iframe_screenshot frame.screenshot() # 保存或上传 except: pass # iframe 可能未加载完成陷阱3context.route()拦截规则不生效原因Playwright 的路由拦截仅对 context 级别请求生效page-level 的page.route()优先级更高且 iframe 的请求属于其 own context。解法在 context 创建时统一设置避免 page-level 覆盖context browser.new_context() # 全局拦截 context.route(**/api/v1/**, lambda route: route.fulfill(status200, json{data: []})) # 禁用 page-level route page.unroute(**/*) # 清除可能存在的 page 级规则5.3 DevTools MCP 的致命缺陷与规避策略缺陷1CDP 命令无事务性失败后状态不一致现象DOM.querySelector()成功返回 nodeId但DOM.getBoxModel()因节点被移除报错此时你已无法用原 nodeId 做任何操作。规避所有 DOM 操作必须包裹在DOM.pushNodesToFrontend()后获取 frontendNodeId再用DOM.describeNode()获取最新 node infoconst { DOM } client; await DOM.enable(); const root await DOM.getDocument(); const nodeId await DOM.querySelector({ nodeId: root.root.nodeId, selector: #btn }); // 推送到 frontend获取稳定引用 const { backendNodeId } await DOM.pushNodesToFrontend({ nodeId }); const nodeInfo await DOM.describeNode({ backendNodeId }); // 此时 nodeInfo.model 保证是最新的 console.log(nodeInfo.model.attributes);缺陷2WebSocket 连接不稳定频繁断开原因CDP WebSocket 无心跳保活Nginx/ALB 默认 60s 断连。规避在连接后立即发送Page.enable并设置Page.lifecycleEventsEnabled触发周期性事件维持连接await Page.enable(); await Page.setLifecycleEventsEnabled({ enabled: true }); // lifecycleEvents 每 30s 发送一次防止超时缺陷3内存泄漏难以监控现象长期运行的 DevTools 进程内存持续增长最终 OOM。监控定期调用HeapProfiler.takeHeapSnapshot()并分析// 每 5 分钟取一次快照 setInterval(async () { const snapshot await HeapProfiler.takeHeapSnapshot(); // 将 snapshot 上传至分析服务 }, 300000);6. 未来演进MCP 不会标准化但会更易用MCP 的本质是 AI 时代对浏览器控制能力的重新封装。它不会走向标准化因为标准化意味着妥协——Chrome 团队不会为 Playwright 的 API 设计修改 CDPPlaywright 也不会为 DevTools 的调试需求降低封装层级。真正的演进方向是“能力下沉”与“体验上浮”能力下沉Chromium 正在将更多内核能力暴露为 CDP 方法。例如Browser.setDownloadBehaviorv123 新增允许直接设置下载路径无需监听Browser.downloadProgress事件Emulation.setGeolocationOverride支持经纬度精度控制这对地理围栏类 Agent 至关重要。体验上浮Playwright v1.42 将引入page.locator()的增强版支持基于文本内容、ARIA 属性、CSS 伪类的复合 selector让 LLM 生成的 selector 更鲁棒Dify 等平台正将 MCP 接口抽象为 YAML 配置用户只需写actions: - click: button:has-text(立即购买) - wait: div.status:has-text(支付成功)底层自动选择 Playwright 或 DevTools 实现。我最近在做的一个项目是用 Playwright 封装 MCP 接口再用 Rust 编写高性能 CDP 代理层将高频操作如click、type编译为 WASM 模块。实测在 100 并发下响应延迟从 120ms 降至 28ms。这印证了一个事实工具选型的终点不是“选哪个”而是“如何组合”。当你把 Playwright 当作手DevTools 当作眼MCP 就成了你指挥浏览器的神经信号——它不重要重要的是你让浏览器为你做什么。
返回列表