尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

告别Selenium:5分钟用Playwright+Python搭建稳定Web自动化测试

告别Selenium:5分钟用Playwright+Python搭建稳定Web自动化测试
📅 发布时间:2026/7/1 20:59:45

1. 项目概述与核心价值

如果你还在用Selenium写Web自动化测试脚本,每次都要花大量时间处理元素等待、iframe切换或者反爬检测,那今天这个分享可能会让你换个思路。我最近把团队里几个老项目的自动化测试框架从Selenium迁移到了Playwright,最大的感受就是:原来写一个稳定可靠的Web自动化脚本可以这么快。就拿一个最常见的登录并检查用户信息的场景来说,用Selenium可能需要处理各种显式等待和异常捕获,代码写出来几十行,但用Playwright配合Python,核心功能5分钟就能搭出骨架,代码简洁得让人怀疑以前是不是在“自虐”。

这个“5分钟”不是夸张,而是基于Playwright设计哲学带来的效率提升。它内置了智能等待、自动重试、多浏览器引擎支持,还有对现代Web应用(比如单页面应用SPA)的原生友好支持。你不再需要到处写time.sleep(10)或者复杂的WebDriverWait,也不用担心因为网络波动或元素加载慢导致脚本动不动就崩掉。对于测试工程师、爬虫开发者,或者任何需要与浏览器进行自动化交互的开发者来说,这意味着可以把精力从“让脚本跑起来”转移到“测试什么业务逻辑”或者“抓取什么数据”上。

接下来,我会用一个完整的、可运行的例子,带你走一遍从零开始用Playwright + Python搭建一个自动化测试脚本的全过程。这个脚本会模拟一个用户登录某个示例网站,在登录成功后进行页面跳转并验证关键信息。我会把每一步为什么这么做、可能会遇到什么坑、以及如何调试都讲清楚。无论你是刚接触自动化测试的新手,还是想从Selenium转型的老手,都能直接跟着操作,拿到一个能跑起来的脚本。

2. 环境准备与工具选型解析

在动手写代码之前,把环境搭对是成功的一半。很多人卡在第一步,不是因为工具难装,而是没搞清楚这几个工具之间的关系和各自的最佳实践。

2.1 Python环境与包管理

首先确保你有一个可用的Python环境。我强烈建议使用Python 3.8或更高版本,因为Playwright对较新的Python特性支持更好。检查版本很简单,在终端或命令行里输入python --version或python3 --version。如果你看到版本号低于3.8,需要先去Python官网下载安装最新版本。

关于Python的安装,有个小坑需要注意:在Windows上安装时,务必勾选“Add Python to PATH”这个选项,这样你才能在任意目录下直接使用python命令。很多新手装完发现命令找不到,就是因为漏了这一步。在macOS或Linux上,通常系统会自带Python 3,但版本可能较旧,你可以通过Homebrew(macOS)或系统包管理器(Linux)来安装更新的版本。

接下来是包管理。Python世界最主流的包管理工具是pip。我们所有后续的库安装都依赖它。首先升级pip到最新版是个好习惯,可以避免一些因版本过旧导致的依赖解析错误。命令是python -m pip install --upgrade pip。

2.2 Playwright vs Selenium:为什么换?

既然标题是“告别Selenium”,我们得先搞清楚Playwright强在哪里。这不是说Selenium不好,它依然是行业基石,拥有最庞大的社区和资料。但Playwright是微软基于现代Web开发痛点“重新发明”的轮子,解决了很多Selenium的顽疾。

核心优势对比:

