最近帮一个团队做采集架构评审,他们用 Selenium 跑了两年,想换 Puppeteer,理由是"听说快很多"。我问了一句"你知道为什么快吗",会议室安静了五秒。
这篇文章不讲"谁更好",讲的是两个框架为什么不一样——从最底层的通信协议往上捋,搞清楚了根因,选型自然有判断依据。
两条协议路线
浏览器自动化说到底就是一件事:你的程序给浏览器发指令,浏览器执行,把结果返回给你。区别在于"用什么语言发指令"。
Selenium 走的是 WebDriver 协议。这个协议的通信路径是这样的:你的代码(Python/Java/任何语言)→ HTTP 请求发给 WebDriver Server → WebDriver Server 翻译成浏览器原生操作 → 浏览器执行 → 结果原路返回。中间架了一个"翻译官"。
Puppeteer 走的是 Chrome DevTools Protocol(CDP)。这个协议的通信路径短一截:你的 Node.js 代码 → 通过 WebSocket 直连 Chromium 的 DevTools 端点 → 浏览器执行 → 结果通过同一条 WebSocket 返回。没有翻译官,你直接跟浏览器内核对话。
打个比方,Selenium 像是你雇了一个翻译跟外国人聊天,你说中文、翻译翻成英文、对方听完回答、翻译再翻回中文给你。Puppeteer 是你直接学了对方的语言,面对面交流。
这个差异为什么重要
协议层面的差距会传导到你能感知的每一个环节。
延迟结构不同。 Selenium 每条指令都要走一次 HTTP 请求-响应周期。如果你连续做"点击 → 等元素 → 再点击 → 再等"这种串行操作,每次都吃一次往返延迟。我测过,在本地环境下单次往返大约 80-120 毫秒,一个采集流程跑二十次串行操作,光协议开销就快 2 秒了。Puppeteer 的 WebSocket 是长连接,指令发出去了浏览器内核直接执行,没有中间层,实测同等操作序列的协议开销在 300 毫秒以内。
事件监听能力不同。 CDP 协议原生支持事件推送——浏览器里发生了网络请求、DOM 变更、控制台输出,这些事件会主动通过 WebSocket 推给你的程序。Puppeteer 的 page.on('request')、page.on('response') 就是基于这个能力实现的,几乎是零延迟感知。Selenium 要做同样的事,只能轮询——定时去查 DOM 有没有变化、网络面板有没有新请求,效率和准确性都差一截。
会话管理不同。 CDP 天然支持多个 session,你可以在一个浏览器进程里开多个隔离的上下文,每个上下文有独立的 Cookie 和 Storage。Puppeteer 的 browser.createIncognitoBrowserContext() 就是直接调 CDP 的 Target.createBrowserContext。Selenium 要做类似的事得开多个 WebDriver 实例,每个实例对应一个浏览器进程,内存开销完全不在一个量级。
CDP 不是没有代价
说了这么多 CDP 的好处,它的短板也得摆出来。
绑死 Chromium。 CDP 是 Chromium 项目的协议,Firefox 和 Safari 不支持。这意味着 Puppeteer 本质上是一个"Chromium 专属工具"。虽然社区搞过 puppeteer-firefox,但它走的是另一条路(不是 CDP),API 兼容性一直不好,2025 年后基本停更。
CDP 版本碎片化。 Chromium 几乎每个大版本都会对 CDP 做增删改,Puppeteer 的版本跟 Chromium 版本是强绑定的。升级 Puppeteer 有可能碰到 CDP 接口变化导致脚本失效。Selenium 这边因为 WebDriver 协议本身比较稳定(W3C 标准化了),接口变动频率低很多。
反检测视角的特殊问题。 CDP 连接本身会在浏览器环境里留下痕迹——Runtime.enable 调用会导致 navigator.webdriver 为 true,CDP 连接会改变 window.chrome 对象的某些属性。部分高级反爬方案会专门检测 CDP 连接特征,这种检测比检测 WebDriver 更难绕过,因为 CDP 连接产生的副作用涉及浏览器内核层面,不靠 JS 注入就能改掉。Selenium 也有自己的指纹问题,但 WebDriver 的检测对抗方案更成熟,社区积累更多。
一个容易被忽略的点:协议的"未来"
WebDriver 协议是 W3C 标准,这意味着它有标准组织背书,浏览器厂商有义务维护各自的 Driver 实现。不管 Chrome 怎么变,Selenium 的跨浏览器能力是有制度保障的。
CDP 是 Chromium 项目的内部协议,没有标准化。Google 可以随时改它、甚至废弃它——实际上 Google 一直在推一个新的 WebDriver BiDi 协议,试图把 CDP 的能力和 WebDriver 的标准化结合起来。如果这个新协议成熟了,Puppeteer 和 Selenium 在协议层的差距可能会被抹平。
但那是后话了。2026 年的当下,CDP 和 WebDriver 的差异仍然实实在在地影响着你每天跑的每一行采集代码。
选型判断的底层逻辑
看完协议差异,选型逻辑其实很清晰:
如果你需要的是"跟浏览器内核做最直接的对话,追求极致的单浏览器性能和事件感知能力,不在意只能用 Chromium"——CDP 路线(Puppeteer)适合你。
如果你需要的是"一套代码控多种浏览器,协议稳定、接口变动少、社区方案多"——WebDriver 路线(Selenium)适合你。
不是谁更好的问题,是你在跟浏览器对话时,需不需要一个翻译的问题。