包含 MemPalace、MarkItDown、Playwright 的安裝與使用筆記。 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
251 lines
5.4 KiB
Markdown
251 lines
5.4 KiB
Markdown
# 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 # 多瀏覽器
|
||
```
|