Python Playwright 语法知识详解(推荐)

 更新时间:2025年11月06日 09:37:05   作者:问道飞鱼  
Playwright 是一个强大的浏览器自动化框架,支持 Chromium、Firefox 和 WebKit,本文给大家介绍Python Playwright 语法知识详解,感兴趣的朋友跟随小编一起看看吧

Playwright for Python 语法详解

Playwright 是一个强大的浏览器自动化框架,支持 Chromium、Firefox 和 WebKit。以下是 Playwright for Python 的全面语法详解。

安装与设置

1. 安装 Playwright

# 安装 Playwright Python 包
pip install playwright
# 安装浏览器二进制文件
playwright install

2. 初始化项目

# 在项目目录中创建 requirements.txt
echo "playwright" > requirements.txt
# 创建基本的测试结构
mkdir tests
touch tests/test_example.py

基础语法结构

1. 同步与异步模式

同步模式
from playwright.sync_api import sync_playwright
def run_sync():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)
        page = browser.new_page()
        page.goto('https://example.com')
        browser.close()
run_sync()
异步模式
import asyncio
from playwright.async_api import async_playwright
async def run_async():
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=False)
        page = await browser.new_page()
        await page.goto('https://example.com')
        await browser.close()
asyncio.run(run_async())

2. 浏览器启动选项

# 各种浏览器启动选项
browser = p.chromium.launch(
    headless=False,           # 显示浏览器界面
    slow_mo=100,             # 操作间延迟(毫秒)
    args=['--start-maximized'],  # 浏览器参数
    executable_path='/path/to/chrome',  # 指定浏览器路径
    timeout=30000,            # 超时时间
    devtools=True,            # 打开开发者工具
    proxy={
        'server': 'http://proxy.example.com:8080',
        'username': 'user',
        'password': 'pass'
    }
)

页面导航与操作

1. 页面导航

# 基本导航
page.goto('https://example.com')
# 带选项的导航
page.goto('https://example.com', 
    timeout=30000,           # 超时时间
    wait_until='networkidle', # 等待条件:'load'|'domcontentloaded'|'networkidle'
    referer='https://google.com' # 设置referer
)
# 导航事件处理
page.on('load', lambda: print('Page loaded!'))
# 前进和后退
page.go_back()
page.go_forward()
# 重新加载
page.reload()

2. 等待策略

# 等待元素出现
page.wait_for_selector('#element-id', timeout=10000)
# 等待特定条件
page.wait_for_function('document.querySelector(".content").innerText.includes("Hello")')
# 等待超时
page.wait_for_timeout(3000)  # 等待3秒
# 等待导航完成
with page.expect_navigation():
    page.click('a#submit')
# 等待弹出窗口
with page.expect_popup() as popup_info:
    page.click('a[target="_blank"]')
popup = popup_info.value

元素定位与交互

1. 元素选择器

# CSS选择器
page.click('button.submit')
page.fill('input#username', 'myuser')
# XPath选择器
page.click('//button[text()="Submit"]')
# 文本选择器
page.click('text=Login')
page.click('text="Click here"')  # 精确匹配
# 组合选择器
page.click('div.container >> text=Submit')
# 根据属性选择
page.click('[data-testid="submit-button"]')
# 根据可见性选择
page.click('button:visible')
# 根据状态选择
page.click('button:enabled')
page.click('input:checked')

2. 元素交互方法

# 点击操作
page.click('button')
page.dblclick('button')
page.click('button', button='right')  # 右键点击
page.click('button', modifiers=['Shift'])  # 带修饰键点击
# 输入操作
page.fill('input#name', 'John Doe')
page.type('input#name', 'Hello World', delay=100)  # 模拟按键延迟
# 选择操作
page.select_option('select#colors', 'red')
page.select_option('select#colors', index=1)  # 按索引选择
page.select_option('select#colors', value=['red', 'blue'])  # 多选
# 复选框和单选按钮
page.check('input#agree')
page.uncheck('input#subscribe')
# 文件上传
page.set_input_files('input[type=file]', 'path/to/file.txt')
page.set_input_files('input[type=file]', ['file1.txt', 'file2.txt'])  # 多文件
# 聚焦和模糊
page.focus('input#search')
page.blur('input#search')
# 悬停
page.hover('div.menu-item')
# 拖放
page.drag_and_drop('#source', '#target')

