Playwright Python:现代浏览器自动化

FreeGuideOnline 最新 2026-06-16

Playwright Python:现代浏览器自动化入门与实战

为什么选择 Playwright?

Playwright 是由微软开发的开源自动化测试框架,能够以单一 API 驱动 Chromium、Firefox 和 WebKit 浏览器。与 Selenium 相比,Playwright 原生支持自动等待(Auto-waiting)、强大的选择器引擎和现代 Web 特性(如 Shadow DOM、Service Workers),无需额外工具即可处理单页应用和复杂交互。它在执行速度、稳定性和跨浏览器一致性方面表现卓越,是当今自动化测试和网页抓取的首选方案。

环境准备与安装

系统要求

  • Python 3.8 或更高版本
  • 操作系统:Windows、macOS、Linux(包括 ARM 架构的树莓派)

安装 Playwright 库

pip install playwright

安装浏览器引擎

Playwright 需要下载浏览器二进制文件(Chromium、Firefox、WebKit),执行如下命令:

playwright install

此操作会将浏览器安装到 Playwright 的缓存目录,如果希望系统识别已安装的 Chrome/Edge 等,可参考后续配置。

第一个自动化脚本

创建 test.py 文件,编写以下代码:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=False)  # 设置为 False 可看到浏览器界面
    page = browser.new_page()
    page.goto('https://playwright.dev/')
    print(page.title())
    browser.close()

使用 python test.py 运行,你会看到浏览器打开并输出页面标题。

同步与异步模式

Playwright 提供了同步(sync_api)和异步(async_api)两套 API。同步模式代码简洁,适合脚本编写;异步模式适合集成到异步 Web 框架中,能发挥更高的并发性能。异步示例:

import asyncio
from playwright.async_api import async_playwright

async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch()
        page = await browser.new_page()
        await page.goto('https://playwright.dev/')
        print(await page.title())
        await browser.close()

asyncio.run(main())

Playwright 核心概念与代码片段

浏览器、上下文与页面

  • Browser:浏览器实例,可通过 p.chromium.launch() 创建。
  • BrowserContext:隔离的浏览器会话,类似隐身窗口。不同上下文之间不共享 Cookie、localStorage。使用 browser.new_context() 创建。
  • Page:单个标签页或窗口,所有交互都基于 Page 对象。

上下文的使用可以模拟多登录状态,同时运行多个独立测试。

context = browser.new_context(locale='zh-CN')  # 设置语言
page = context.new_page()

选择器与定位元素

Playwright 提供了多种内置定位方式,推荐使用 page.locator()page.get_by_*() 方法,它们内置自动等待并支持链式操作。

基础定位方法

# 通过文本内容
page.get_by_text("提交")
# 通过角色(无障碍属性)
page.get_by_role("button", name="登录")
# 通过标签和属性
page.get_by_label("用户名")
page.get_by_placeholder("请输入密码")
# 通过测试 ID
page.get_by_test_id("submit-btn")
# CSS 与 XPath 仍可使用,但推荐上述语义化方法
page.locator("css=button.primary")
page.locator("xpath=//button[@type='submit']")

链式与过滤

row = page.get_by_role("listitem").filter(has_text="Playwright")
row.locator(".delete-btn").click()

交互操作:点击、输入与键盘

所有交互都会自动等待元素可操作(可见、启用、无动画遮挡)。

# 导航
page.goto("https://example.com")
# 点击
page.get_by_text("开始使用").click()
# 输入文本(默认先清空并键入)
page.get_by_placeholder("邮箱").fill("user@example.com")
# 逐字输入(模拟真实打字)
page.get_by_placeholder("邮箱").type("user@example.com", delay=100)
# 键盘操作
page.keyboard.press("Enter")
page.keyboard.press("Control+A")
# 复选与单选框
page.get_by_label("我同意").check()
page.get_by_role("radio", name="个人用户").click()

提取数据与断言

直接从 Page 或 Locator 提取文本、属性以及 HTML。

# 提取单个文本
heading = page.get_by_role("heading").text_content()
# 提取属性
link = page.get_by_role("link").get_attribute("href")
# 提取多个元素
texts = page.locator(".item").all_text_contents()
# 使用断言(需安装 pytest 并配合 Playwright 断言)
from playwright.sync_api import expect
expect(page.get_by_text("操作成功")).to_be_visible()
expect(page).to_have_title("预期标题")

自动化等待机制

