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 语法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Django中使用session保持用户登陆连接的例子

    Django中使用session保持用户登陆连接的例子

    今天小编就为大家分享一篇Django中使用session保持用户登陆连接的例子,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-08-08
  • Python中导入自定义模块的几种方法总结

    Python中导入自定义模块的几种方法总结

    这篇文章主要介绍了Python中导入自定义模块的几种方法总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01
  • Python 如何定义匿名或内联函数

    Python 如何定义匿名或内联函数

    这篇文章主要介绍了Python 如何定义匿名或内联函数,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-08-08
  • 如何解决Visdom全蓝,不显示内容问题

    如何解决Visdom全蓝,不显示内容问题

    这篇文章主要介绍了如何解决Visdom全蓝,不显示内容问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • Python学习思维导图(必看篇)

    Python学习思维导图(必看篇)

    下面小编就为大家带来一篇Python学习思维导图(必看篇)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • python exe文件解包方法总结

    python exe文件解包方法总结

    这篇文章总结了如何从Python EXE文件中提取和反编译Python脚本(.pyc文件)的过程,包括使用pyinstxtractor.py或archive_viewer.py进行解包,感兴趣的小伙伴跟着小编一起来看看吧
    2025-03-03
  • Python调用Windows命令打印文件

    Python调用Windows命令打印文件

    Windows命令行打印文件使用print 命令,具体用法可使用help print查看,下面是使用Python调用print指令执行打印文件功能的代码,需要的朋友可以参考下
    2020-02-02
  • 使用Python实现加密或解密Word文档

    使用Python实现加密或解密Word文档

    在日常办公和文档管理中,保护敏感信息的安全性至关重要,本文详细介绍了使用 Spire.Doc for Python 对 Word 文档进行加密和解密的多种方法,感兴趣的小伙伴可以了解下
    2026-05-05
  • pytorch 在网络中添加可训练参数,修改预训练权重文件的方法

    pytorch 在网络中添加可训练参数,修改预训练权重文件的方法

    今天小编就为大家分享一篇pytorch 在网络中添加可训练参数,修改预训练权重文件的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-08-08
  • 5款非常棒的Python工具

    5款非常棒的Python工具

    这篇文章主要为大家详细介绍了5款非常棒的Python工具,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01

最新评论