3. 元素状态检查

# 检查元素存在
if page.query_selector('div.error'):
    print('Error element exists')
# 检查元素可见性
is_visible = page.is_visible('div.popup')
is_hidden = page.is_hidden('div.loading')
# 检查元素状态
is_enabled = page.is_enabled('button.submit')
is_checked = page.is_checked('input#agree')
is_editable = page.is_editable('input#name')
# 获取元素属性
value = page.get_attribute('img#logo', 'src')
class_name = page.get_attribute('div.container', 'class')
# 获取元素文本
text = page.text_content('div.message')
inner_text = page.inner_text('div.message')
# 获取元素HTML
html = page.inner_html('div.container')
# 获取输入值
input_value = page.input_value('input#email')

高级交互技术

1. 键盘操作

# 键盘输入
page.keyboard.type('Hello World!')
page.keyboard.press('Enter')
page.keyboard.down('Shift')
page.keyboard.up('Shift')
# 快捷键
page.keyboard.press('Control+A')  # 全选
page.keyboard.press('Control+C')  # 复制
page.keyboard.press('Control+V')  # 粘贴
# 特殊键
page.keyboard.press('ArrowLeft')
page.keyboard.press('Tab')
page.keyboard.press('Escape')

2. 鼠标操作

# 获取元素位置
bounding_box = page.query_selector('button').bounding_box()
# 精确鼠标控制
page.mouse.move(bounding_box['x'] + bounding_box['width']/2, 
                bounding_box['y'] + bounding_box['height']/2)
page.mouse.click(bounding_box['x'] + bounding_box['width']/2, 
                 bounding_box['y'] + bounding_box['height']/2)
# 鼠标拖拽
page.mouse.down()
page.mouse.move(100, 100)
page.mouse.up()

3. 触摸屏模拟

# 触摸操作
page.touchscreen.tap(100, 100)
# 多点触控
page.touchscreen.tap_point(100, 100)
page.touchscreen.tap_point(200, 200)

页面与框架管理

1. 多页面处理

# 获取所有页面
all_pages = context.pages
# 创建新页面
new_page = context.new_page()
# 等待新页面
with context.expect_page() as new_page_info:
    page.click('a[target="_blank"]')
new_page = new_page_info.value
# 切换到特定页面
context.pages[1].bring_to_front()

2. 框架处理

# 获取框架
frame = page.frame(name='frame-name')
frame = page.frame(url=r'.*login.*')
# 框架内操作
frame.click('button.submit')
frame.fill('input#username', 'user')
# 遍历所有框架
for frame in page.frames:
    print(frame.name)

3. 页面上下文

# 执行JavaScript
page.evaluate('document.title')
result = page.evaluate('([x, y]) => x + y', [1, 2])
# 注入JavaScript
page.add_script_tag(url='https://code.jquery.com/jquery.js')
page.add_script_tag(content='console.log("Hello");')
# 注入样式
page.add_style_tag(url='https://cdn.example.com/style.css')
page.add_style_tag(content='body { background: red; }')
# 设置页面内容
page.set_content('<html><body><h1>Hello</h1></body></html>')

网络请求处理

1. 请求拦截与修改

# 路由拦截
def handle_route(route):
    if 'api.example.com' in route.request.url:
        route.fulfill(
            status=200,
            content_type='application/json',
            body='{"success": true}'
        )
    else:
        route.continue_()
page.route('**/*', handle_route)
# 特定模式拦截
page.route('**/*.jpg', lambda route: route.abort())
page.route('**/api/*', handle_route)
# 修改请求头
page.route('**/*', lambda route: route.continue_(headers={**route.request.headers, 'x-custom': 'value'}))

2. 请求监控

# 请求事件处理
def log_request(request):
    print(f"Request: {request.method} {request.url}")
def log_response(response):
    print(f"Response: {response.status} {response.url}")
page.on('request', log_request)
page.on('response', log_response)
# 等待请求完成
with page.expect_response('https://example.com/api/data') as response_info:
    page.click('button#load-data')
response = response_info.value
# 等待多个请求
with page.expect_response(lambda response: response.url.startswith('https://api')) as response_info:
    page.click('button#fetch')

3. API请求直接调用

# 使用Playwright发起API请求
response = page.request.get('https://api.example.com/data')
print(response.json())
# 带参数的请求
response = page.request.post(
    'https://api.example.com/login',
    data={'username': 'user', 'password': 'pass'},
    headers={'Content-Type': 'application/json'}
)