特性维度SeleniumPlaywright
架构基于WebDriver协议,需要对应浏览器的驱动(如chromedriver)。直接通过DevTools协议与浏览器内核通信,无需单独驱动。
等待机制需要手动设置显式/隐式等待,否则易因元素未加载报错。自动等待。几乎所有操作(点击、填充)都会自动等待元素可交互。
执行速度较慢,因为要通过WebDriver代理。更快,直接协议通信,且支持无头模式下的硬件加速。
浏览器支持支持所有主流浏览器,但需要各自驱动。原生支持Chromium(Chrome/Edge)、Firefox、WebKit(Safari引擎),安装时自动下载。
录制与调试有Selenium IDE,但功能相对基础。内置强大的Codegen录制工具和Trace Viewer可视化调试器。
网络拦截支持,但配置较复杂。强大且简单,可轻松模拟API响应、修改请求头、拦截资源。
移动端模拟可通过特定配置实现。内置设备模拟(如iPhone、Pixel),包含视口、User-Agent、触摸事件。
iframe与多页需要显式切换上下文。原生支持,像处理普通页面一样简单。

简单来说,Playwright把Selenium时代需要开发者手动处理的“脏活累活”都包了。它的API设计更符合直觉,比如page.click('button'),它会自动等到这个按钮出现在DOM中、可见、且未被其他元素遮挡、稳定可点击时,才执行点击。这省去了大量try...except和WebDriverWait的代码。

2.3 安装Playwright for Python

安装过程非常简单,一行命令搞定。打开你的终端(命令行、PowerShell或Terminal),执行:

pip install playwright

这条命令会从PyPI(Python包索引)下载并安装Playwright的Python客户端库。安装完成后,我们还需要安装Playwright本身需要使用的浏览器内核。Playwright没有使用你系统里安装的Chrome或Firefox,而是为了保证测试环境的一致性,使用了自己管理的特定版本的浏览器。这是好事,意味着你的脚本在任何机器上运行,浏览器环境都是一模一样的。

安装浏览器内核的命令是:

playwright install

这条命令会下载Chromium、Firefox和WebKit三大浏览器引擎。下载可能需要几分钟,取决于你的网络速度。如果你只想安装其中一个(比如Chromium),可以用playwright install chromium。

注意:playwright install命令可能会被某些网络环境下的防火墙或代理影响。如果下载速度极慢或失败,可以尝试设置环境变量PLAYWRIGHT_DOWNLOAD_HOST为国内的镜像源,例如https://npmmirror.com/mirrors/playwright/。具体镜像地址请查阅当时可用的镜像站。

安装完成后,你可以通过playwright --version来验证安装是否成功,它会输出Playwright命令行工具和核心库的版本号。

2.4 选择你的代码编辑器

写Python脚本,一个好用的编辑器能事半功倍。这里有几个主流选择:

  1. Visual Studio Code (VSCode):目前最流行的免费选择。你需要安装Python扩展和Playwright Test for VSCode扩展。后者能提供测试运行、录制和调试的图形化界面,非常强大。
  2. PyCharm:JetBrains出品,专业Python IDE。社区版免费,专业版收费但功能更强(特别是对Web开发和测试的集成)。它对Playwright的支持也很好,可以通过插件或直接运行配置来执行脚本。
  3. Jupyter Notebook / JupyterLab:适合做探索性交互,比如快速试验一些选择器或操作。但不适合作为最终自动化脚本的载体。

我个人日常用VSCode,因为它轻量、插件生态丰富,而且微软官方对Playwright的支持非常积极。后续的演示我也会基于VSCode的环境。

3. 第一个脚本:从登录到验证

理论说再多不如动手跑一遍。我们用一个经典的场景来构建第一个脚本:访问一个公开的测试网站,完成登录操作,然后验证登录成功后的页面元素。

3.1 目标网站与用例设计

为了演示,我们使用互联网上一个经典的测试登录页面:https://the-internet.herokuapp.com/login。这个网站是专门为测试自动化搭建的,有简单的登录表单,登录成功和失败都有明确的反馈,非常适合练手。

我们的测试用例很简单:

  1. 打开登录页面。
  2. 在用户名输入框输入tomsmith。
  3. 在密码输入框输入SuperSecretPassword!。
  4. 点击登录按钮。
  5. 等待页面跳转到成功页面。
  6. 验证页面上是否存在“You logged into a secure area!”的成功消息。
  7. 关闭浏览器。

3.2 编写基础脚本骨架

在项目文件夹里新建一个Python文件,比如叫first_test.py。我们先导入必要的模块,并写出脚本的基本结构。

