Python Playwright 語法知識詳解(推薦)
Playwright for Python 語法詳解
Playwright 是一個強大的瀏覽器自動化框架,支持 Chromium、Firefox 和 WebKit。以下是 Playwright for Python 的全面語法詳解。
安裝與設(shè)置
1. 安裝 Playwright
# 安裝 Playwright Python 包 pip install playwright # 安裝瀏覽器二進(jìn)制文件 playwright install
2. 初始化項目
# 在項目目錄中創(chuàng)建 requirements.txt echo "playwright" > requirements.txt # 創(chuàng)建基本的測試結(jié)構(gòu) mkdir tests touch tests/test_example.py
基礎(chǔ)語法結(jié)構(gòu)
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'], # 瀏覽器參數(shù)
executable_path='/path/to/chrome', # 指定瀏覽器路徑
timeout=30000, # 超時時間
devtools=True, # 打開開發(fā)者工具
proxy={
'server': 'http://proxy.example.com:8080',
'username': 'user',
'password': 'pass'
}
)頁面導(dǎo)航與操作
1. 頁面導(dǎo)航
# 基本導(dǎo)航
page.goto('https://example.com')
# 帶選項的導(dǎo)航
page.goto('https://example.com',
timeout=30000, # 超時時間
wait_until='networkidle', # 等待條件:'load'|'domcontentloaded'|'networkidle'
referer='https://google.com' # 設(shè)置referer
)
# 導(dǎo)航事件處理
page.on('load', lambda: print('Page loaded!'))
# 前進(jìn)和后退
page.go_back()
page.go_forward()
# 重新加載
page.reload()2. 等待策略
# 等待元素出現(xiàn)
page.wait_for_selector('#element-id', timeout=10000)
# 等待特定條件
page.wait_for_function('document.querySelector(".content").innerText.includes("Hello")')
# 等待超時
page.wait_for_timeout(3000) # 等待3秒
# 等待導(dǎo)航完成
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')
# 根據(jù)屬性選擇
page.click('[data-testid="submit-button"]')
# 根據(jù)可見性選擇
page.click('button:visible')
# 根據(jù)狀態(tài)選擇
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']) # 多選
# 復(fù)選框和單選按鈕
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. 元素狀態(tài)檢查
# 檢查元素存在
if page.query_selector('div.error'):
print('Error element exists')
# 檢查元素可見性
is_visible = page.is_visible('div.popup')
is_hidden = page.is_hidden('div.loading')
# 檢查元素狀態(tài)
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')高級交互技術(shù)
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') # 復(fù)制
page.keyboard.press('Control+V') # 粘貼
# 特殊鍵
page.keyboard.press('ArrowLeft')
page.keyboard.press('Tab')
page.keyboard.press('Escape')2. 鼠標(biāo)操作
# 獲取元素位置
bounding_box = page.query_selector('button').bounding_box()
# 精確鼠標(biāo)控制
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)
# 鼠標(biāo)拖拽
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
# 創(chuàng)建新頁面
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.*')
# 框架內(nèi)操作
frame.click('button.submit')
frame.fill('input#username', 'user')
# 遍歷所有框架
for frame in page.frames:
print(frame.name)3. 頁面上下文
# 執(zhí)行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; }')
# 設(shè)置頁面內(nèi)容
page.set_content('<html><body><h1>Hello</h1></body></html>')網(wǎng)絡(luò)請求處理
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. 請求監(jiān)控
# 請求事件處理
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請求直接調(diào)用
# 使用Playwright發(fā)起API請求
response = page.request.get('https://api.example.com/data')
print(response.json())
# 帶參數(shù)的請求
response = page.request.post(
'https://api.example.com/login',
data={'username': 'user', 'password': 'pass'},
headers={'Content-Type': 'application/json'}
)斷言與驗證
1. 內(nèi)置斷言
# 頁面標(biāo)題斷言
assert page.title() == 'Expected Title'
# URL斷言
assert page.url == 'https://example.com'
# 元素可見性斷言
assert page.is_visible('div.success')
# 文本內(nèi)容斷言
assert 'Welcome' in page.text_content('body')2. 等待斷言
# 等待元素出現(xiàn)并斷言
page.wait_for_selector('div.success', state='visible')
assert page.text_content('div.success') == 'Operation successful'
# 等待文本出現(xiàn)
page.wait_for_selector('text=Welcome back')
# 等待函數(shù)條件
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質(zhì)量(0-100)
omit_background=True, # 隱藏默認(rèn)背景
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. 設(shè)備模擬
# 模擬移動設(shè)備
from playwright.sync_api import sync_playwright
def test_mobile():
with sync_playwright() as p:
# 獲取設(shè)備描述符
iPhone = p.devices['iPhone 12 Pro']
# 使用設(shè)備模擬創(chuàng)建上下文
browser = p.chromium.launch()
context = browser.new_context(**iPhone)
page = context.new_page()
page.goto('https://example.com')
# 移動端測試代碼...
browser.close()2. 地理位置與權(quán)限
# 模擬地理位置
context = browser.new_context(
geolocation={'longitude': 116.397128, 'latitude': 39.916697},
permissions=['geolocation']
)
# 模擬權(quán)限
context = browser.new_context(
permissions=['notifications', 'microphone']
)3. Cookie與存儲
# 設(shè)置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'調(diào)試與故障排除
1. 調(diào)試技巧
# 啟用調(diào)試模式
browser = p.chromium.launch(headless=False, devtools=True)
# 暫停執(zhí)行
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. 選擇器調(diào)試
# 高亮匹配元素
page.locator('button').highlight()
# 評估選擇器
count = page.locator('button').count()
print(f'Found {count} buttons')
# 調(diào)試選擇器
try:
page.wait_for_selector('button:visible', timeout=5000)
except:
print('Button not found within 5 seconds')性能優(yōu)化
1. 瀏覽器上下文復(fù)用
# 復(fù)用瀏覽器上下文
context = browser.new_context()
# 在不同測試中復(fù)用
def test_1(context):
page = context.new_page()
# 測試代碼...
def test_2(context):
page = context.new_page()
# 測試代碼...
# 清理上下文
context.clear_cookies()
context.clear_permissions()2. 并行執(zhí)行
# 使用多線程并行測試
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()總結(jié)
Playwright for Python 提供了強大而靈活的瀏覽器自動化能力。通過掌握上述語法和技巧,您可以:
- 創(chuàng)建可靠的瀏覽器自動化腳本
- 實現(xiàn)復(fù)雜的用戶交互模擬
- 處理各種網(wǎng)絡(luò)條件和異常情況
- 集成到現(xiàn)有的測試框架中
- 優(yōu)化腳本性能和穩(wěn)定性
Playwright 的持續(xù)更新和活躍社區(qū)確保了其功能的不斷改進(jìn)和擴展,使其成為現(xiàn)代Web自動化測試的首選工具之一。
相關(guān)文獻(xiàn)
Playwright for Python 推薦項目結(jié)構(gòu)
【Python知識】使用 Playwright for Python 從零開始搭建自動化測試方案
【Python知識】Playwright for Python 腳本錄制指南
到此這篇關(guān)于Python Playwright 語法知識詳解的文章就介紹到這了,更多相關(guān)Python Playwright 語法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python中導(dǎo)入自定義模塊的幾種方法總結(jié)
這篇文章主要介紹了Python中導(dǎo)入自定義模塊的幾種方法總結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-01-01
Python 如何定義匿名或內(nèi)聯(lián)函數(shù)
這篇文章主要介紹了Python 如何定義匿名或內(nèi)聯(lián)函數(shù),文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下2020-08-08
如何解決Visdom全藍(lán),不顯示內(nèi)容問題
這篇文章主要介紹了如何解決Visdom全藍(lán),不顯示內(nèi)容問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-06-06
Python學(xué)習(xí)思維導(dǎo)圖(必看篇)
下面小編就為大家?guī)硪黄狿ython學(xué)習(xí)思維導(dǎo)圖(必看篇)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-06-06
pytorch 在網(wǎng)絡(luò)中添加可訓(xùn)練參數(shù),修改預(yù)訓(xùn)練權(quán)重文件的方法
今天小編就為大家分享一篇pytorch 在網(wǎng)絡(luò)中添加可訓(xùn)練參數(shù),修改預(yù)訓(xùn)練權(quán)重文件的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-08-08