断言与验证

1. 内置断言

# 页面标题断言
assert page.title() == 'Expected Title'
# URL断言
assert page.url == 'https://example.com'
# 元素可见性断言
assert page.is_visible('div.success')
# 文本内容断言
assert 'Welcome' in page.text_content('body')

2. 等待断言

# 等待元素出现并断言
page.wait_for_selector('div.success', state='visible')
assert page.text_content('div.success') == 'Operation successful'
# 等待文本出现
page.wait_for_selector('text=Welcome back')
# 等待函数条件
page.wait_for_function('() => document.querySelectorAll(".item").length > 5')

截图与PDF生成

1. 截图功能

# 页面截图
page.screenshot(path='screenshot.png')
# 元素截图
page.locator('div.chart').screenshot(path='chart.png')
# 截图选项
page.screenshot(
    path='fullpage.png',
    full_page=True,           # 截取完整页面
    type='jpeg',              # 图片类型:'png'|'jpeg'
    quality=80,               # JPEG质量(0-100)
    omit_background=True,     # 隐藏默认背景
    timeout=10000             # 超时时间
)

2. PDF生成

# 生成PDF
page.pdf(
    path='page.pdf',
    scale=0.8,                # 缩放比例
    format='A4',              # 纸张格式
    margin={'top': '1cm', 'bottom': '1cm'},  # 边距
    print_background=True,    # 打印背景
    landscape=False           # 横向/纵向
)

高级功能

1. 设备模拟

# 模拟移动设备
from playwright.sync_api import sync_playwright
def test_mobile():
    with sync_playwright() as p:
        # 获取设备描述符
        iPhone = p.devices['iPhone 12 Pro']
        # 使用设备模拟创建上下文
        browser = p.chromium.launch()
        context = browser.new_context(**iPhone)
        page = context.new_page()
        page.goto('https://example.com')
        # 移动端测试代码...
        browser.close()

2. 地理位置与权限

# 模拟地理位置
context = browser.new_context(
    geolocation={'longitude': 116.397128, 'latitude': 39.916697},
    permissions=['geolocation']
)
# 模拟权限
context = browser.new_context(
    permissions=['notifications', 'microphone']
)

3. Cookie与存储

# 设置Cookie
context.add_cookies([{
    'name': 'session',
    'value': 'abc123',
    'url': 'https://example.com',
    'domain': 'example.com',
    'path': '/',
    'httpOnly': True,
    'secure': True,
    'expires': int(time.time()) + 3600  # 1小时后过期
}])
# 获取Cookie
cookies = context.cookies()

测试框架集成

1. 与Pytest集成

# conftest.py
import pytest
from playwright.sync_api import sync_playwright
@pytest.fixture(scope='session')
def browser():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)
        yield browser
        browser.close()
@pytest.fixture
def page(browser):
    context = browser.new_context()
    page = context.new_page()
    yield page
    context.close()
# test_example.py
def test_login(page):
    page.goto('https://example.com/login')
    page.fill('input#username', 'testuser')
    page.fill('input#password', 'password')
    page.click('button#submit')
    assert page.url == 'https://example.com/dashboard'

2. 测试最佳实践

# 页面对象模型
class LoginPage:
    def __init__(self, page):
        self.page = page
        self.username_input = page.locator('input#username')
        self.password_input = page.locator('input#password')
        self.submit_button = page.locator('button#submit')
    def navigate(self):
        self.page.goto('https://example.com/login')
    def login(self, username, password):
        self.username_input.fill(username)
        self.password_input.fill(password)
        self.submit_button.click()
# 使用页面对象
def test_login(page):
    login_page = LoginPage(page)
    login_page.navigate()
    login_page.login('testuser', 'password')
    assert page.url == 'https://example.com/dashboard'

调试与故障排除

1. 调试技巧

# 启用调试模式
browser = p.chromium.launch(headless=False, devtools=True)
# 暂停执行
page.pause()
# 慢速模式
browser = p.chromium.launch(headless=False, slow_mo=1000)
# 记录控制台输出
page.on('console', lambda msg: print(f'CONSOLE: {msg.text}'))
# 记录页面错误
page.on('pageerror', lambda err: print(f'PAGE ERROR: {err}'))
# 记录请求失败
page.on('requestfailed', lambda req: print(f'REQUEST FAILED: {req.url} {req.failure}'))

