playwright-browser
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePlaywright Browser Automation
Playwright浏览器自动化
Use this skill for capturing screenshots, web scraping, form automation, and browser-based testing.
本技能可用于截图捕获、网页爬取、表单自动化以及浏览器端测试。
Quick Start
快速开始
The project's venv has Playwright installed. Always use the venv Python:
bash
undefined项目的venv环境已安装Playwright。请始终使用venv中的Python:
bash
undefinedRun Playwright scripts
Run Playwright scripts
.venv/bin/python scripts/my_playwright_script.py
.venv/bin/python scripts/my_playwright_script.py
Install browsers if needed (one-time)
Install browsers if needed (one-time)
.venv/bin/playwright install chromium
undefined.venv/bin/playwright install chromium
undefinedScreenshot Capture
截图捕获
Basic Screenshot
基础截图
python
#!/Users/arun/dev/agents_webinar/.venv/bin/python
from playwright.sync_api import sync_playwright
def capture_screenshot(url: str, output_path: str) -> str:
"""Capture a screenshot of a webpage.
Args:
url: URL to capture
output_path: Path to save PNG file
Returns:
Path to saved screenshot
"""
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page(viewport={'width': 1280, 'height': 800})
page.goto(url, wait_until='networkidle')
page.screenshot(path=output_path)
browser.close()
return output_pathpython
#!/Users/arun/dev/agents_webinar/.venv/bin/python
from playwright.sync_api import sync_playwright
def capture_screenshot(url: str, output_path: str) -> str:
"""Capture a screenshot of a webpage.
Args:
url: URL to capture
output_path: Path to save PNG file
Returns:
Path to saved screenshot
"""
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page(viewport={'width': 1280, 'height': 800})
page.goto(url, wait_until='networkidle')
page.screenshot(path=output_path)
browser.close()
return output_pathUsage
Usage
capture_screenshot('https://example.com', 'screenshot.png')
undefinedcapture_screenshot('https://example.com', 'screenshot.png')
undefinedFull Page Screenshot
整页截图
python
def capture_full_page(url: str, output_path: str) -> str:
"""Capture full-page screenshot (scrolls entire page)."""
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page(viewport={'width': 1280, 'height': 800})
page.goto(url, wait_until='networkidle')
page.screenshot(path=output_path, full_page=True)
browser.close()
return output_pathpython
def capture_full_page(url: str, output_path: str) -> str:
"""Capture full-page screenshot (scrolls entire page)."""
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page(viewport={'width': 1280, 'height': 800})
page.goto(url, wait_until='networkidle')
page.screenshot(path=output_path, full_page=True)
browser.close()
return output_pathAbove-the-Fold Screenshot
首屏截图
python
def capture_above_fold(url: str, output_path: str, width: int = 1280, height: int = 800) -> str:
"""Capture only the visible viewport (above-the-fold content)."""
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page(viewport={'width': width, 'height': height})
page.goto(url, wait_until='networkidle')
# Viewport screenshot (not full_page)
page.screenshot(path=output_path, full_page=False)
browser.close()
return output_pathpython
def capture_above_fold(url: str, output_path: str, width: int = 1280, height: int = 800) -> str:
"""Capture only the visible viewport (above-the-fold content)."""
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page(viewport={'width': width, 'height': height})
page.goto(url, wait_until='networkidle')
# Viewport screenshot (not full_page)
page.screenshot(path=output_path, full_page=False)
browser.close()
return output_pathElement Screenshot
元素截图
python
def capture_element(url: str, selector: str, output_path: str) -> str:
"""Capture screenshot of a specific element."""
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto(url, wait_until='networkidle')
element = page.locator(selector)
element.screenshot(path=output_path)
browser.close()
return output_pathpython
def capture_element(url: str, selector: str, output_path: str) -> str:
"""Capture screenshot of a specific element."""
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto(url, wait_until='networkidle')
element = page.locator(selector)
element.screenshot(path=output_path)
browser.close()
return output_pathUsage
Usage
capture_element('https://example.com', 'header.hero', 'hero_section.png')
undefinedcapture_element('https://example.com', 'header.hero', 'hero_section.png')
undefinedAsync API (Recommended for Multiple Pages)
异步API(多页面场景推荐)
python
#!/Users/arun/dev/agents_webinar/.venv/bin/python
import asyncio
from playwright.async_api import async_playwright
async def capture_multiple_pages(urls: list[str], output_dir: str) -> list[str]:
"""Capture screenshots of multiple pages concurrently."""
async with async_playwright() as p:
browser = await p.chromium.launch()
async def capture_one(url: str) -> str:
page = await browser.new_page(viewport={'width': 1280, 'height': 800})
await page.goto(url, wait_until='networkidle')
filename = url.replace('https://', '').replace('/', '_') + '.png'
path = f"{output_dir}/{filename}"
await page.screenshot(path=path)
await page.close()
return path
results = await asyncio.gather(*[capture_one(url) for url in urls])
await browser.close()
return resultspython
#!/Users/arun/dev/agents_webinar/.venv/bin/python
import asyncio
from playwright.async_api import async_playwright
async def capture_multiple_pages(urls: list[str], output_dir: str) -> list[str]:
"""Capture screenshots of multiple pages concurrently."""
async with async_playwright() as p:
browser = await p.chromium.launch()
async def capture_one(url: str) -> str:
page = await browser.new_page(viewport={'width': 1280, 'height': 800})
await page.goto(url, wait_until='networkidle')
filename = url.replace('https://', '').replace('/', '_') + '.png'
path = f"{output_dir}/{filename}"
await page.screenshot(path=path)
await page.close()
return path
results = await asyncio.gather(*[capture_one(url) for url in urls])
await browser.close()
return resultsUsage
Usage
asyncio.run(capture_multiple_pages([
'https://example.com',
'https://example.com/pricing',
'https://example.com/about'
], 'screenshots'))
undefinedasyncio.run(capture_multiple_pages([
'https://example.com',
'https://example.com/pricing',
'https://example.com/about'
], 'screenshots'))
undefinedWait Strategies
等待策略
Wait Until Options
等待选项
python
undefinedpython
undefined'load' - Wait for load event (default)
'load' - Wait for load event (default)
page.goto(url, wait_until='load')
page.goto(url, wait_until='load')
'domcontentloaded' - Wait for DOMContentLoaded
'domcontentloaded' - Wait for DOMContentLoaded
page.goto(url, wait_until='domcontentloaded')
page.goto(url, wait_until='domcontentloaded')
'networkidle' - Wait until no network requests for 500ms (RECOMMENDED)
'networkidle' - Wait until no network requests for 500ms (RECOMMENDED)
page.goto(url, wait_until='networkidle')
page.goto(url, wait_until='networkidle')
'commit' - Wait for first byte of response
'commit' - Wait for first byte of response
page.goto(url, wait_until='commit')
undefinedpage.goto(url, wait_until='commit')
undefinedWait for Specific Elements
等待特定元素
python
undefinedpython
undefinedWait for element to be visible
Wait for element to be visible
page.wait_for_selector('.hero-cta', state='visible')
page.wait_for_selector('.hero-cta', state='visible')
Wait for element to be hidden
Wait for element to be hidden
page.wait_for_selector('.loading-spinner', state='hidden')
page.wait_for_selector('.loading-spinner', state='hidden')
Wait with timeout
Wait with timeout
page.wait_for_selector('.lazy-loaded-content', timeout=10000) # 10 seconds
undefinedpage.wait_for_selector('.lazy-loaded-content', timeout=10000) # 10 seconds
undefinedWait for Network Idle After Interaction
交互后等待网络空闲
python
undefinedpython
undefinedClick and wait for network to settle
Click and wait for network to settle
page.click('button.load-more')
page.wait_for_load_state('networkidle')
page.click('button.load-more')
page.wait_for_load_state('networkidle')
Then capture
Then capture
page.screenshot(path='after_load_more.png')
undefinedpage.screenshot(path='after_load_more.png')
undefinedElement Selection
元素选择
Locator Strategies
定位器策略
python
undefinedpython
undefinedCSS selector (most common)
CSS selector (most common)
page.locator('button.cta')
page.locator('#signup-form')
page.locator('[data-testid="hero-section"]')
page.locator('button.cta')
page.locator('#signup-form')
page.locator('[data-testid="hero-section"]')
Text content
Text content
page.locator('text=Sign Up Now')
page.get_by_text('Get Started')
page.locator('text=Sign Up Now')
page.get_by_text('Get Started')
Role-based (accessibility)
Role-based (accessibility)
page.get_by_role('button', name='Submit')
page.get_by_role('link', name='Pricing')
page.get_by_role('button', name='Submit')
page.get_by_role('link', name='Pricing')
Label (forms)
Label (forms)
page.get_by_label('Email address')
page.get_by_label('Email address')
Placeholder
Placeholder
page.get_by_placeholder('Enter your email')
page.get_by_placeholder('Enter your email')
Chained selectors
Chained selectors
page.locator('form').locator('button[type="submit"]')
undefinedpage.locator('form').locator('button[type="submit"]')
undefinedExtract Text Content
提取文本内容
python
def extract_page_content(url: str) -> dict:
"""Extract key text content from a page."""
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto(url, wait_until='networkidle')
content = {
'title': page.title(),
'h1': page.locator('h1').first.text_content() if page.locator('h1').count() > 0 else None,
'meta_description': page.locator('meta[name="description"]').get_attribute('content'),
'cta_buttons': [btn.text_content() for btn in page.locator('a.cta, button.cta').all()],
}
browser.close()
return contentpython
def extract_page_content(url: str) -> dict:
"""Extract key text content from a page."""
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto(url, wait_until='networkidle')
content = {
'title': page.title(),
'h1': page.locator('h1').first.text_content() if page.locator('h1').count() > 0 else None,
'meta_description': page.locator('meta[name="description"]').get_attribute('content'),
'cta_buttons': [btn.text_content() for btn in page.locator('a.cta, button.cta').all()],
}
browser.close()
return contentForm Automation
表单自动化
Fill and Submit Form
填写并提交表单
python
def fill_form(url: str, form_data: dict) -> str:
"""Fill out a form and capture result."""
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto(url, wait_until='networkidle')
# Fill text fields
page.fill('input[name="email"]', form_data['email'])
page.fill('input[name="company"]', form_data['company'])
# Select dropdown
page.select_option('select[name="country"]', form_data['country'])
# Check checkbox
page.check('input[name="agree_terms"]')
# Click submit
page.click('button[type="submit"]')
# Wait for navigation/result
page.wait_for_load_state('networkidle')
# Capture result
page.screenshot(path='form_result.png')
browser.close()
return 'form_result.png'python
def fill_form(url: str, form_data: dict) -> str:
"""Fill out a form and capture result."""
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto(url, wait_until='networkidle')
# Fill text fields
page.fill('input[name="email"]', form_data['email'])
page.fill('input[name="company"]', form_data['company'])
# Select dropdown
page.select_option('select[name="country"]', form_data['country'])
# Check checkbox
page.check('input[name="agree_terms"]')
# Click submit
page.click('button[type="submit"]')
# Wait for navigation/result
page.wait_for_load_state('networkidle')
# Capture result
page.screenshot(path='form_result.png')
browser.close()
return 'form_result.png'Mobile Screenshots
移动端截图
python
from playwright.sync_api import sync_playwright
def capture_mobile(url: str, output_path: str) -> str:
"""Capture screenshot with mobile viewport."""
with sync_playwright() as p:
# Use iPhone 12 device profile
iphone = p.devices['iPhone 12']
browser = p.chromium.launch()
context = browser.new_context(**iphone)
page = context.new_page()
page.goto(url, wait_until='networkidle')
page.screenshot(path=output_path)
browser.close()
return output_pathpython
from playwright.sync_api import sync_playwright
def capture_mobile(url: str, output_path: str) -> str:
"""Capture screenshot with mobile viewport."""
with sync_playwright() as p:
# Use iPhone 12 device profile
iphone = p.devices['iPhone 12']
browser = p.chromium.launch()
context = browser.new_context(**iphone)
page = context.new_page()
page.goto(url, wait_until='networkidle')
page.screenshot(path=output_path)
browser.close()
return output_pathAvailable device profiles include:
Available device profiles include:
'iPhone 12', 'iPhone 12 Pro Max', 'iPhone SE'
'iPhone 12', 'iPhone 12 Pro Max', 'iPhone SE'
'iPad Pro', 'iPad Mini'
'iPad Pro', 'iPad Mini'
'Pixel 5', 'Galaxy S9+'
'Pixel 5', 'Galaxy S9+'
'Desktop Chrome', 'Desktop Firefox', 'Desktop Safari'
'Desktop Chrome', 'Desktop Firefox', 'Desktop Safari'
undefinedundefinedPDF Generation
PDF生成
python
def generate_pdf(url: str, output_path: str) -> str:
"""Generate PDF from webpage (Chromium only)."""
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto(url, wait_until='networkidle')
page.pdf(
path=output_path,
format='A4',
print_background=True,
margin={'top': '1cm', 'bottom': '1cm', 'left': '1cm', 'right': '1cm'}
)
browser.close()
return output_pathpython
def generate_pdf(url: str, output_path: str) -> str:
"""Generate PDF from webpage (Chromium only)."""
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto(url, wait_until='networkidle')
page.pdf(
path=output_path,
format='A4',
print_background=True,
margin={'top': '1cm', 'bottom': '1cm', 'left': '1cm', 'right': '1cm'}
)
browser.close()
return output_pathError Handling
错误处理
python
from playwright.sync_api import sync_playwright, TimeoutError as PlaywrightTimeout
def safe_capture(url: str, output_path: str, timeout: int = 30000) -> dict:
"""Capture with comprehensive error handling."""
result = {'success': False, 'path': None, 'error': None}
try:
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page(viewport={'width': 1280, 'height': 800})
response = page.goto(url, wait_until='networkidle', timeout=timeout)
if response and response.status >= 400:
result['error'] = f"HTTP {response.status}"
else:
page.screenshot(path=output_path)
result['success'] = True
result['path'] = output_path
browser.close()
except PlaywrightTimeout:
result['error'] = f"Timeout after {timeout}ms"
except Exception as e:
result['error'] = str(e)
return resultpython
from playwright.sync_api import sync_playwright, TimeoutError as PlaywrightTimeout
def safe_capture(url: str, output_path: str, timeout: int = 30000) -> dict:
"""Capture with comprehensive error handling."""
result = {'success': False, 'path': None, 'error': None}
try:
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page(viewport={'width': 1280, 'height': 800})
response = page.goto(url, wait_until='networkidle', timeout=timeout)
if response and response.status >= 400:
result['error'] = f"HTTP {response.status}"
else:
page.screenshot(path=output_path)
result['success'] = True
result['path'] = output_path
browser.close()
except PlaywrightTimeout:
result['error'] = f"Timeout after {timeout}ms"
except Exception as e:
result['error'] = str(e)
return resultPerformance Tips
性能优化技巧
1. Reuse Browser Instance
1. 复用浏览器实例
python
undefinedpython
undefinedBad: Launch browser for each page
Bad: Launch browser for each page
for url in urls:
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto(url)
page.screenshot(...)
browser.close()
for url in urls:
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto(url)
page.screenshot(...)
browser.close()
Good: Reuse browser
Good: Reuse browser
with sync_playwright() as p:
browser = p.chromium.launch()
for url in urls:
page = browser.new_page()
page.goto(url)
page.screenshot(...)
page.close() # Close page, not browser
browser.close()
undefinedwith sync_playwright() as p:
browser = p.chromium.launch()
for url in urls:
page = browser.new_page()
page.goto(url)
page.screenshot(...)
page.close() # Close page, not browser
browser.close()
undefined2. Disable Unnecessary Resources
2. 禁用非必要资源
python
def fast_capture(url: str, output_path: str) -> str:
"""Fast capture by blocking non-essential resources."""
with sync_playwright() as p:
browser = p.chromium.launch()
context = browser.new_context()
# Block images, fonts, stylesheets for faster load
context.route('**/*.{png,jpg,jpeg,gif,svg,woff,woff2,ttf}',
lambda route: route.abort())
page = context.new_page()
page.goto(url, wait_until='domcontentloaded')
page.screenshot(path=output_path)
browser.close()
return output_pathpython
def fast_capture(url: str, output_path: str) -> str:
"""Fast capture by blocking non-essential resources."""
with sync_playwright() as p:
browser = p.chromium.launch()
context = browser.new_context()
# Block images, fonts, stylesheets for faster load
context.route('**/*.{png,jpg,jpeg,gif,svg,woff,woff2,ttf}',
lambda route: route.abort())
page = context.new_page()
page.goto(url, wait_until='domcontentloaded')
page.screenshot(path=output_path)
browser.close()
return output_path3. Headless vs Headed Mode
3. 无头模式与有头模式
python
undefinedpython
undefinedHeadless (default, faster, no UI)
Headless (default, faster, no UI)
browser = p.chromium.launch(headless=True)
browser = p.chromium.launch(headless=True)
Headed (shows browser, useful for debugging)
Headed (shows browser, useful for debugging)
browser = p.chromium.launch(headless=False)
browser = p.chromium.launch(headless=False)
Slow motion (for demos)
Slow motion (for demos)
browser = p.chromium.launch(headless=False, slow_mo=500) # 500ms between actions
undefinedbrowser = p.chromium.launch(headless=False, slow_mo=500) # 500ms between actions
undefinedCRO Analysis Pattern (Demo 6)
CRO分析模式(演示6)
python
#!/Users/arun/dev/agents_webinar/.venv/bin/python
"""Capture landing page for CRO analysis."""
from playwright.sync_api import sync_playwright
import json
def capture_for_cro_analysis(url: str, output_dir: str) -> dict:
"""Capture screenshots and metadata for CRO analysis.
Returns dict with paths to:
- above_fold.png: What users see first
- full_page.png: Complete page
- metadata.json: Page info (title, CTAs, etc.)
"""
with sync_playwright() as p:
browser = p.chromium.launch()
# Desktop viewport
page = browser.new_page(viewport={'width': 1280, 'height': 800})
page.goto(url, wait_until='networkidle')
# Above-the-fold
above_fold_path = f"{output_dir}/above_fold.png"
page.screenshot(path=above_fold_path, full_page=False)
# Full page
full_page_path = f"{output_dir}/full_page.png"
page.screenshot(path=full_page_path, full_page=True)
# Extract metadata
metadata = {
'url': url,
'title': page.title(),
'h1': page.locator('h1').first.text_content() if page.locator('h1').count() > 0 else None,
'cta_count': page.locator('a.cta, button.cta, [class*="cta"], [class*="btn-primary"]').count(),
'form_count': page.locator('form').count(),
'image_count': page.locator('img').count(),
}
metadata_path = f"{output_dir}/metadata.json"
with open(metadata_path, 'w') as f:
json.dump(metadata, f, indent=2)
browser.close()
return {
'above_fold': above_fold_path,
'full_page': full_page_path,
'metadata': metadata_path
}
if __name__ == '__main__':
import sys
url = sys.argv[1] if len(sys.argv) > 1 else 'https://www.reform.app/done-for-you-forms'
output_dir = sys.argv[2] if len(sys.argv) > 2 else 'demos/06-vision-audit/outputs'
result = capture_for_cro_analysis(url, output_dir)
print(f"Captured: {result}")python
#!/Users/arun/dev/agents_webinar/.venv/bin/python
"""Capture landing page for CRO analysis."""
from playwright.sync_api import sync_playwright
import json
def capture_for_cro_analysis(url: str, output_dir: str) -> dict:
"""Capture screenshots and metadata for CRO analysis.
Returns dict with paths to:
- above_fold.png: What users see first
- full_page.png: Complete page
- metadata.json: Page info (title, CTAs, etc.)
"""
with sync_playwright() as p:
browser = p.chromium.launch()
# Desktop viewport
page = browser.new_page(viewport={'width': 1280, 'height': 800})
page.goto(url, wait_until='networkidle')
# Above-the-fold
above_fold_path = f"{output_dir}/above_fold.png"
page.screenshot(path=above_fold_path, full_page=False)
# Full page
full_page_path = f"{output_dir}/full_page.png"
page.screenshot(path=full_page_path, full_page=True)
# Extract metadata
metadata = {
'url': url,
'title': page.title(),
'h1': page.locator('h1').first.text_content() if page.locator('h1').count() > 0 else None,
'cta_count': page.locator('a.cta, button.cta, [class*="cta"], [class*="btn-primary"]').count(),
'form_count': page.locator('form').count(),
'image_count': page.locator('img').count(),
}
metadata_path = f"{output_dir}/metadata.json"
with open(metadata_path, 'w') as f:
json.dump(metadata, f, indent=2)
browser.close()
return {
'above_fold': above_fold_path,
'full_page': full_page_path,
'metadata': metadata_path
}
if __name__ == '__main__':
import sys
url = sys.argv[1] if len(sys.argv) > 1 else 'https://www.reform.app/done-for-you-forms'
output_dir = sys.argv[2] if len(sys.argv) > 2 else 'demos/06-vision-audit/outputs'
result = capture_for_cro_analysis(url, output_dir)
print(f"Captured: {result}")Troubleshooting
故障排除
"Browser not found"
"浏览器未找到"
bash
undefinedbash
undefinedInstall Chromium browser
Install Chromium browser
.venv/bin/playwright install chromium
.venv/bin/playwright install chromium
Or install all browsers
Or install all browsers
.venv/bin/playwright install
undefined.venv/bin/playwright install
undefined"Timeout waiting for page"
"页面等待超时"
python
undefinedpython
undefinedIncrease timeout
Increase timeout
page.goto(url, timeout=60000) # 60 seconds
page.goto(url, timeout=60000) # 60 seconds
Or use less strict wait
Or use less strict wait
page.goto(url, wait_until='domcontentloaded') # Faster than 'networkidle'
undefinedpage.goto(url, wait_until='domcontentloaded') # Faster than 'networkidle'
undefined"Element not found"
"元素未找到"
python
undefinedpython
undefinedCheck if element exists first
Check if element exists first
if page.locator('.cta-button').count() > 0:
page.locator('.cta-button').click()
else:
print("CTA button not found")
undefinedif page.locator('.cta-button').count() > 0:
page.locator('.cta-button').click()
else:
print("CTA button not found")
undefinedSSL/Certificate Errors
SSL/证书错误
python
undefinedpython
undefinedIgnore HTTPS errors (use cautiously)
Ignore HTTPS errors (use cautiously)
context = browser.new_context(ignore_https_errors=True)
undefinedcontext = browser.new_context(ignore_https_errors=True)
undefinedQuick Reference
快速参考
Screenshot types:
- - Viewport only
page.screenshot(path='file.png') - - Full scrollable page
page.screenshot(path='file.png', full_page=True) - - Specific element
element.screenshot(path='file.png')
Wait strategies:
- - Most reliable for dynamic pages
wait_until='networkidle' - - Faster, for static pages
wait_until='domcontentloaded' - - Wait for specific element
page.wait_for_selector('.class')
Viewport sizes:
- Desktop: 1280x800 or 1920x1080
- Tablet: 768x1024
- Mobile: Use
p.devices['iPhone 12']
Best practices:
- Always use context manager
with sync_playwright() - Use for JS-heavy pages
wait_until='networkidle' - Close pages/browsers to free resources
- Handle timeouts gracefully
- Use async API for multiple concurrent captures
截图类型:
- - 仅视口区域
page.screenshot(path='file.png') - - 完整可滚动页面
page.screenshot(path='file.png', full_page=True) - - 特定元素
element.screenshot(path='file.png')
等待策略:
- - 动态页面最可靠
wait_until='networkidle' - - 速度更快,适用于静态页面
wait_until='domcontentloaded' - - 等待特定元素
page.wait_for_selector('.class')
视口尺寸:
- 桌面端:1280x800 或 1920x1080
- 平板端:768x1024
- 移动端:使用
p.devices['iPhone 12']
最佳实践:
- 始终使用 上下文管理器
with sync_playwright() - 针对JS重页面使用
wait_until='networkidle' - 关闭页面/浏览器以释放资源
- 优雅处理超时
- 多页面并发捕获使用异步API