经常有同行或者刚入路的小伙伴在私信里问我:“博主,都2026年了,写爬虫和自动化到底是选 Selenium 还是 Playwright ?”
我的回答一律是:
能用 Playwright 就绝对不要碰 Selenium。如果你还在用 Selenium 死磕,90% 的情况下都是在给自己的爬虫项目挖坑。
不可否认,Selenium 在 2007 年出道时确实是革命性的。但在 2026 年的今天,现代 Web 爬虫的需求已经发生了翻天覆地的变化——反检测要求更苛刻、并发性能要求更高、API 现代化程度要求更极致。在这几个核心维度上,Selenium 的历史包袱已经成了严重的拖累。 今天就站在一个长期在一线摸爬滚打的爬虫博主角度,和大家掏心窝子聊聊为什么该全面迁移了,文末还会附上我们团队在集成 爬虫代理 时的避坑落地方案。
不可否认,Selenium 在 2007 年出道时确实是革命性的。但在 2026 年的今天,现代 Web 爬虫的需求已经发生了翻天覆地的变化——反检测要求更苛刻、并发性能要求更高、API 现代化程度要求更极致。在这几个核心维度上,Selenium 的历史包袱已经成了严重的拖累。 今天就站在一个长期在一线摸爬滚打的爬虫博主角度,和大家掏心窝子聊聊为什么该全面迁移了,文末还会附上我们团队在集成 爬虫代理 时的避坑落地方案。
一、 启动速度:Selenium 的“冷启动”代价
在商业级爬虫的高并发场景下,启动速度直接决定了服务器的资源开销和吞吐量。- Selenium 的硬伤:每启动一次浏览器,都需要在系统底层创建一个完整且独立的浏览器进程,加载各种渲染引擎、用户配置和扩展程序。实测冷启动时间基本在 2-5 秒之间,具体取决于机器性能。以一次 100 并发请求的场景为例,每次请求都可能触发新进程创建,总耗时可能拉长到 300 秒以上。
- Playwright 的降维打击:引入了浏览器上下文(Browser Context)的概念,支持预创建浏览器池以实现进程复用。在首次启动后,后续的上下文复用可在 1 秒以内完成。同一个浏览器实例可以创建多个独立的上下文,不仅相互之间的 Cookie 和状态完全隔离,资源消耗更是比 Selenium 降低了 5 倍以上。
核心结论:Selenium 每次启动浏览器都是一次完整进程创建,而 Playwright 可以用连接池模式省掉这部分开销。在需要频繁启动或并发的场景,这个差距直接决定了你的项目能不能跑起来。
# Playwright 异步/上下文复用模式(推荐)
# 无头模式启动,复用已启动浏览器
browser = await playwright.chromium.launch(headless=True)
# Selenium 无头模式(仍需创建独立完整进程)
options = ChromeOptions()
options.add_argument("--headless")
driver = webdriver.Chrome(options=options)
二、 反爬对抗能力:指纹特征是 Selenium 的死穴
做爬虫最头疼的就是和 Cloudflare、DataDome、PerimeterX 等顶级反爬系统对线。在 2026 年,Selenium 的指纹问题在 WebDriver 协议层面就无法根治,几乎成了反爬系统的“活靶子”。1. Selenium 无法根治的指纹暴露面
- navigator.webdriver 属性固定显示为 true。
- window.navigator.plugins 包含明显的 Selenium 相关插件信息。
- ChromeOptions 参数会在请求头中留下 --disable-blink-features=AutomationControl 被移除的痕迹。
- WebGL 渲染指纹异常,Canvas 指纹被污染。
- 存在浏览器自动化专用的 Console 日志特征。
2. Playwright 的应对姿态
Playwright 默认会抹平大部分自动化指纹,并且在 launch 选项中内置了反检测配置,配合 Stealth 插件可以将被拦截率压到 10% 以下 :# Playwright 内置反检测与特征抹平
browser = await playwright.chromium.launch(
headless=True,
args=[
'--disable-blink-features=AutomationControlled',
'--exclude-switches=enable-automation'
]
)
# 动态注入,额外抹平 webdriver 特征
await page.add_init_script("""
Object.defineProperty(navigator, 'webdriver', {get: () => false});
""")
三、 API 设计:老旧的 WebDriver 协议 vs 现代异步 API
Selenium 依赖的 WebDriver 协议设计于 2006 年,底层基于 同步 HTTP 请求模式 。在单线程顺序执行的时代这没问题,但在需要处理复杂并行任务、异步等待、并行抓取多目标时,Selenium 就会显得无比臃肿。# Selenium 的同步阻塞等待,代码冗长且容易超时崩溃
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myId"))
)
driver.find_element(By.ID, "myId").click() # 同步等待
而 Playwright 则是完全为
异步、并发
而生的,API 设计更符合 2026 年的主流开发习惯:
# Playwright 异步并发,API 内置自动重试机制
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page()
# 异步等待,Locator API 会自动等待元素可操作并进行自动重试
await page.wait_for_selector("#myId")
# 利用 asyncio 轻松并行操作多个页面
pages = await asyncio.gather(*[
fetch_target(browser, url) for url in urls
])
优势总结:Playwright 的等待机制内置超时和自动重试,无需手动编写复杂的 Wait 循环;支持异步上下文管理器,资源释放更安全;对于点击、悬停、文件上传、iframe 嵌套等复杂交互,其 locator API 比 Selenium 的 By.ID 灵活得多。
四、 代理集成:如何优雅地接入爬虫代理?
在代理集成这块,Selenium 的坑更是深不见底。配置不对轻则请求失败,重则直接被代理服务端返回 407(Proxy Authentication Required)或者网站直接报 403。 博主敲黑板提示 :根据爬虫代理官方技术文档的明确说明, 动态转发模式不适用于浏览器自动化工具(如 Selenium 和 Playwright) 。在浏览器自动化场景下,我们需要进行长连接和会话保持,因此必须使用 固定转发模式 或 IP 白名单认证模式 !1. Selenium 配置代理的血泪史
- 407 认证噩梦:Selenium 设置带用户名密码认证的代理没有标准方式,往往需要预先打包、安装一个认证扩展(.crx)。可笑的是,这个扩展在 headless 无头模式下经常静默失效,且失败的 407 错误经常被 Selenium 吞掉。
- HTTPS 会话频繁断开:WebDriver 协议在每个请求后不会主动保持长连接,导致 HTTPS 会话在代理层面频繁断开。虽然文档指出可以通过 sessionKeepAlive 参数保持连接,但在 Selenium 中没有直接对应的配置项,自行实现的成本极高。
2. Playwright 的现代化代理配置实战
使用 Playwright 配置代理就清爽得多了,其代理 API 更加现代化,配置复杂度只有 Selenium 的 1/5 不到。方案 A:固定转发模式 + 用户名密码认证(Python 示例)
Playwright 原生支持在 launch 时直接传入包含认证信息的代理参数。# 16YUN 固定转发模式 + Playwright
browser = await playwright.chromium.launch(
args=[f'--proxy-server=http://username:password@proxy.16yun.cn:8080']
)
方案 B:IP 白名单认证模式(最推荐,安全性最高)
如果你的爬虫服务器拥有固定出口 IP,在控制台绑定白名单后,代码里连密码都不用写,安全性更高。# 16YUN IP白名单模式(不需要用户名密码)
browser = await playwright.chromium.launch(
args=[f'--proxy-server=http://proxy.16yun.cn']
)
💡 针对 Java 爬虫栈的额外避坑指南
如果你是用 Java 写爬虫,通过代理发送 HTTPS 请求时,JDK 默认会跳过代理对 CONNECT 方法的 tunnel 处理,导致静默失败。请务必在启动 JVM 时添加参数,或者在代码中加入以下设置:// Java 爬虫需要强制设置 JDK tunnel,注意该参数在不同JDK版本间行为可能不一致
System.setProperty("jdk.httpclient.tunnel.respectDroneHttps", "false");
// 或者在 JVM 启动参数中设置:-Djdk.httpclient.tunnel.respectDroneHttps=false
五 & 六、 维护成本与迁移建议
1. 维护状态对比
- Selenium:目前已进入维护模式,新功能开发停滞。最后一次主要版本发布还是 2021 年的 Selenium 4.x,GitHub 活跃度在 2023 年后显著下降,且 Chrome 130+ 等新版本需要等待社区 patch。
- Playwright:由微软核心团队高频维护,每月保持小版本迭代(当前版本 1.50+)。最爽的一点是浏览器绑定——Playwright 会随每个版本同步更新对应的 Chromium 版本,无需手动去配各种 chromedriver。
2. 两者的核心 API 快速迁移表
| Selenium API | Playwright 现代 API | 说明 |
|---|---|---|
| driver.find_element | page.locator | 元素定位 |
| WebDriverWait | page.wait_for_selector | 显式等待 |
| driver.switch_to.window | page.context.pages[n] | 标签页/窗口切换 |
| ChromeOptions | browser.launch(args=[...]) | 启动参数配置 |
3. 爬虫代理选型与落地方案指南
| 场景 | 推荐代理模式 | 原因 |
|---|---|---|
| 浏览器自动化(Playwright/Selenium) | 固定转发模式 | 动态转发模式不适用于浏览器自动化 |
| 需要长期会话保持 | 固定转发模式 | sessionKeepAlive 参数仅在固定转发下稳定 |
| 高频短时纯 API 请求 | 动态转发模式 | 请求完成后 IP 自动释放,避免资源浪费 |
- 认证方式选择:
- 用户名密码认证:适合需要多用户隔离的场景,Playwright 原生支持。
- IP 白名单认证:适合固定 IP 出口,代码中无需暴露凭证,安全性更高。
七、 边界说明:何时还能用 Selenium?
本文的比较基于 2026 年主流反爬系统 、 Selenium 4.x vs Playwright 1.50+ 以及 非传统 Web 测试的纯爬虫自动化场景 。但在以下边界场景里,请根据实际约束做判断,不要盲目迁移:- Selenium 仍有价值的场景:深度依赖 Selenium IDE 的老项目(无预算重写);需要对接极老系统的 WebDriver 兼容层;团队已完全掌握 Selenium 且无学习 Playwright 的时间窗口。
- Playwright 需要谨慎的场景:需要 IE 浏览器兼容(Playwright 原生不支持 IE);极度依赖第三方 Selenium 扩展插件的复杂场景;团队技术栈完全锁定在 Selenium 生态中。