# Playwright (Python) 安裝與使用筆記 ## 基本資訊 - **專案**: https://github.com/microsoft/playwright-python - **版本**: 1.51.0 - **作者**: Microsoft - **授權**: Apache-2.0 - **需求**: Python 3.8+ - **文件**: https://playwright.dev/python/docs/intro - **安裝日期**: 2026-04-15 ## 安裝 ```bash pip install playwright # 安裝 Python 套件 playwright install # 下載瀏覽器(Chromium、Firefox、WebKit) playwright install chromium # 只裝特定瀏覽器 ``` ### 已安裝的瀏覽器 | 瀏覽器 | 版本 | 路徑 | |--------|------|------| | Chromium | — | ~/Library/Caches/ms-playwright/ | | Firefox | 135.0 | ~/Library/Caches/ms-playwright/firefox-1475 | | WebKit | 18.4 | ~/Library/Caches/ms-playwright/webkit-2140 | ## 同步 API ```python from playwright.sync_api import sync_playwright with sync_playwright() as p: browser = p.chromium.launch() # 無頭模式 # browser = p.chromium.launch(headless=False) # 有頭模式(看得到瀏覽器) page = browser.new_page() page.goto("https://example.com") print(page.title()) page.screenshot(path="screenshot.png") browser.close() ``` ## 非同步 API ```python import asyncio from playwright.async_api import async_playwright async def main(): async with async_playwright() as p: browser = await p.chromium.launch() page = await browser.new_page() await page.goto("https://example.com") print(await page.title()) await page.screenshot(path="screenshot.png") await browser.close() asyncio.run(main()) ``` ## 常用操作 ### 選取元素與互動 ```python # 點擊 page.click("text=登入") page.click("#submit-btn") page.click("button.primary") # 填寫表單 page.fill("#username", "user@example.com") page.fill("#password", "secret") # 選擇下拉選單 page.select_option("select#color", "blue") # 勾選 checkbox page.check("#agree") # 等待元素出現 page.wait_for_selector(".result") # 取得文字內容 text = page.text_content(".message") inner = page.inner_text("h1") ``` ### 截圖與 PDF ```python # 截圖 page.screenshot(path="page.png") page.screenshot(path="full.png", full_page=True) # 特定元素截圖 page.locator(".card").screenshot(path="card.png") # 存成 PDF(僅 Chromium 支援) page.pdf(path="page.pdf") ``` ### Locator(推薦的選取方式) ```python # 依角色 page.get_by_role("button", name="送出") # 依文字 page.get_by_text("歡迎光臨") # 依 label page.get_by_label("電子郵件") # 依 placeholder page.get_by_placeholder("搜尋...") # 依 test id page.get_by_test_id("login-form") # 鏈式操作 page.locator(".card").filter(has_text="特價").first.click() ``` ### 網路攔截 ```python # 攔截請求 def handle_route(route): if "analytics" in route.request.url: route.abort() else: route.continue_() page.route("**/*", handle_route) # 攔截並修改回應 def mock_api(route): route.fulfill( status=200, content_type="application/json", body='{"data": "mocked"}' ) page.route("**/api/data", mock_api) ``` ### Browser Context(隔離環境) ```python # 每個 context 有獨立的 cookies、localStorage context = browser.new_context( viewport={"width": 1280, "height": 720}, locale="zh-TW", timezone_id="Asia/Taipei", user_agent="custom-agent", ) page = context.new_page() # 帶裝置模擬 from playwright.sync_api import sync_playwright with sync_playwright() as p: iphone = p.devices["iPhone 14"] context = browser.new_context(**iphone) ``` ### 等待與自動等待 ```python # Playwright 預設自動等待元素可操作後才執行動作 # 以下是額外的等待方法: page.wait_for_load_state("networkidle") # 等網路閒置 page.wait_for_url("**/dashboard") # 等 URL 變化 page.wait_for_selector(".loaded") # 等元素出現 # 等待 response with page.expect_response("**/api/data") as response_info: page.click("#load-btn") response = response_info.value ``` ## CLI 工具 ### Codegen(自動產生程式碼) ```bash # 打開瀏覽器錄製操作,自動產生 Python 程式碼 playwright codegen https://example.com # 指定裝置模擬 playwright codegen --device="iPhone 14" https://example.com # 指定語言 playwright codegen --target python-async https://example.com ``` ### Trace Viewer(除錯追蹤) ```python # 錄製 trace context.tracing.start(screenshots=True, snapshots=True, sources=True) # ... 執行操作 ... context.tracing.stop(path="trace.zip") ``` ```bash # 檢視 trace playwright show-trace trace.zip ``` ### 其他 CLI ```bash playwright open https://example.com # 開啟瀏覽器 playwright screenshot --help # 截圖工具 playwright install --with-deps # 安裝瀏覽器 + 系統相依 ``` ## Pytest 整合 ```bash pip install pytest-playwright ``` ```python # test_example.py def test_homepage(page): page.goto("https://example.com") assert page.title() == "Example Domain" def test_login(page): page.goto("https://example.com/login") page.fill("#username", "admin") page.fill("#password", "password") page.click("text=Login") assert page.url == "https://example.com/dashboard" ``` ```bash # 執行測試 pytest pytest --headed # 顯示瀏覽器 pytest --browser firefox # 指定瀏覽器 pytest --browser chromium --browser firefox # 多瀏覽器 ```