Python Playwright 语法知识详解(推荐)
作者:问道飞鱼
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 提供了强大而灵活的浏览器自动化能力。通过掌握上述语法和技巧,您可以:
- 创建可靠的浏览器自动化脚本
- 实现复杂的用户交互模拟
- 处理各种网络条件和异常情况
- 集成到现有的测试框架中
- 优化脚本性能和稳定性
Playwright 的持续更新和活跃社区确保了其功能的不断改进和扩展,使其成为现代Web自动化测试的首选工具之一。
相关文献
Playwright for Python 推荐项目结构
【Python知识】使用 Playwright for Python 从零开始搭建自动化测试方案
【Python知识】Playwright for Python 脚本录制指南
到此这篇关于Python Playwright 语法知识详解的文章就介绍到这了,更多相关Python Playwright 语法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
