上周有个朋友找我帮忙看他的采集脚本,用的是 Selenium + ChromeDriver,跑了三个月突然大面积超时。我翻了翻他的代码,说实话——问题不在 Selenium 本身,是他对"浏览器自动化"这件事的理解从一开始就跑偏了。
这类问题我遇到太多了。工作室这几年做过不下二十个采集项目,Puppeteer 和 Selenium 都用过,踩过坑也尝过甜头。今天把选型思路摊开聊聊,不站队,只讲我们实际用下来的体感。
先把"自动化框架"这个概念拆清楚
很多人一上来就比"谁快""谁稳",这比法本身就有问题。Puppeteer 和 Selenium 压根不是同一层的东西。
Selenium 是一套协议标准(WebDriver),它定义的是"浏览器应该暴露哪些操作接口",具体实现由各浏览器厂商的 Driver 来完成。所以 Selenium 天然跨浏览器——Chrome、Firefox、Edge、Safari,只要厂商提供了 Driver,你就能控。
Puppeteer 是一个 Node.js 库,它直接通过 Chrome DevTools Protocol(CDP)与 Chromium 内核通信。不走 WebDriver 那套中间层,指令直达浏览器内核。代价也很明显:基本只能控 Chromium 系浏览器。
一句话总结:Selenium 是"通过标准协议遥控浏览器",Puppeteer 是"直接钻进浏览器的大脑里操作"。架构差异决定了后面所有的取舍。
速度这件事,差距比你想的大
我们 2025 年初做过一组内部基准测试:同一个目标站点、同样的采集逻辑(登录 → 翻页 → 提取结构化数据),分别用 Puppeteer 无头模式、Selenium + ChromeDriver 无头模式、Selenium + GeckoDriver 无头模式跑 100 次取中位数。
结果大概是这样:
Puppeteer(无头):单轮采集平均 3.2 秒
Selenium + ChromeDriver(无头):单轮采集平均 5.1 秒
Selenium + GeckoDriver(无头):单轮采集平均 6.8 秒
差距主要来自两个地方:一是 CDP 协议本身比 WebDriver 少了至少一层 IPC 中转;二是 Puppeteer 的 API 设计是 Promise 链式调用,网络请求拦截和 DOM 事件监听几乎是实时的,而 Selenium 每次操作都要走一轮"客户端 → Driver → 浏览器 → Driver → 客户端"的往返。
不过话说回来,如果你只是跑日频批量任务、不在乎那几秒延迟,这点速度差在实际业务里体感并不明显。真正让人头疼的是下面这个场景。
反检测:这场仗两个框架都打得很吃力
说实话,2026 年的反爬环境比三年前严太多了。Cloudflare Turnstile、DataDome、PerimeterX(现在叫 HUMAN)这些方案对自动化工具的特征识别已经做得非常细致了。
Selenium 的原生指纹几乎是明牌。 ChromeDriver 启动时会在 navigator 对象上注入一堆 webdriver 相关属性,HTTP 请求头里也会带 ChromeDriver 的标识。市面上虽然有 undetected-chromedriver 这种补丁库,但本质上是在打补丁——每次 Chrome 更新都可能失效,维护成本很高。我们去年有个项目用了 undetected-chromedriver,Chrome 升了一个小版本之后连续三天采集全挂,半夜起来修脚本的那种痛苦我不想再经历第二次。
Puppeteer 的原生指纹也没好到哪去。navigator.webdriver 同样是 true,window.chrome 对象的结构和真实浏览器有差异。好在社区里有 puppeteer-extra-plugin-stealth 这个插件,它做了十几项指纹伪装(覆盖 chrome.runtime、webgl vendor、plugin array 等),实测下来比 Selenium 侧的补丁方案要稳定。但"稳定"是相对的——今年四月份 Cloudflare 更新了一版检测规则,stealth 插件也短暂失效了大约一周。
我们工作室目前的实际做法是:两个框架都不裸跑。 Puppeteer 侧用 stealth 插件 + 自定义指纹注入做前置处理;Selenium 侧用 undetected-chromedriver + 手动覆盖 navigator 属性。成本上 Puppeteer 侧的配置更省心一些,Selenium 侧需要操心的细节更多。
跨浏览器需求——Selenium 的主场
如果你的项目需要同时在 Chrome、Firefox、Safari 上跑自动化测试或采集(比如做兼容性监控、多端价格比对),那没什么好纠结的,Selenium 是唯一选项。
Puppeteer 虽然也有 Firefox 的实验性支持(通过 puppeteer-firefox),但 2025 年底这个项目已经基本停滞了,API 兼容度远不如 Chrome 侧成熟。微软的 Playwright 倒是一个值得关注的替代方案——它同时支持 Chromium、Firefox、WebKit,API 设计跟 Puppeteer 很像,而且原生支持多浏览器上下文隔离。如果你现在就想要"Puppeteer 的手感 + 跨浏览器能力",Playwright 可能是最佳答案,不过那就是另一篇文章了。
生态和调试体验
这块我觉得 Puppeteer 赢得比较明显。
Puppeteer 自带的 DevTools 集成非常丝滑——你可以直接用 Chrome DevTools 的 Performance 面板看采集过程中的网络瀑布、CPU 占用、内存变化,调试体验跟平时开发前端几乎没有区别。它的 page.waitForSelector()、page.evaluate() 这些 API 设计得非常直觉,基本上看一下文档就能上手。
Selenium 的调试体验就差一截了。虽然有 Selenium Grid 可以分布式执行,有 Selenium IDE 可以录制回放,但日常写脚本时你面对的更多是"等一个元素出现 → 等不到 → 超时 → 报错"这种枯燥循环。隐式等待和显式等待的区别,是每个 Selenium 使用者都得迈过去的一道坎——我见过太多人在 implicitly_wait 和 WebDriverWait 之间反复纠结,最后写出了一堆 time.sleep(3) 了事。
语言栈也是个现实问题
Puppeteer 只支持 Node.js(Python 版本 Pyppeteer 已经很久没维护了)。如果你的技术栈是 Python 为主,Selenium 的 Python binding 是成熟得多的选择——社区庞大、文档齐全、StackOverflow 上有海量问答可以参考。
我们工作室因为前端和后端都大量用 Node,所以 Puppeteer 的接入成本几乎为零。但如果是给客户的运维团队做交付,对方只有 Python 环境,那我们会直接用 Selenium,不会硬推 Puppeteer。
选框架有时候不是选"哪个更好",而是选"哪个更适合你团队的手"。
我们自己的选型决策树
经过这几年的实战,工作室内部沉淀了一个很简单的判断逻辑:
选 Puppeteer 的场景:
只需要跑 Chromium 系浏览器
团队技术栈以 Node.js 为主
对采集速度有明确要求(单轮 < 5 秒)
目标站点反爬强度中等,stealth 插件能应付
选 Selenium 的场景:
有跨浏览器硬需求(兼容性测试、多端采集)
团队技术栈以 Python 为主
需要 Selenium Grid 做分布式大规模执行
目标站点对 CDP 协议有检测(少数站点会专门识别 CDP 连接特征)
两个都别选,去看 Playwright 的场景:
新项目、新起步,没有历史包袱
既要速度又要跨浏览器
需要多浏览器上下文隔离(比如同时登录多个账号做对比采集)
写在最后
工具选型这件事,说到底是在约束条件下做取舍。Puppeteer 快但不跨浏览器,Selenium 广但慢半拍,Playwright 全能但社区生态还在成长。没有完美选项,只有"在你这个具体场景下最不别扭的那个"。
回到开头那位朋友的问题——他的 Selenium 超时不是 Selenium 的锅,是目标站点加了 WebDriver 指纹检测而他完全没做伪装。后来我帮他加了 undetected-chromedriver 和几行指纹覆盖代码,跑到现在也没再出过问题。
技术选型的第一步不是比参数,是搞清楚你面对的战场长什么样。





































