Python自动化新选择:Playwright从入门到工程化实践指南
1. 项目概述:为什么是 Playwright?
如果你正在寻找一个能让你在 Python 里“为所欲为”的浏览器自动化工具,那 Playwright 绝对值得你花时间深入了解。我最初接触它,是因为厌倦了 Selenium 在某些复杂场景下的“力不从心”——比如处理动态加载的 iframe、等待那些永远不确定何时出现的元素,或者模拟真实的用户手势操作。Playwright 的出现,像是一把瑞士军刀,它由微软出品,原生支持 Chromium、Firefox 和 WebKit 三大浏览器引擎,这意味着你写一套脚本,就能在几乎所有现代浏览器上运行,这本身就是巨大的生产力解放。
简单来说,Playwright for Python 是一个让你用 Python 代码来控制浏览器,实现自动化测试、网页抓取、监控、甚至 RPA(机器人流程自动化)的库。它的核心优势在于“稳”和“全”。稳,体现在其强大的自动等待机制和丰富的选择器上,大大减少了编写“sleep”等待的时间。全,则体现在它几乎能模拟人类在浏览器中的所有操作:点击、输入、拖拽、上传文件、拦截网络请求、执行 JavaScript,甚至录制操作视频。对于 Python 开发者,尤其是从 Selenium 转过来的朋友,你会发现它的 API 设计非常现代和 Pythonic,学习曲线相对平缓。
无论你是想自动化日常的重复性网页操作,还是构建健壮的端到端(E2E)测试套件,亦或是进行复杂的数据抓取,Playwright 都能提供强大的支持。接下来,我将从一个实践者的角度,带你从零开始,深入 Playwright 的每一个核心环节,分享那些官方文档里不会写的实操细节和避坑经验。
2. 环境搭建与核心工具链配置
工欲善其事,必先利其器。Playwright 的环境搭建看似简单,但其中有不少细节决定了你后续开发的顺畅程度。这里我推荐使用venv或conda创建独立的 Python 虚拟环境,这是保证项目依赖纯净的最佳实践。
2.1 Python 环境与 Playwright 安装
首先,确保你的 Python 版本在 3.7 及以上。我强烈建议使用 Python 3.8+,以获得更好的性能和兼容性。
# 1. 创建并激活虚拟环境(以 venv 为例) python -m venv playwright-env # Windows playwright-env\Scripts\activate # macOS/Linux source playwright-env/bin/activate # 2. 安装 Playwright Python 库 pip install playwright # 3. 安装 Playwright 所需的浏览器驱动(Chromium, Firefox, WebKit) playwright install注意:
playwright install这一步至关重要。它会下载对应操作系统的浏览器二进制文件到本地缓存中。在国内网络环境下,这一步可能会因为网络问题而失败或缓慢。如果遇到问题,可以尝试设置镜像源或使用离线安装包。
关于浏览器安装的深度解析:playwright install默认会安装 Chromium、Firefox 和 WebKit。如果你只需要其中一两个,可以指定浏览器,如playwright install chromium。这些浏览器是 Playwright 专门定制的版本,与你在系统里安装的 Chrome 或 Firefox 是隔离的,这保证了自动化环境的一致性和可复现性。这也是 Playwright 比直接驱动本地浏览器更稳定的原因之一。
2.2 开发工具选择与配置
一个顺手的 IDE 能极大提升效率。VSCode 和 PyCharm 是两大主流选择。
VSCode 配置要点:
- 安装官方 Python 扩展和 Pylance。
- 在项目根目录创建
.vscode/settings.json,可以配置 Python 解释器路径指向你的虚拟环境。 - 安装 Playwright Test 扩展,以便在 VSCode 中直接运行和调试测试用例。
PyCharm 配置要点:
- 在
File -> Settings -> Project -> Python Interpreter中,添加你的虚拟环境。 - 配置运行/调试配置时,确保工作目录和解释器选择正确。
无论用哪个,核心是确保你的代码补全、跳转和调试功能能正常工作。Playwright 的 API 有很好的类型提示,在现代 IDE 中能获得非常智能的代码补全体验。
2.3 验证安装与第一个脚本
安装完成后,写一个最简单的脚本来验证一切是否就绪。
# first_script.py import asyncio from playwright.async_api import async_playwright async def main(): async with async_playwright() as p: # 启动 Chromium 浏览器,headless=False 表示显示浏览器界面 browser = await p.chromium.launch(headless=False) # 创建一个新的浏览器上下文(类似于一个独立的隐身会话) context = await browser.new_context() # 打开一个新页面 page = await context.new_page() # 导航到百度 await page.goto("https://www.baidu.com") # 截图保存,证明我们成功打开了页面 await page.screenshot(path="baidu.png") # 获取页面标题并打印 title = await page.title() print(f"页面标题是:{title}") # 关闭浏览器 await browser.close() # 运行异步函数 asyncio.run(main())运行这个脚本,你会看到一个浏览器窗口自动打开,访问百度,截图保存,然后在控制台打印标题,最后关闭。恭喜,你的 Playwright 环境已经成功跑起来了!
实操心得:
headless=False在调试阶段非常有用,你可以亲眼看到自动化过程。但在生产环境或 CI/CD 流水线中,务必设置为headless=True(默认值),以节省资源。browser.new_context()创建了一个独立的上下文。这非常重要,每个上下文拥有独立的 cookies、本地存储和缓存,相互隔离。你可以利用这一点来模拟多个用户会话,或者避免测试间的相互污染。
3. 核心 API 与自动化操作精讲
掌握了环境,我们就进入核心部分:如何用代码操控浏览器。Playwright 的 API 设计围绕Browser、Context、Page、Locator这几个核心对象展开,理解它们的关系是写出高效脚本的关键。
3.1 浏览器、上下文与页面:理解三层架构
可以把这三层结构想象成:
- Browser(浏览器):相当于你电脑上安装的 Chrome 或 Firefox 程序。一个
Browser实例代表一个正在运行的浏览器进程。 - Context(上下文):相当于一个全新的“隐身模式”窗口。在一个浏览器实例下,你可以创建多个互不干扰的上下文。每个上下文有自己的存储、cookies、权限设置。这在多账号操作或并行测试时极其有用。
- Page(页面):相当于浏览器标签页。一个上下文中可以打开多个页面。我们绝大部分的自动化操作(如点击、输入)都发生在
Page对象上。
import asyncio from playwright.async_api import async_playwright async def multi_context_demo(): async with async_playwright() as p: browser = await p.chromium.launch(headless=False) # 创建两个独立的上下文(模拟两个用户) user1_context = await browser.new_context() user2_context = await browser.new_context() # 在每个上下文中打开页面 user1_page = await user1_context.new_page() user2_page = await user2_context.new_page() # 两个页面可以同时进行不同的操作,cookies 完全隔离 await user1_page.goto("https://example.com/login") await user2_page.goto("https://example.com/signup") # ... 执行登录和注册操作 ... await browser.close()3.2 元素定位器:稳、准、狠地找到目标
与元素交互的前提是找到它。Playwright 提供了多种强大且稳定的定位方式,远超简单的 CSS 选择器或 XPath。
1. 文本定位器 (text=)这是 Playwright 的一大亮点,可以直接通过页面上的可见文本来定位元素,对于测试和自动化来说非常直观和稳定。
# 点击页面上文本为“登录”的按钮 await page.click("text=登录") # 更精确的匹配 await page.click("text='精确登录文本'")2. CSS 和 XPath 定位器这是传统但依然有效的方式。Playwright 对它们进行了增强,内置了自动等待。
# CSS 选择器 await page.click("#submit-button") # ID await page.click(".btn-primary") # Class # XPath await page.click("//button[@data-testid='submit']")3. 角色定位器 (role=)这是遵循 WAI-ARIA 标准的定位方式,对于现代 Web 应用的可访问性测试尤其有用,能定位到具有特定语义的角色元素,如 button、link、textbox。
# 点击一个角色为按钮的元素 await page.click("role=button[name='确认']") # 向一个角色为文本框的元素输入内容 await page.fill("role=textbox[name='用户名']", "my_username")4. Locator 对象:最佳实践以上方式通常直接用在page.click()等方法里。但更推荐的做法是使用page.locator()先创建一个Locator对象。这个对象代表一个元素查找策略,可以复用,并且支持链式调用和更复杂的操作。
# 创建一个定位器 submit_btn = page.locator("button:has-text('提交')") # 等待元素可见(自动等待机制) await submit_btn.wait_for(state="visible") # 然后点击 await submit_btn.click() # 或者获取其属性 value = await submit_btn.get_attribute("data-value")注意事项:尽量避免使用
page.$()和page.$$()(返回 ElementHandle),而是优先使用page.locator()。Locator更现代,自动处理等待,且 API 更友好。ElementHandle 需要手动管理生命周期,容易导致内存泄漏或元素过时(StaleElement)错误。
3.3 模拟用户交互:点击、输入与更多
定位到元素后,就可以模拟用户操作了。Playwright 的交互 API 非常丰富。
基础交互:
# 点击(左键) await page.click("button#ok") # 双击 await page.dblclick("item") # 输入文本(会先清空输入框) await page.fill("input#search", "Playwright") # 模拟按键,如回车 await page.press("input#search", "Enter") # 勾选复选框或单选框 await page.check("#agree-terms") # 取消勾选 await page.uncheck("#newsletter") # 从下拉框选择 await page.select_option("select#country", "CN")高级交互:
# 悬停(Hover) await page.hover("nav.menu > li") # 拖放(Drag and Drop) await page.drag_and_drop("#source-item", "#target-area") # 上传文件(非常方便,无需模拟点击文件选择框) await page.set_input_files("input[type='file']", "path/to/myfile.pdf") # 模拟键盘组合键 await page.keyboard.press("Control+A") # 全选 # 模拟鼠标移动和点击 await page.mouse.move(100, 200) await page.mouse.click(100, 200)处理弹窗和对话框:Playwright 可以轻松监听和处理各种弹窗。
# 监听并接受一个 alert 对话框 page.once("dialog", lambda dialog: dialog.accept()) await page.click("button#trigger-alert") # 监听并处理下载事件 async with page.expect_download() as download_info: await page.click("a#download-link") download = await download_info.value # 保存下载文件 await download.save_as("/path/to/save.zip")3.4 等待策略:告别 sleep,拥抱智能等待
在自动化中,等待是门艺术。硬编码的time.sleep()是万恶之源,它让脚本变得脆弱且低效。Playwright 内置了强大的自动等待机制。
1. 自动等待(Auto-waiting)这是 Playwright 的核心优势。当执行click,fill,check等操作时,Playwright 会自动执行一系列可操作性检查,确保元素:
- 已附加到 DOM
- 可见(非隐藏、非透明、display 非 none)
- 启用(非 disabled)
- 稳定(未在动画中)
- 可接收事件(例如,未被其他元素遮挡)
只有所有检查通过,操作才会执行。这极大地简化了代码,你通常不需要手动写等待。
2. 显式等待有时你需要等待特定条件成立。使用page.wait_for_*系列方法。
# 等待导航完成(页面加载) await page.goto("https://example.com", wait_until="networkidle") # 推荐使用 networkidle # 等待元素出现在 DOM 中 await page.wait_for_selector(".loaded-indicator") # 等待元素变为可见状态 await page.wait_for_selector("#success-message", state="visible") # 等待元素从 DOM 中消失 await page.wait_for_selector("#loading-spinner", state="hidden") # 等待某个函数在页面上下文中返回真值 await page.wait_for_function("window.status === 'ready'") # 等待超时设置(单位毫秒) await page.click("button.slow", timeout=30000) # 给这个点击操作30秒超时3. 网络请求等待对于高度动态的 SPA(单页应用),等待网络请求是更可靠的方式。
# 在点击一个会触发 API 请求的按钮后,等待特定请求完成 async with page.expect_response("**/api/data") as response_info: await page.click("button#load-data") response = await response_info.value # 可以处理响应数据 data = await response.json()实操心得:优先依赖 Playwright 的自动等待。仅在自动等待无法覆盖的场景(如等待一个非交互元素的出现、等待一个特定的网络响应)下,才使用显式等待。几乎永远不要使用asyncio.sleep或time.sleep。
4. 高级特性与实战技巧
掌握了基础操作,我们来看看 Playwright 那些能让你事半功倍的高级特性。
4.1 网络拦截与 Mock
Playwright 允许你监听和修改浏览器发出的任何网络请求和响应。这对于测试、性能分析、屏蔽广告或模拟后端数据至关重要。
# 拦截请求,修改请求头或阻止请求 await page.route("**/*.{png,jpg,jpeg}", lambda route: route.abort()) # 阻止图片加载,加速 await page.route("https://api.example.com/data", lambda route: route.continue_(headers={**route.request.headers, "Authorization": "Bearer fake-token"})) # 拦截请求并返回 Mock 数据 async def handle_route(route): if "/api/user" in route.request.url: # 返回一个模拟的 JSON 响应 await route.fulfill( status=200, content_type="application/json", body=json.dumps({"name": "Mock User", "id": 123}) ) else: # 其他请求正常继续 await route.continue_() await page.route("**/api/**", handle_route) # 监听所有响应 page.on("response", lambda response: print(f"{response.status} {response.url}"))4.2 执行 JavaScript
你可以在页面上下文中执行任意 JavaScript 代码,这给了你极大的灵活性。
# 获取页面上的数据(例如,从全局变量中) dimensions = await page.evaluate("""() => { return { width: document.documentElement.clientWidth, height: document.documentElement.clientHeight, deviceScaleFactor: window.devicePixelRatio }; }""") print(dimensions) # 在页面中注入并执行一个函数,并传递 Python 参数 selector = ".item" count = await page.evaluate("selector => document.querySelectorAll(selector).length", selector) print(f"找到 {count} 个 .item 元素") # 处理返回复杂对象的场景 result = await page.evaluate_handle("() => window.someComplexObject") # result 是一个 JSHandle,可以在后续的 evaluate 中继续使用4.3 多页面、多浏览器与并行操作
Playwright 天生支持并行,这对于提高自动化效率或测试并发场景非常有用。
import asyncio async def parallel_tasks(): async with async_playwright() as p: browser = await p.chromium.launch() # 在一个浏览器实例中创建多个页面并行工作 page1 = await browser.new_page() page2 = await browser.new_page() # 使用 asyncio.gather 并行执行任务 await asyncio.gather( page1.goto("https://example1.com"), page2.goto("https://example2.com") ) # 分别操作 task1 = page1.evaluate("() => document.title") task2 = page2.content() titles = await asyncio.gather(task1, task2) print(titles) await browser.close()4.4 录制与代码生成:Playwright Codegen
对于初学者或快速生成脚本原型,playwright codegen是一个神器。它是一个交互式录制工具。
# 打开录制工具,并指定目标网址和输出语言 playwright codegen https://www.baidu.com --target python -o my_script.py执行命令后,会打开一个浏览器和一个 Inspector 窗口。你在浏览器中的所有操作(点击、输入、导航)都会被实时转换成 Python 代码,并显示在 Inspector 中。录制结束后,代码会保存到my_script.py。注意:生成的代码通常比较冗长,需要你根据实际情况进行重构和优化,但它是一个绝佳的起点。
4.5 设备模拟与视口设置
你可以轻松地模拟移动设备访问,测试响应式布局。
from playwright.async_api import async_playwright import asyncio async def emulate_mobile(): async with async_playwright() as p: # 使用预定义的设备描述符(如 iPhone 11) iphone_11 = p.devices["iPhone 11"] browser = await p.chromium.launch(headless=False) # 创建上下文时传入设备信息 context = await browser.new_context(**iphone_11) page = await context.new_page() await page.goto("https://m.example.com") await page.screenshot(path="mobile-view.png") await browser.close() # 或者手动设置视口和 User-Agent context = await browser.new_context( viewport={"width": 375, "height": 667}, user_agent="Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) ..." )5. 工程化实践:从脚本到项目
当你的自动化脚本越来越多,就需要考虑工程化了。这包括测试组织、配置管理、报告生成和持续集成。
5.1 使用 Pytest 与 Playwright 进行结构化测试
Playwright 官方推荐与 Pytest 结合使用,它提供了强大的pytest-playwright插件。 首先安装插件:
pip install pytest pytest-playwright然后,你可以编写结构清晰的测试用例。
# test_login.py import re from playwright.sync_api import Page, expect def test_login_success(page: Page): """测试成功登录流程""" page.goto("https://example.com/login") page.fill("#username", "testuser") page.fill("#password", "securepass") page.click("button[type='submit']") # 使用 Playwright 的断言库,它内置了自动等待 expect(page).to_have_url(re.compile(r".*/dashboard")) expect(page.locator(".welcome-msg")).to_contain_text("testuser") def test_login_failure(page: Page): """测试登录失败场景""" page.goto("https://example.com/login") page.fill("#username", "wrong") page.fill("#password", "wrong") page.click("button[type='submit']") expect(page.locator(".error-message")).to_be_visible()使用 Pytest 运行测试:
pytest test_login.py -v # 指定浏览器 pytest test_login.py --browser chromium --browser firefoxPytest 提供了固件(fixture),page就是pytest-playwright提供的一个固件,它自动管理了浏览器和页面的生命周期,你无需在测试函数中手动启动和关闭。
5.2 配置管理与环境变量
将配置(如基础URL、登录凭证、超时时间)从代码中分离出来。
# config.py import os from dotenv import load_dotenv load_dotenv() # 从 .env 文件加载环境变量 class Config: BASE_URL = os.getenv("BASE_URL", "https://staging.example.com") USERNAME = os.getenv("TEST_USERNAME") PASSWORD = os.getenv("TEST_PASSWORD") HEADLESS = os.getenv("HEADLESS", "True").lower() == "true" SLOW_MO = int(os.getenv("SLOW_MO", "0")) # 操作延迟,便于观察 VIEWPORT = {"width": 1920, "height": 1080} # .env 文件(不应提交到版本库) # BASE_URL=https://production.example.com # TEST_USERNAME=admin # TEST_PASSWORD=secret # HEADLESS=True # SLOW_MO=0在测试或脚本中导入Config类使用即可。
5.3 生成测试报告与追踪
Playwright 可以自动生成丰富的测试报告。
# 运行测试并生成 HTML 报告 pytest --tb=short --html=report.html --self-contained-html此外,Playwright 本身也支持强大的追踪(Tracing)功能,可以记录测试执行过程中的所有操作、网络请求、控制台日志,生成一个可视化的追踪文件,对于调试失败的测试用例极其有用。
# 在测试开始前启动追踪 context.tracing.start(screenshots=True, snapshots=True, sources=True) # ... 执行测试操作 ... # 测试结束后停止追踪并保存 context.tracing.stop(path="trace.zip")你可以使用playwright show-trace trace.zip命令来可视化地查看这个追踪文件。
5.4 集成到 CI/CD (GitHub Actions 示例)
将 Playwright 测试集成到持续集成流程中,确保每次代码变更都经过自动化验证。
# .github/workflows/playwright.yml name: Playwright Tests on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: python-version: '3.10' - name: Install dependencies run: | pip install -r requirements.txt playwright install --with-deps chromium # 只安装必要的浏览器 - name: Run your tests run: pytest --browser chromium --headless - name: Upload test results if: always() uses: actions/upload-artifact@v3 with: name: playwright-report path: playwright-report/ retention-days: 306. 常见问题排查与性能优化
即使有了强大的工具,在实际项目中依然会遇到各种问题。这里记录了一些高频问题和解决思路。
6.1 元素定位失败:StaleElementReference 与等待
这是最常见的问题。通常是因为页面在定位器被创建后发生了变化(动态加载)。
- 症状:
TimeoutError: Timeout 30000ms exceeded.或Error: Element is not attached to the DOM。 - 解决方案:
- 强化定位器:使用更稳定、唯一的属性,如
># 通过名称、URL 或选择器定位 iframe frame = page.frame(name="login-frame") # 通过 name # 或者 frame = page.frame(url=re.compile(r".*/login")) # 然后在 frame 内操作 await frame.fill("#username", "user") - 动态内容:对于通过 AJAX 或前端框架(React, Vue)渲染的内容,使用等待策略是关键。等待特定的网络响应 (
page.expect_response) 或等待一个标志性元素出现 (page.wait_for_selector)。
- 强化定位器:使用更稳定、唯一的属性,如
6.3 验证码与反爬机制
Playwright 可以绕过一些简单的反爬,但对于复杂的验证码(如 Google reCAPTCHA),自动化解决既不道德也可能违法。在合法合规的前提下:
- 测试环境:关闭验证码或使用测试密钥。
- 其他方案:考虑使用第三方验证码识别服务(注意法律和成本),或者将需要验证码的步骤设计为手动触发点。
6.4 性能优化技巧
当脚本运行缓慢时,可以尝试以下优化:
- 重用浏览器上下文:避免为每个测试用例都启动/关闭浏览器。使用 Pytest 的会话级固件或手动管理。
- 并行执行:利用
asyncio.gather或 Pytest 的-n参数(需安装pytest-xdist)并行运行独立测试。 - 拦截不必要的资源:使用
page.route阻止图片、样式、字体等非必要资源的加载,大幅提升页面加载速度。await page.route("**/*.{png,jpg,jpeg,svg,css,woff2}", lambda route: route.abort()) - 禁用非必要特性:创建浏览器上下文时,可以禁用 JavaScript、CSS 等(仅适用于特定场景,如纯数据抓取)。
context = await browser.new_context(java_script_enabled=False) - 使用
headless=True:无头模式比有头模式快得多,资源占用也更少。
6.5 调试技巧
- 慢动作模式:启动浏览器时设置
slow_mo参数(单位毫秒),让操作变慢以便观察。browser = await p.chromium.launch(headless=False, slow_mo=500) - 打开开发者工具:
browser = await p.chromium.launch(devtools=True) - 录制追踪文件:如前所述,这是最强大的调试工具,能完整复盘执行过程。
- 打印页面状态:在关键步骤使用
page.content()、page.title()、page.url打印信息,或使用console.log注入 JS。# 在页面上下文中执行 console.log await page.evaluate("console.log('Current URL:', window.location.href)")
7. Playwright 与 Selenium 的深度对比与选型
很多朋友会问,有了 Selenium,为什么还要用 Playwright?我根据自己的使用经验,做了一个核心对比。
| 特性维度 | Playwright | Selenium (WebDriver) | 说明与影响 |
|---|---|---|---|
| 架构与协议 | 基于 Chrome DevTools Protocol 等现代浏览器调试协议,直接与浏览器引擎通信。 | 基于 W3C WebDriver 标准,通过一个中间代理驱动浏览器。 | Playwright 通信更直接,理论上更高效稳定。Selenium 标准更统一,历史更久。 |
| 浏览器支持 | 原生支持 Chromium、Firefox、WebKit(Safari 内核)。浏览器由 Playwright 统一管理。 | 支持所有实现 WebDriver 协议的浏览器(Chrome, Firefox, Safari, Edge等)。需自行下载对应驱动。 | Playwright 的浏览器版本是定制的,环境一致性极佳。Selenium 需要手动匹配驱动和浏览器版本,易出问题。 |
| 自动等待 | 内置强大自动等待。几乎所有操作(click, fill)都自动等待元素可操作。 | 无内置自动等待。需要手动编写WebDriverWait和expected_conditions。 | Playwright 大幅减少了“等待”代码,脚本更简洁健壮。这是最显著的体验提升。 |
| API 设计 | 现代、流畅、Pythonic。同步/异步 API 清晰分离。 | 经典,但有些 API 略显陈旧。同步为主,异步支持需额外库。 | Playwright 的 API 更符合现代 Python 开发者的习惯,学习成本略低。 |
| 移动端/设备模拟 | 内置丰富的设备描述符,模拟移动设备非常方便。 | 需要通过ChromeOptions或FirefoxOptions设置参数,相对繁琐。 | Playwright 在设备模拟上开箱即用,体验更好。 |
| 网络拦截 | 原生支持,API 强大且易用,可轻松 Mock 请求和响应。 | 支持有限,通常需要依赖浏览器扩展或代理,实现复杂。 | 对于需要 Mock 数据或性能测试的场景,Playwright 优势巨大。 |
| 录制工具 | playwright codegen功能强大,生成代码质量较高。 | IDE 插件或 Selenium IDE,生成代码可能较冗长。 | Playwright 的录制工具集成在 CLI 中,使用更方便。 |
| 社区与生态 | 较新,但由微软主导,发展迅速。社区活跃,文档优秀。 | 极其成熟,社区庞大,资料和解决方案无数。第三方工具和云服务支持完善。 | Selenium 在遇到复杂问题时更容易找到答案。Playwright 的生态正在快速追赶。 |
| 执行速度 | 通常更快,尤其是在无头模式下和并行执行时。 | 受 WebDriver 协议和驱动影响,有时稍慢。 | 对于大规模测试套件,Playwright 的速度优势能节省可观时间。 |
选型建议:
- 选择 Playwright,如果你:项目是全新的;追求开发效率和脚本稳定性;需要处理大量动态内容、iframe 或网络拦截;团队熟悉现代 JavaScript/TypeScript 生态(Playwright 也原生支持 JS/TS);看重开箱即用的设备模拟和追踪功能。
- 选择 Selenium,如果你:需要支持 Internet Explorer 等老旧浏览器;项目已有大量基于 Selenium 的遗产代码;团队对 Selenium 非常熟悉;依赖某些仅支持 Selenium 的第三方云测试平台或工具。
从我个人的经验来看,对于绝大多数新的Web 自动化项目(测试或爬虫),Playwright 是更优的选择。它用更少的代码解决了更多的问题,尤其是在处理现代复杂 Web 应用时,其稳定性和开发体验显著优于 Selenium。