import asyncio from playwright.async_api import async_playwright async def main(): # 启动Playwright,它负责管理浏览器进程 async with async_playwright() as p: # 启动一个Chromium浏览器实例,headless=False表示有界面,方便我们看 browser = await p.chromium.launch(headless=False, slow_mo=1000) # slow_mo让动作慢一点,方便观察 # 创建一个新的浏览器上下文(类似于一个独立的会话) context = await browser.new_context() # 在新上下文中打开一个标签页 page = await context.new_page() # 这里将填充我们的主要操作步骤 # 操作完成后,暂停一会儿,让我们看看结果 await page.pause() # 关闭浏览器 await browser.close() # 运行主函数 asyncio.run(main())

代码解析与注意事项:

  • 异步编程:Playwright的Python API主要使用async/await语法。这是因为浏览器操作(导航、点击、等待)本质上是I/O密集型任务,异步可以避免阻塞,提升脚本效率,尤其是在并行执行多个测试时。如果你不熟悉异步,可以暂时把它看作一种固定写法,async def定义异步函数,await调用异步操作。
  • async_playwright():这是一个异步上下文管理器,是使用Playwright的入口。async with语句确保在使用完毕后正确清理资源。
  • browser.launch:这里我们启动了Chromium。参数headless=False意味着我们会看到一个真实的浏览器窗口打开,这对于调试初期非常有用。slow_mo=1000表示每个Playwright操作后延迟1000毫秒(1秒),让我们能看清发生了什么。正式运行时可以去掉或设为0。
  • browser.new_context():上下文(Context)是一个重要的概念。它代表一个独立的“浏览器会话”,拥有独立的cookie、localStorage、缓存等。每个测试用例通常使用独立的context,保证用例间隔离。
  • page.pause():这行代码会让脚本执行到此暂停,并打开Playwright Inspector(一个调试工具)。这是一个非常有用的调试命令,我们后面会详细讲。
  • asyncio.run(main()):这是Python 3.7+运行异步主程序的标准方式。

现在运行这个脚本(在终端进入文件所在目录,执行python first_test.py),你应该能看到一个Chromium浏览器窗口打开,然后停住。这说明环境搭建和基础启动成功了。

3.3 填充核心操作:导航、输入与点击

接下来,我们把注释# 这里将填充我们的主要操作步骤替换成实际的自动化逻辑。

# 1. 导航到登录页面 await page.goto('https://the-internet.herokuapp.com/login') print(f"页面标题: {await page.title()}") # 打印标题,确认导航成功 # 2. 输入用户名 # 使用CSS选择器定位用户名输入框。通过查看页面HTML,发现它的id是'username' username_input = page.locator('#username') await username_input.fill('tomsmith') # fill()方法会先清空输入框,再输入文本,并触发相关事件(如input, change) # 3. 输入密码 password_input = page.locator('#password') # id是'password' await password_input.fill('SuperSecretPassword!') # 4. 点击登录按钮 # 按钮的CSS选择器是`button[type='submit']`,或者直接用`text=`选择器按文本定位 login_button = page.locator('button[type="submit"]') await login_button.click() # click()方法会等待按钮可点击(可见、未被禁用、未被遮挡)后才执行点击 # 5. 等待导航完成(跳转到成功页面) # 点击登录后页面会跳转,显式等待一下新页面加载是个好习惯 await page.wait_for_url('**/secure') # 使用通配符匹配包含/secure的URL # 也可以等待某个特定元素出现,作为页面加载完成的标志 await page.wait_for_selector('h4', state='visible') # 等待成功页面的h4标题出现 # 6. 验证成功消息 success_message = page.locator('text=You logged into a secure area!') # 检查这个元素是否在页面上可见 if await success_message.is_visible(): print("✅ 登录成功!成功消息已显示。") else: print("❌ 登录失败,未找到成功消息。") # 7. 为了演示,我们还可以截图保存成功页面 await page.screenshot(path='login_success.png') print("截图已保存为 'login_success.png'")

