上周有个朋友找我帮忙看他的采集脚本,用的是 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 同样是 truewindow.chrome 对象的结构和真实浏览器有差异。好在社区里有 puppeteer-extra-plugin-stealth 这个插件,它做了十几项指纹伪装(覆盖 chrome.runtimewebgl vendorplugin 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_waitWebDriverWait 之间反复纠结,最后写出了一堆 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 和几行指纹覆盖代码,跑到现在也没再出过问题。

技术选型的第一步不是比参数,是搞清楚你面对的战场长什么样。

原文来自邦阅网 (52by.com) - www.52by.com/article/232337

声明:该文观点仅代表作者本人,邦阅网系信息发布平台,仅提供信息存储空间服务,若存在侵权问题,请及时联系邦阅网或作者进行删除。

评论
登录 后参与评论
发表你的高见