Playwright 的自动等待体现在:

  1. 操作前自动等待:点击、输入等动作会等待元素出现并达到可操作状态。
  2. 断言自动重试expect() 会持续检查直到条件满足或超时。
  3. 显式等待:需要等待特定状态时使用 wait_for 系列方法。
# 等待网络安静(无请求持续500ms以上)
page.wait_for_load_state("networkidle")
# 等待特定元素可见
page.locator(".result").wait_for()
# 等待下载事件
with page.expect_download() as download_info:
    page.get_by_text("下载报告").click()
download = download_info.value
download.save_as("report.pdf")

处理弹窗、对话框与多页面

对话框

自动取消或确认 JavaScript 对话框:

page.on("dialog", lambda dialog: dialog.accept())
page.get_by_text("删除").click()

新标签页

with page.expect_popup() as popup_info:
    page.get_by_text("打开新窗口").click()
new_page = popup_info.value
new_page.wait_for_load_state()
print(new_page.title())

截图、录像与追踪

调试复杂场景时,Playwright 的可视化诊断功能非常强大。

# 截图
page.screenshot(path="screenshot.png", full_page=True)
# 录像(上下文级别)
context = browser.new_context(record_video_dir="videos/")
page = context.new_page()
# ... 执行操作 ...
context.close()  # 视频自动保存
# 追踪(Trace Viewer)
browser = p.chromium.launch()
context = browser.new_context()
context.tracing.start(screenshots=True, snapshots=True)
page = context.new_page()
# ... 执行操作 ...
context.tracing.stop(path="trace.zip")

使用 playwright show-trace trace.zip 命令打开图形化界面,回放每一步截图、DOM 快照和日志。

高级配置与技巧

绕过反自动化检测

许多网站会检测自动化工具,Playwright 通过修改启动参数和上下文设置降低检测风险。

browser = p.chromium.launch(
    headless=False,
    args=["--disable-blink-features=AutomationControlled"]
)
context = browser.new_context(
    viewport={"width": 1920, "height": 1080},
    user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ..."
)
page.add_init_script("""
    Object.defineProperty(navigator, 'webdriver', {get: () => undefined});
""")

使用已安装的浏览器

如果你希望复用系统装的 Chrome 或 Edge,可以使用 channel 参数:

browser = p.chromium.launch(channel="chrome")   # 或 "msedge"

注意需要先通过 playwright install chromeplaywright install msedge 安装 Playwright 的驱动适配。

并行与性能

异步 API 配合 asyncio.gather 可以同时运行多个浏览器实例,大幅提升抓取或测试效率。对于大量页面,可使用 context.new_page() 而非创建多个上下文,以减少内存开销。

完整示例:表单提交与结果验证

以下示范一个典型的搜索提交并检查返回结果的流程:

from playwright.sync_api import sync_playwright
from playwright.sync_api import expect

with sync_playwright() as p:
    browser = p.chromium.launch(headless=False)
    context = browser.new_context(locale="zh-CN")
    page = context.new_page()
    page.goto("https://www.google.com")
    # 处理 Cookies 同意弹窗
    try:
        page.get_by_text("接受全部").click(timeout=3000)
    except:
        pass
    # 执行搜索
    page.get_by_label("搜索", exact=True).fill("Playwright Python")
    page.keyboard.press("Enter")
    # 等待结果加载
    first_result = page.locator("h3").first
    expect(first_result).to_be_visible()
    print(first_result.text_content())
    # 验证标题包含搜索词
    expect(page).to_have_title("Playwright Python - Google 搜索")
    browser.close()

测试集成与 CI 建议

  • Playwright 与 pytest 深度集成,通过 pytest-playwright 插件可提供 page, browser 等夹具。
  • 在 Docker 中运行:
    docker run -it mcr.microsoft.com/playwright/python:v1.XX-jammy
    
  • 无头模式下推荐使用 --headless=new 参数,避免云环境图形依赖问题。

常见问题排查

  • 元素找不到:使用 page.pause() 进入交互调试模式,或开启 PWDEBUG=1 环境变量。
  • 网络超时:通过 page.set_default_timeout(60000) 调整,或对特定操作设置 timeout 参数。
  • 浏览器未自动下载:手动执行 python -m playwright install chromium

Playwright Python 凭借简洁的 API、卓越的可靠性和丰富的调试工具,极大降低了浏览器自动化的门槛。掌握本文基础后,推荐阅读官方文档了解网络拦截、模拟移动设备、身份验证等高级主题,在真实项目中实践。