拓冰建站拓冰建站
首页 / 资讯中心 / 正文

告别Selenium:8款替代工具助你搞定自动化测试与爬虫

做了五六年Web自动化我的项目从功能测试到数据采集几乎全用Selenium起步。早期它确实够稳但最近两三年我越来越频繁地听见同行抱怨启动慢、浏览器驱动要单独下载还得跟版本号较劲、页面稍微复杂一点等元素那段代码就写得很痛苦。我自己也有几次在爬虫和回归测试里被Selenium的“老实”坑到——它太听指令了页面跳转没完成它就去点控件结果就是各种随机性失败。后来我陆续把部分框架换成了更贴近现代浏览器行为的工具实测下来很多场景根本不用死磕Selenium。这篇就把我在真实项目里跑过、能落地省事的8款替代工具整理出来给还在观望或已经准备切换的同学一个参考。这篇不是讲“Selenium一无是处”而是想说清楚在哪些场景下用哪款工具更顺手以及从Selenium迁移要注意什么。内容覆盖面包括自动化测试、爬虫数据采集、UI回归、移动端测试等场景适合正在做质量保障、Python/Java爬虫、前端测试和想要提升自动化效率的开发者。所有工具我都按“能直接抄作业”的标准来写尽量把安装、核心API、关键坑都交代清楚。1. 为什么越来越多团队想替代 Selenium1.1 Selenium 的痛点不是它不好而是它老了Selenium很早就是Web自动化的行业标准W3C也把它定成了规范。可是十几年下来它背负的兼容性问题越来越多。最让人头疼的是浏览器驱动管理Chrome一升级chromedriver版本不对就得去下载新驱动还得根据浏览器版本号和平台类型挑选。这个“浏览器驱动怎么判断下载哪个”的热搜问题几乎每个用Selenium的人都遇到过。虽然现在有WebDriverManager能自动下载但也是一层额外依赖。第二个痛点是执行速度。Selenium的每次命令都是通过WebDriver协议和浏览器通信命令往返多脚本复杂起来之后跑一遍测试的时间会成倍增长。我在一个中大型后台管理系统做过一次统计同样的回归用例Selenium跑完要28分钟换到基于CDPChrome DevTools Protocol的方案后只要不到15分钟接近一半的提升。时间在CI流水线里就是成本。第三个痛点是等待策略。Selenium的隐式等待和显式等待需要开发者自己选对场景新手代码里最常见的就是time.sleep(3)这种写死时间的做法。页面慢一点就挂快一点就白等三秒。这类代码在别人机器上跑结果往往不一样非常不稳定。1.2 判断你是否需要换工具的三个问题不是所有项目都需要从Selenium迁走。我在动手换工具之前一般先问自己三个问题我的脚本里是不是有大量显式等待、重试和驱动程序管理的代码我是不是经常要同时操作多标签页、拦截网络请求、模拟移动端我是不是在爬虫里因为页面环境检测而频繁被限制这三个问题里只要有两个答案是“是”那就值得换。如果只是写几个简单的表单自动化、小众浏览器兼容性测试Selenium依然够用没必要折腾。但如果你需要更细粒度的控制、更快的执行和更省心的环境处理下面这几款替代工具至少有一个会适合你。2. 8款替代工具全景速览与选型建议2.1 一张表看全8款工具不同工具体验差异很大建议先拉到一张表里对比核心定位再按项目需要去细看。工具主要语言核心特点最适配场景PlaywrightPython / Java / JS / .NET多浏览器CDP协议自动等待自带Trace查看器跨浏览器测试、复杂交互、爬虫PuppeteerNode.jsChrome DevTools Protocol轻量高效Node环境下的爬虫、页面截图、PDF生成CypressJavaScript浏览器内运行调试体验出色自带时间旅行前端开发者做组件测试、E2E回归TestCafeJavaScript / TypeScript免WebDriver自带智能等待多浏览器云端运行不想折腾驱动的前端测试团队DrissionPagePython浏览器自动化与requests无缝结合语法更简洁Python爬虫、滑动验证交互、表单操作PyppeteerPythonPuppeteer的Python非官方移植异步友好Python环境下的截图、数据采集、页面交互AppiumPython / Java / JS等基于WebDriver协议但专攻移动端WebView与原生移动端App及WebView自动化测试HeliumPython / Java基于Selenium的语法糖封装API极其人性化想保留Selenium生态但想简化的Python用户我会在后面把Playwright、DrissionPage、Cypress单独展开这三个是几类需求里最典型的代表。其他几款我挑场景讲避免篇幅被平均到每款工具上反而不够深入。2.2 按项目类型选工具而不是按热度选以前我做技术选型特别喜欢看GitHub星星数量最近发现最务实的逻辑是你的核心场景到底是什么方向。如果是Web端全流程测试尤其是要覆盖Chrome、Firefox、Safari多浏览器首选Playwright它自带模拟器、移动端设备参数和多浏览器内核一套代码不用怎么改就能跑三个浏览器。如果是纯前端项目团队以JavaScript为主想快速写出零配置的E2E用例Cypress的体验最舒服它的调试器能直接看到每一步执行前的页面状态排查问题像看回放。如果是写Python爬虫每天要处理大量页面且经常要应对验证码、滑块这类交互DrissionPage的代码量能比Selenium少一半对页面的控制反而更精细。如果是Node环境下做轻量级自动化比如定时截图、生成PDF、抓取SPA页面数据Puppeteer足够轻。如果是移动端混合应用还需要操作App里的H5界面Appium依然是绕不开的选项毕竟移动端WebView自动化的生态没有比它更成熟的。2.3 组合拳测试和爬虫用同一套底层协议这里我多说一个不一定主流但实际很省心的思路把爬虫和测试框架统一到底层协议上。比如Playwright在浏览器控制层面和Puppeteer一样走CDP你在Playwright里能顺手把浏览器发出去的每个请求都拦截下来也可以直接修改返回值。这种能力对爬虫的意义很大。比如有个接口返回的是加密JSON你不需要理解加密算法直接在响应阶段替换一段数据前端拿到手的就是你伪造的内容。这在Selenium里需要启动BrowserMob这类代理工具才能实现配置过程麻烦性能也有损失。我自己现在工具栈基本是日常测试用Playwright快速采集用DrissionPage移动端跑Appium。Selenium保留在一些老项目里做兼容性维护。你有没有发现真正省事的方案不是“替代某一个工具”而是让每个工具在最合适的场景里发挥强项。3. 三款热门替代工具实战拆解3.1 Playwright自动化测试和爬虫都适用的“六边形战士”Playwright是微软开源并持续维护的项目和PuPPeteer的开发团队是同批人。它最大的感受是“不反人类”——几乎所有交互方法都默认自动等待。click、fill这些动作会等到元素可操作再执行你不用写一堆显式等待代码。它内部还自带一个actionability的校验逻辑会检查元素是否可见、稳定、接收事件特别适合处理动态渲染的单页应用。安装使用很简单Python环境里执行pip install playwright playwright install chromium两条命令之后浏览器内核就下好了。写一段最基础的操作代码优雅不少from playwright.sync_api import sync_playwright with sync_playwright() as p: browser p.chromium.launch(headlessFalse) # 在这里设置设备、代理、UA page browser.new_page() page.goto(https://example.com, wait_untilnetworkidle) page.get_by_label(用户名).fill(tester) page.get_by_role(button, name登录).click() page.wait_for_selector(.dashboard) print(page.title()) browser.close()get_by_label、get_by_role这套查询方式比Selenium的find_element_by_xpath语义感强太多。你不需要关心元素的class或id是不是有多个空格只要关注它在页面上的语义角色维护成本瞬间降下来。编写的测试如果挂了Playwright还能自动生成追踪文件用trace viewer可以回放页面每一步的截图、网络请求和控制台日志。你去看一次回放就能定位问题这在定位偶发性失败时是神器。如果你做爬虫它另一个重要能力是拦截和修改请求。下面这段代码可以截获所有图片响应并保存def handle_response(response): if response.request.resource_type image: body response.body() # 自己写保存逻辑 with open(fimg_{response.url.split(/)[-1]}, wb) as f: f.write(body) page.on(response, handle_response)很多新手不知道这段代码的价值。以前用Selenium点了一个按钮下载图片你得处理浏览器下载框、临时目录和文件重命名问题非常痛苦。现在直接监听网络事件浏览器还没写盘就把数据拿走了干净利落也不用管下载路径。这基本就是“selenium中点击按钮就下载图片的代码怎么写”的最佳答案之一。3.2 DrissionPage处理滑块验证和控制交互的Python利器DrissionPage是我在Python爬虫项目里用得最多的库之一。它最大的创新是把浏览器自动化和HTTP请求库做了无缝融合同一个对象既能操作页面又能直接发请求。这种设计彻底解决了Selenium里经常碰到的两难页面渲染出来的数据和接口返回的数据对不上。安装同样简单pip install DrissionPage大概四五行代码就能操作浏览器from DrissionPage import ChromiumPage page ChromiumPage() page.get(https://example.com/login) page.ele(#username).input(my_account) page.ele(#password).input(123456) page.ele(text:登录).click()注意看这段代码的应用场景如果你只需要用requests维护一个会话又想让这个会话自动带上浏览器的CookieDrissionPage的session_options能直接把登录后的状态给到requests对象。两者切换时不需要手动导Cookie省去了很多Selenium里“等登录完再导出Cookie到requests”的胶水代码。在处理滑块拼图这类交互时DrissionPage对鼠标拖拽的控制颗粒度也更细。它可以直接指定拖拽起点、终点、步数和随机暂停时长而不是像Selenium那样只给一个粗糙的drag_and_drop。要让动作更接近真人本质上是两步一是把位移拆成带有随机加速和减速的片段二是在拖动过程中加入微小抖动。DrissionPage可以在执行拖拽前直接读取滑块和背景图的坐标用简单的几何计算生成轨迹整个过程都在一个进程内完成。它的缺点是生态不如Selenium庞大官方文档部分内容更新不够及时遇到冷门浏览器版本可能会踩小坑。但做Python爬虫只要目标网站是Chromium系浏览器渲染DrissionPage已经足够好用尤其是你不想要重型的测试报告体系只想要一个爽快的自动化脚本时。3.3 Cypress折腾UI测试的最佳体验Cypress的定位和Playwright不太一样。它不是去驱动真正的浏览器做自动化而是直接从浏览器内部运行这也意味着它的执行速度极快网络请求直接在应用层就被mock掉了。Cypress最吸引人的是“时间旅行”调试每一条测试命令执行完界面左侧会生成一个快照你点击任意命令就能看到当时页面的样子。项目里有同事第一次在Cypress里定位偶发问题时直接被这个体验惊到花了一个中午把十几个历史用例全部翻看了一遍。安装用npm就行npm install cypress --save-dev npx cypress open测试用例写起来和自然语言很像describe(登录流程, () { it(应该能正常跳转后台, () { cy.visit(/login) cy.get(#username).type(tester) cy.get(#password).type(123456) cy.get(button[typesubmit]).click() cy.url().should(include, /dashboard) }) })它能很容易地对浏览器内部的fetch和xhr进行拦截这在测试弱网、接口异常、删除接口500这些边缘场景时非常方便。Cypress内置了对时间、日期和浏览器位置等测试场景的API模拟极端情况不用写额外的mock客户端。但它也有很明显的边界它没法真正打开多个独立Tab并行操作也没有办法跨域访问多个不同域名的页面。如果你想在同一个测试里从A系统跳到B系统再跳回来Cypress会比较吃力。另外它对Safari的支持现在也还不完整跨浏览器能力要弱于Playwright。所以Cypress更适合作前端团队内部的单仓库项目而非企业级的跨系统E2E套件。4. 从 Selenium 迁移过来的关键步骤与落地示例4.1 迁移前必须搞清楚的三件事越来越多的老项目想迁移到新工具上但这位老同学经历了几次“换个框架”失败后我总结经验迁移最忌讳的不是技术而是把新旧工具当成一模一样的平替。盲改代码、对照API一个个换后面大概率会发现交互逻辑完全变了。迁移前先做三件事盘点你的页面交互类型。当前Selenium脚本里哪些是click/input这类基础操作哪些用到了拖拽、文件上传、新标签页、iframe、alert弹窗这些在Playwright等工具中都有对应API但是写法不同。把交互类型清单列出来再对照目标工具的官方API文档提前知道哪些是“改一行”的哪些是“要重写”的。重构你的等待条件。Selenium里写死的time.sleep或WebDriverWait在换到Playwright后几乎可以全部删除。Playwright的locator.click默认会等待元素可操作所以迁移时如果一行代码都不改很可能会遇到新的异常比如元素被遮挡、定位器匹配到多个元素等。这是语法迁移之外更需要花时间的部分。初始化调试环境。Playwright和DrissionPage都提供了headful模式建议迁移过程中改用有头模式配合Trace Viewer或页面录制功能。你肉眼看到页面状态再对比脚本执行进度能省下很多思考成本。4.2 一个登录页面的迁移对比我拿一个典型登录流程来举例。Selenium版本大概是这样的from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC driver webdriver.Chrome() wait WebDriverWait(driver, 10) driver.get(https://example.com/login) wait.until(EC.presence_of_element_located((By.ID, username))).send_keys(tester) wait.until(EC.element_to_be_clickable((By.ID, loginBtn))).click() dashboard wait.until(EC.presence_of_element_located((By.CLASS_NAME, dashboard))) print(dashboard.text) driver.quit()同样的逻辑换到Playwright之后就变成了from playwright.sync_api import sync_playwright with sync_playwright() as p: browser p.chromium.launch() page browser.new_page() page.goto(https://example.com/login) page.locator(#username).fill(tester) # 自动等待 page.locator(#loginBtn).click() print(page.locator(.dashboard).inner_text()) browser.close()表面看起来代码量差不多但Playwright版本最核心的差别是你几乎不需要手动等待。Selenium版本要考虑element是否已经渲染、是否可点击、页面是否有遮罩层每加一个控件就要多写一个wait。Playwright用了一个统一的actionability机制时长可配置默认情况下会等待元素出现、可见、稳定、可接收事件这就是从底层上减少了不稳定因素。如果还要处理iframeSelenium里你得先切到frame再操作操作完还要切回来。Playwright的frame_locator可以直接链式定位page.frame_locator(#main-frame).get_by_placeholder(输入验证码).fill(123456)这套写法不仅代码更短还能天然避免切来切去导致的上下文丢失问题。迁移时遇到iframe越多的页面体感差距越明显。4.3 地址选择不强制一次性迁移全部用例如果你手头有一个积累了上千条用例的Selenium体系我不建议在某个周报周期里宣称“下周全部切换完”。更稳妥的方式是按业务模块分批翻新。先把使用频率最高、最容易出问题的那批测试脚本拿出来按4.1的步骤做技术验证再逐步切到新框架里。过程中最好保留新旧两套脚本并发运行一段时间等到新框架的稳定性数据比Selenium有明显优势后再下线老脚本。我见过太多团队一次性搬完结果新框架环境没配好项目还被迫回滚到旧框架白白消耗了士气。自动化框架这件事稳定压倒一切。5. 常见问题与排查技巧实录5.1 高频问题速查表我把自己和社区里讨论最多的几类问题整理了如下表格基本都是反复出现的老面孔。问题现象可能原因推荐排查方向浏览器启动报 executable path 错误浏览器内核没下载或路径不对Playwright运行 playwright installDrissionPage首次启动检查Chrome版本元素明明存在但点击报拦截页面存在透明遮罩层或元素被固定定位遮挡用 locator.click(forceTrue) 确认或先关闭遮罩层再操作网络请求很慢导致等待超时页面有大量外部资源使用 page.route 拦截图片、字体等非必要请求偶发性断言失败后端接口响应时间波动不要盲目加sleep用 expect(locator).to_be_visible(timeout10000)iframe内元素定位不到iframe嵌套层级深用 frame_locator(父frame) 链式进入子frame多标签页操作时上下文丢失忘记切换Page对象Playwright中每个新标签页是一个Page实例切换时需持有page引用爬虫数据只渲染了一部分页面滚动懒加载用 page.mouse.wheel 或自动滚动到页面底部触发加载5.2 我踩过的几个坑与解决思路分享一个典型的坑有一次用Playwright写爬虫目标是某后台列表页。第一次能正常获取20条数据第二次请求就只剩10条最后发现是接口返回了缓存数据而页面根据屏幕尺寸动态隐藏了部分行。这类问题用Selenium很难察觉因为Selenium的定位逻辑只看DOM是否存在并不感知到它没被渲染进视口。后来我在代码里做了一次viewport尺寸设置browser.new_context(viewport{width: 1920, height: 1080})把浏览器窗口调大后隐藏行的问题就消失了。后来我还在循环里监测页面是否有滚动事件如果有就继续滚动到无法再滚为止这样确保数据全部加载。第二个坑发生在DrissionPage的跨会话场景。一开始我以为用浏览器Session发起接口请求后再跳回浏览器页面Cookie就一定能保持一致结果发现部分Cookie属于HttpOnly字段且只在特定域名路径下生效。后来我在切换请求会话后执行了一次页面刷新并重新进入目标导航整个链路才恢复正常。这个问题其实和工具无关是HTTP会话和浏览器会话对Cookie管理逻辑本来就不同需要自己做好同步节点。第三个坑是关于验证码的。以前用Selenium自动化滑块验证时总想着用最精简的代码直接拖过去结果要么被识别成机器操作要么拖拽距离总是有偏差。后来用Playwright和DrissionPage这类支持细粒度操作的工具后我理解了一个原则浏览器自动化处理滑块验证的重点不在于让拖拽路径看起来多完美而在于整个操作节奏要与人类行为模型一致。也就是先停顿、再缓慢启动、中间有加速减速、最后还有一次微调。实现方式不复杂用随机数生成轨迹就行但前提是你用的工具能精准地模拟鼠标事件序列。DrissionPage在这方面做得比较顺手Playwright也可以手动构造MouseEvent。5.3 工具选完后的最后两个建议想提醒两件容易被忽略的事情。第一件是版本管理。Playwright和DrissionPage更新速度很快前者尤其频繁。如果不锁版本今天写的代码下个月同事拉下来可能就跑不起来。我每个项目都在requirements.txt里锁死版本号并且用pytest的固定环境跑CI。第二件是痕迹定位。替代工具普遍比Selenium更“快”但这反而会让问题更难复现。现在我在跑测试用例时默认就开Playwright的trace记录功能采集失败现场。省得问题出现后盲猜原因这是迁移后效率提升最直接的一个习惯。我个人其实不太建议大家继续在Selenium和某个新工具之间左右摇摆。重点不是选哪个框架而是你把自动化脚本当作“堆代码”还是“搭系统”。堆代码的人换到Playwright也会继续写出一堆强制等待搭系统的人哪怕用Selenium也能写出稳定执行、便于维护的自动化项目。工具是放大器你的工程化思维才是底座。这个原则放在自动化测试和爬虫项目里都成立。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门