关键点解析:

  1. page.goto():用于导航到一个URL。它会自动等待页面触发load事件(即主要资源加载完成)。对于单页面应用(SPA),你可能需要结合page.wait_for_load_state('networkidle')来等待网络请求基本停止。
  2. page.locator():这是Playwright最核心的定位器API。它返回一个Locator对象,代表页面上一个或一组元素。重要:locator是“懒加载”的,它不会立即去查找元素,而是在你执行操作(如click(),fill())时,才去查找并操作。这意味着你可以先定义好定位器,但实际的查找和等待逻辑由Playwright在操作时智能处理。
  3. 选择器策略:优先使用稳定的选择器,如id、># 找到所有具有 .item 类的元素,然后过滤出其中文本包含“重要”的 important_items = page.locator('.item').filter(has_text='重要') # 找到表单,然后在表单内部找输入框 username_in_form = page.locator('form#loginForm').locator('input[name="user"]') # 查找第n个匹配项(从0开始) second_button = page.locator('button').nth(1)

    3. 最佳实践与避坑:

    • 优先使用get_by_*系列方法:Playwright提供了更语义化的定位方法,如page.get_by_role("button", name="Submit"),page.get_by_label("User Name"),page.get_by_placeholder("Enter email"),page.get_by_test_id("login-submit")。这些方法通常比原始的CSS/XPath更稳定,因为它们与用户感知的UI方式(角色、标签、占位符)绑定,而不是与实现细节(CSS类名)绑定。
    • 避免过度依赖文本:UI文本是最容易变化的。如果必须用,尽量用部分匹配或正则,并考虑国际化。
    • 为可测试性添加属性:如果你是和自己团队的开发合作,可以推动他们在关键元素上添加>context = await browser.new_context() # 启动追踪 await context.tracing.start(screenshots=True, snapshots=True, sources=True) # ... 执行你的测试操作 ... # 停止追踪并将数据保存到文件 await context.tracing.stop(path=“trace.zip”)

      测试运行后,你会得到一个trace.zip文件。使用命令playwright show-trace trace.zip打开Trace Viewer。这是一个Web界面,你可以:

      • 像看视频一样逐帧回放整个测试过程。
      • 查看每一步操作前后的DOM快照、网络请求、控制台日志。
      • 查看任何时间点的页面截图。
      • 直观地定位是哪个操作失败了,失败时页面是什么状态。

      这个功能对于排查“在我机器上是好的”这类问题,以及进行测试失败后的根因分析,是革命性的。

      5. 构建健壮脚本:异常处理、复用与最佳实践

      一个只能在你本地电脑上跑一次的脚本价值有限。我们需要让它健壮、可维护、可复用。

      5.1 结构化与封装:Page Object Model (POM)

      当测试用例越来越多时,把页面定位和操作逻辑直接写在测试脚本里会变得难以维护。Page Object Model (POM) 是一种设计模式,它将每个页面封装成一个类,页面的元素定位器和基本操作作为类的方法。测试脚本只关心业务逻辑流。

      以我们的登录为例,可以这样重构:

      pages/login_page.py

      from playwright.async_api import Page class LoginPage: def __init__(self, page: Page): self.page = page self.username_input = page.get_by_label("Username") # 使用更稳定的定位方式 self.password_input = page.get_by_label("Password") self.submit_button = page.get_by_role("button", name="Login") async def navigate(self): await self.page.goto('https://the-internet.herokuapp.com/login') async def login(self, username: str, password: str): await self.username_input.fill(username) await self.password_input.fill(password) await self.submit_button.click()

      pages/secure_page.py

      from playwright.async_api import Page class SecurePage: def __init__(self, page: Page): self.page = page self.success_message = page.locator('text=You logged into a secure area!') self.logout_button = page.get_by_role("link", name="Logout") async def get_success_message(self) -> str: # 返回元素的文本内容 return await self.success_message.text_content() async def logout(self): await self.logout_button.click()

      test_login.py

      import asyncio from playwright.async_api import async_playwright from pages.login_page import LoginPage from pages.secure_page import SecurePage async def test_successful_login(): async with async_playwright() as p: browser = await p.chromium.launch(headless=True) # CI环境用无头模式 context = await browser.new_context() page = await context.new_page() # 初始化页面对象 login_page = LoginPage(page) secure_page = SecurePage(page) # 注意:此时页面还在登录页 # 业务逻辑 await login_page.navigate() await login_page.login('tomsmith', 'SuperSecretPassword!') # 等待并验证跳转成功 await page.wait_for_url('**/secure') message = await secure_page.get_success_message() assert 'secure area' in message.lower() print(f"登录成功,消息:{message}") # 登出 await secure_page.logout() await page.wait_for_url('**/login') await browser.close() asyncio.run(test_successful_login())

      采用POM后,如果登录页面的HTML结构变了,你只需要修改LoginPage类中的定位器,所有用到这个页面的测试用例都不需要改动。这大大提升了代码的可维护性。

      5.2 异常处理与断言

      自动化脚本必须能妥善处理意外情况,并给出清晰的失败信息。

      1. 使用 try…except 捕获特定异常:

      try: # 尝试点击一个可能不存在的按钮 await page.get_by_role('button', name='可能消失的按钮').click(timeout=5000) # 设置较短超时 except TimeoutError: print("警告:未找到‘可能消失的按钮’,跳过此步骤。") # 可以在这里执行备用逻辑,或者只是记录日志继续执行 except Exception as e: print(f"操作‘可能消失的按钮’时发生未知错误: {e}") # 根据情况决定是重试、失败还是继续

      2. 使用Playwright的内置断言:Playwright Test框架(另一个工具,用于编写结构化测试)有丰富的断言库。但在纯脚本中,我们可以用Python的assert语句,并结合Playwright的检查方法。

      # 检查元素可见 assert await page.get_by_text('Welcome').is_visible() # 检查URL包含特定字符串 assert '/dashboard' in page.url # 检查输入框的值 value = await page.locator('#email').input_value() assert value == 'user@example.com'

      3. 失败时截图:这是最重要的调试信息之一。我们可以在任何可能失败的地方,或者在except块中截图。

      import traceback try: # 一些可能失败的操作 await critical_operation() except Exception as e: # 获取当前时间戳,生成唯一的文件名 import datetime timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S') screenshot_path = f'error_{timestamp}.png' await page.screenshot(path=screenshot_path, full_page=True) print(f"操作失败,已截图保存至: {screenshot_path}") print(traceback.format_exc()) # 打印完整的错误堆栈 raise # 重新抛出异常,让脚本停止

      5.3 配置与复用:Context、Fixture与数据驱动

      1. 浏览器上下文(Context)的妙用:Context是一个独立的会话环境。你可以为不同的测试场景创建不同的Context,实现完全隔离。你还可以在Context级别设置一些全局配置,这些配置会对该Context下的所有Page生效:

      # 创建一个带有特定视口、语言和权限的上下文 context = await browser.new_context( viewport={'width': 1920, 'height': 1080}, locale='zh-CN', # 设置浏览器语言环境 permissions=['geolocation'], # 授予地理位置权限 ignore_https_errors=True, # 忽略HTTPS证书错误(用于测试环境) # 模拟设备,如iPhone 13 # device_scale_factor=3, # has_touch=True, # is_mobile=True, # user_agent='...' ) # 设置所有请求的公共头 await context.set_extra_http_headers({ 'Authorization': 'Bearer your_token', 'X-Custom-Header': 'value' })

      2. 数据驱动测试:如果你的测试逻辑相同,只是输入数据和预期结果不同,可以使用数据驱动。最简单的方式是使用pytest这样的测试框架配合参数化。纯脚本也可以实现:

      import asyncio import csv test_data = [ {'username': 'tomsmith', 'password': 'SuperSecretPassword!', 'expected': True}, {'username': 'wrong', 'password': 'wrong', 'expected': False}, ] async def run_login_test(username, password, should_succeed): # ... 具体的登录测试逻辑 ... success = await page.locator('text=You logged into').is_visible() assert success == should_succeed, f"登录预期{should_succeed},实际{success}" async def main(): for data in test_data: print(f"测试用例: {data['username']}/{data['password']}") try: await run_login_test(data['username'], data['password'], data['expected']) print(" 通过") except AssertionError as e: print(f" 失败: {e}") asyncio.run(main())

      6. 进阶实战:处理复杂场景与常见问题

      掌握了基础,我们来看看如何应对真实项目中更复杂的场景。

      6.1 处理文件上传与下载

      文件上传:Playwright处理文件上传极其简单,不需要像Selenium那样模拟键盘操作。

      # 假设有一个 <input type="file" id="avatar"> file_input = page.locator('input#avatar') # 只需设置输入框的文件路径即可 await file_input.set_input_files('path/to/your/avatar.png') # 上传多个文件 await file_input.set_input_files(['file1.png', 'file2.png']) # 如果要清空已选择的文件 await file_input.set_input_files([])

      文件下载:处理下载需要监听‘download’事件。

      # 启动下载监听 async with page.expect_download() as download_info: # 执行会触发下载的操作,比如点击一个下载链接 await page.get_by_text('Download Report').click() # 等待下载事件发生,并获取Download对象 download = await download_info.value # 等待下载完成,并保存到指定路径 save_path = f'./downloads/{download.suggested_filename}' # 使用浏览器建议的文件名 await download.save_as(save_path) print(f"文件已下载到: {save_path}")

      6.2 处理弹窗、新窗口与iframe

      弹窗(Dialog):监听并处理alert,confirm,prompt。

      # 在点击可能触发弹窗的按钮前,先监听对话框事件 page.on('dialog', lambda dialog: dialog.accept()) # 自动接受(确定)所有对话框 # 或者更精细的控制 def handle_dialog(dialog): print(f"对话框消息: {dialog.message}") if dialog.type == 'alert': dialog.accept() elif dialog.type == 'confirm': # 根据业务逻辑决定是accept()还是dismiss() dialog.accept() elif dialog.type == 'prompt': dialog.accept("这是输入到prompt的文本") # 向prompt输入文本并确定 page.on('dialog', handle_dialog) # 然后执行触发弹窗的操作

      新窗口/标签页:

      # 监听新页面(窗口/标签页)打开事件 async with page.context.expect_page() as new_page_info: await page.get_by_text('Open in new window').click() # 点击会打开新窗口的链接 new_page = await new_page_info.value # 获取新页面的Page对象 # 现在可以像操作普通page一样操作new_page了 await new_page.wait_for_load_state() print(await new_page.title())

      iframe:Playwright处理iframe非常优雅,你可以像获取普通元素一样获取iframe,然后在其内部进行定位。

      # 通过选择器定位到iframe元素本身 iframe_element = page.frame_locator('iframe#myIframe') # 在iframe内部定位元素并操作 await iframe_element.locator('button.submit').click() # 或者通过name或URL获取frame对象 frame = page.frame(name='frameName') # 或 page.frame(url='**/widget') if frame: await frame.click('button')

      6.3 网络请求拦截与模拟

      这是Playwright相比Selenium的另一大杀器,可以用于模拟后端API响应、修改请求、拦截资源等,非常适合测试前端在不同数据下的表现,或者跳过一些不必要的资源加载加速测试。

      # 1. 路由(Route):拦截请求并返回自定义响应 await page.route('**/api/user/profile', lambda route: route.fulfill( status=200, content_type='application/json', body=json.dumps({'name': 'Mock User', 'age': 30}) # 返回模拟数据 )) # 2. 继续请求,但修改请求(如添加头信息) await page.route('**/*', lambda route: route.continue_(headers={ **route.request.headers, 'X-Mocked': 'true', # 添加自定义头 })) # 3. 拦截请求并中止(例如阻止图片加载以加速) await page.route('**/*.{png,jpg,jpeg}', lambda route: route.abort()) # 执行你的测试,所有对 /api/user/profile 的请求都会得到模拟数据 await page.goto('https://example.com')

      6.4 常见问题排查清单

      即使有了强大的工具,脚本运行时还是会遇到各种问题。这里是一个快速排查清单:

      问题现象可能原因排查步骤与解决方案
      元素找不到(TimeoutError)1. 选择器写错了或不唯一。
      2. 元素在iframe里。
      3. 元素是动态加载的,还没出现。
      4. 页面状态不对(没跳转完)。
      1. 使用page.pause()和Inspector检查元素,确认选择器。
      2. 检查是否存在iframe,用frame_locator。
      3. 在操作前增加wait_for_selector。
      4. 在操作前等待页面状态稳定(wait_for_load_state(‘networkidle’))。
      点击/输入没反应1. 元素被遮挡(弹窗、其他元素)。
      2. 元素是disabled状态。
      3. 需要触发其他事件(如focus,input)。
      1. 截图查看当前页面状态。用Inspector检查元素是否可交互。
      2. 检查元素属性。可能需要先触发前置条件。
      3. 尝试用page.evaluate()执行JS直接点击,或先用element.focus()。
      脚本在CI上失败,本地却成功1. 环境差异(浏览器版本、屏幕分辨率)。
      2. 网络延迟或超时设置太短。
      3. 资源加载失败(如图片、CSS)。
      1. 确保CI环境安装了正确的Playwright版本和浏览器(playwright install)。
      2. 增加全局或关键操作的超时时间。
      3. 使用Trace Viewer (show-trace) 回看失败瞬间的页面和网络状态。这是最有效的手段。
      页面加载慢或超时1. 网络问题或测试环境慢。
      2. 页面有大量未优化的资源。
      1. 适当增加page.goto()或wait_for_load_state的超时。
      2. 考虑使用page.route拦截并屏蔽非必要的第三方资源(如分析脚本、广告)。
      被网站检测为自动化脚本一些网站会检测WebDriver特征。1. Playwright默认已经尝试隐藏一些自动化特征,但可以进一步配置:await browser.new_context(ignore_https_errors=True, viewport=None, has_touch=False)并使用更真实的User-Agent。
      2. 尝试使用playwright.chromium.launch_persistent_context加载一个真实的用户数据目录,模拟真实浏览器会话。

      记住,Trace Viewer是你的最佳朋友。任何在CI上难以复现的失败,第一件事就是保存并查看Trace。它能告诉你失败时页面到底长什么样,网络请求是什么状态,几乎能解决90%的“玄学”问题。

      从Selenium切换到Playwright,最深的体会是心智负担的减轻。以前写脚本,很大一部分精力在和各种等待、异常、浏览器兼容性作斗争。现在用Playwright,我可以更专注于测试用例的业务逻辑本身。它的API设计非常人性化,auto-waiting和强大的调试工具让脚本的稳定性上了一个大台阶。对于新的自动化项目,Playwright无疑是我的首选。对于老项目,如果维护Selenium脚本的成本已经很高,那么花点时间迁移到Playwright,从长期看绝对是值得的投资。

相关新闻

  • Playwright Java:跨浏览器自动化测试的终极解决方案深度解析
  • 终极指南:5个简单步骤为Foobar2000配置酷狗QQ网易云逐字歌词
  • 华为MetaERP 华为IFS(集成财经服务)变革本身是公司级管理升级,其“成功案例“通常体现为关键业务场景的改善实例和量化成效数据。结合公开资料整理如下:一、流程效率提升——合同到回款(OTC)打

最新新闻

  • Rewards Dropout:大模型风格对齐的奖励层正则化新范式
  • Matlab版Chan-Vese主动轮廓分割工具包:含曲率计算、边界延拓与5组实测图像
  • RHEL 9服务器安全加固:firewalld防火墙与SSH密钥认证配置实战
  • python美化输出
  • OpenSSL C语言实现SM2国密算法:从环境配置到加密签名完整指南
  • RoseTTAFold蛋白质结构预测:从零开始快速掌握AI蛋白质建模的完整指南

日新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

周新闻

  • Windows字体自定义终极方案:No!! MeiryoUI完全指南
  • Deepin Boot Maker:告别命令行,3分钟制作Linux启动盘的智能解决方案
  • Plain Craft Launcher 2:重新定义你的Minecraft游戏体验

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号