2. 选择器调试

# 高亮匹配元素
page.locator('button').highlight()
# 评估选择器
count = page.locator('button').count()
print(f'Found {count} buttons')
# 调试选择器
try:
    page.wait_for_selector('button:visible', timeout=5000)
except:
    print('Button not found within 5 seconds')

性能优化

1. 浏览器上下文复用

# 复用浏览器上下文
context = browser.new_context()
# 在不同测试中复用
def test_1(context):
    page = context.new_page()
    # 测试代码...
def test_2(context):
    page = context.new_page()
    # 测试代码...
# 清理上下文
context.clear_cookies()
context.clear_permissions()

2. 并行执行

# 使用多线程并行测试
import concurrent.futures
def run_test(test_func, browser_type):
    with sync_playwright() as p:
        browser = getattr(p, browser_type).launch()
        context = browser.new_context()
        page = context.new_page()
        test_func(page)
        browser.close()
with concurrent.futures.ThreadPoolExecutor() as executor:
    futures = []
    for _ in range(3):
        futures.append(executor.submit(run_test, test_function, 'chromium'))
    for future in concurrent.futures.as_completed(futures):
        future.result()

总结

Playwright for Python 提供了强大而灵活的浏览器自动化能力。通过掌握上述语法和技巧,您可以:

  1. 创建可靠的浏览器自动化脚本
  2. 实现复杂的用户交互模拟
  3. 处理各种网络条件和异常情况
  4. 集成到现有的测试框架中
  5. 优化脚本性能和稳定性

Playwright 的持续更新和活跃社区确保了其功能的不断改进和扩展,使其成为现代Web自动化测试的首选工具之一。

相关文献

Playwright for Python 推荐项目结构
【Python知识】使用 Playwright for Python 从零开始搭建自动化测试方案
【Python知识】Playwright for Python 脚本录制指南

到此这篇关于Python Playwright 语法知识详解的文章就介绍到这了,更多相关Python Playwright 语法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 在Pytorch中计算卷积方法的区别详解(conv2d的区别)

    在Pytorch中计算卷积方法的区别详解(conv2d的区别)

    今天小编就为大家分享一篇在Pytorch中计算卷积方法的区别详解(conv2d的区别),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-01-01
  • python中append实例用法总结

    python中append实例用法总结

    在本篇文章中小编给各位分享的是关于python中append实例用法以及相关知识点,需要的朋友们可以学习下。
    2019-07-07
  • 基于python模拟TCP3次握手连接及发送数据

    基于python模拟TCP3次握手连接及发送数据

    这篇文章主要介绍了基于python模拟TCP3次握手连接及发送数据,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • Python实现动态加载模块、类、函数的方法分析

    Python实现动态加载模块、类、函数的方法分析

    这篇文章主要介绍了Python实现动态加载模块、类、函数的方法,结合实例形式分析了Python动态加载模块、类及函数的实现方法及操作技巧,需要的朋友可以参考下
    2017-07-07
  • Django配置Mysql数据库连接的实现

    Django配置Mysql数据库连接的实现

    本文主要介绍了Django配置Mysql数据库连接的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • Java Unsafe类实现原理及测试代码

    Java Unsafe类实现原理及测试代码

    这篇文章主要介绍了Java Unsafe类实现原理及测试代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • python判断链表是否有环的实例代码

    python判断链表是否有环的实例代码

    在本篇文章里小编给大家整理的是关于python判断链表是否有环的知识点及实例代码,需要的朋友们参考下。
    2020-01-01
  • Matplotlib绘制子图的常见几种方法

    Matplotlib绘制子图的常见几种方法

    Matplotlib的可以把很多张图画到一个显示界面,在作对比分析的时候非常有用。本文就介绍了几种方法,需要的朋友们下面随着小编来一起学习学习吧
    2021-05-05
  • python 返回列表中某个值的索引方法

    python 返回列表中某个值的索引方法

    今天小编就为大家分享一篇python 返回列表中某个值的索引方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-11-11
  • python获取本地计算机名字的方法

    python获取本地计算机名字的方法

    这篇文章主要介绍了python获取本地计算机名字的方法,涉及Python获取本地计算机信息的相关技巧,非常简单实用,需要的朋友可以参考下
    2015-04-04

最新评论