跳到主要內容

網路

簡介

Playwright 提供 API 來監控修改瀏覽器網路流量,包括 HTTP 和 HTTPS。頁面執行的任何請求,包括 XHRfetch 請求,都可以被追蹤、修改和處理。

模擬 API

查看我們的 API 模擬指南,以深入了解如何

  • 模擬 API 請求,且永遠不會連線到 API
  • 執行 API 請求並修改回應
  • 使用 HAR 檔案來模擬網路請求。

HTTP 驗證

執行 HTTP 驗證。

context = browser.new_context(
http_credentials={"username": "bill", "password": "pa55w0rd"}
)
page = context.new_page()
page.goto("https://example.com")

HTTP Proxy

您可以設定頁面透過 HTTP(S) Proxy 或 SOCKSv5 載入。Proxy 可以針對整個瀏覽器全域設定,或針對每個瀏覽器內容個別設定。

您可以選擇性地指定 HTTP(S) Proxy 的使用者名稱和密碼,也可以指定要繞過 Proxy 的主機。

以下是全域 Proxy 的範例

browser = chromium.launch(proxy={
"server": "http://myproxy.com:3128",
"username": "usr",
"password": "pwd"
})

也可以針對每個內容指定

browser = chromium.launch()
context = browser.new_context(proxy={"server": "http://myproxy.com:3128"})

網路事件

您可以監控所有 請求回應

from playwright.sync_api import sync_playwright, Playwright

def run(playwright: Playwright):
chromium = playwright.chromium
browser = chromium.launch()
page = browser.new_page()
# Subscribe to "request" and "response" events.
page.on("request", lambda request: print(">>", request.method, request.url))
page.on("response", lambda response: print("<<", response.status, response.url))
page.goto("https://example.com")
browser.close()

with sync_playwright() as playwright:
run(playwright)

或在使用 page.expect_response() 按鈕點擊後等待網路回應

# Use a glob url pattern
with page.expect_response("**/api/fetch_data") as response_info:
page.get_by_text("Update").click()
response = response_info.value

變化

使用 page.expect_response() 等待回應

# Use a regular expression
with page.expect_response(re.compile(r"\.jpeg$")) as response_info:
page.get_by_text("Update").click()
response = response_info.value

# Use a predicate taking a response object
with page.expect_response(lambda response: token in response.url) as response_info:
page.get_by_text("Update").click()
response = response_info.value

處理請求

page.route(
"**/api/fetch_data",
lambda route: route.fulfill(status=200, body=test_data))
page.goto("https://example.com")

您可以透過在 Playwright 指令碼中處理網路請求來模擬 API 端點。

變化

使用 browser_context.route() 在整個瀏覽器內容中或使用 page.route() 在頁面上設定路由。它將適用於彈出式視窗和開啟的連結。

context.route(
"**/api/login",
lambda route: route.fulfill(status=200, body="accept"))
page.goto("https://example.com")

修改請求

# Delete header
def handle_route(route):
headers = route.request.headers
del headers["x-secret"]
route.continue_(headers=headers)
page.route("**/*", handle_route)

# Continue requests as POST.
page.route("**/*", lambda route: route.continue_(method="POST"))

您可以繼續進行修改的請求。上面的範例從傳出的請求中移除 HTTP 標頭。

中止請求

您可以使用 page.route()route.abort() 中止請求。

page.route("**/*.{png,jpg,jpeg}", lambda route: route.abort())

# Abort based on the request type
page.route("**/*", lambda route: route.abort() if route.request.resource_type == "image" else route.continue_())

修改回應

若要修改回應,請使用 APIRequestContext 取得原始回應,然後將回應傳遞至 route.fulfill()。您可以透過選項覆寫回應上的個別欄位

def handle_route(route: Route) -> None:
# Fetch original response.
response = route.fetch()
# Add a prefix to the title.
body = response.text()
body = body.replace("<title>", "<title>My prefix:")
route.fulfill(
# Pass all fields from the response.
response=response,
# Override response body.
body=body,
# Force content type to be html.
headers={**response.headers, "content-type": "text/html"},
)

page.route("**/title.html", handle_route)

Glob URL 模式

Playwright 在網路攔截方法 (例如 page.route()page.expect_response()) 中使用簡化的 glob 模式進行 URL 比對。這些模式支援基本萬用字元

  1. 星號
    • 單個 * 符合任何字元,除了 /
    • ** 符合任何字元,包括 /
  2. 問號 ? 符合任何單個字元,除了 /
  3. 大括號 {} 可用於比對以逗號 , 分隔的選項清單
  4. 方括號 [] 可用於比對一組字元
  5. 反斜線 \ 可用於跳脫任何特殊字元 (請注意將反斜線本身跳脫為 \\)

範例

  • https://example.com/*.js 符合 https://example.com/file.js,但不符合 https://example.com/path/file.js
  • https://example.com/\\?page=1 符合 https://example.com/?page=1,但不符合 https://example.com
  • **/v[0-9]* 符合 https://example.com/v1/,但不符合 https://example.com/vote/
  • **/*.js 符合 https://example.com/file.jshttps://example.com/path/file.js
  • **/*.{png,jpg,jpeg} 符合所有影像請求

重要注意事項

  • glob 模式必須符合整個 URL,而不僅僅是部分 URL。
  • 使用 glob 進行 URL 比對時,請考量完整的 URL 結構,包括協定和路徑分隔符號。
  • 對於更複雜的比對需求,請考慮使用 [RegExp] 而不是 glob 模式。

WebSockets

Playwright 支援開箱即用的 WebSockets 檢查、模擬和修改。請參閱我們的 API 模擬指南,以了解如何模擬 WebSockets。

每次建立 WebSocket 時,都會觸發 page.on("websocket") 事件。此事件包含 WebSocket 執行個體,以供進一步的 Web Socket 框架檢查

def on_web_socket(ws):
print(f"WebSocket opened: {ws.url}")
ws.on("framesent", lambda payload: print(payload))
ws.on("framereceived", lambda payload: print(payload))
ws.on("close", lambda payload: print("WebSocket closed"))

page.on("websocket", on_web_socket)

遺失的網路事件和 Service Workers

Playwright 的內建 browser_context.route()page.route() 允許您的測試原生路由請求並執行模擬和攔截。

  1. 如果您正在使用 Playwright 的原生 browser_context.route()page.route(),而且似乎遺失了網路事件,請將 service_workers 設定為 'block' 來停用 Service Workers。
  2. 可能是您正在使用模擬工具,例如 Mock Service Worker (MSW)。雖然此工具可開箱即用來模擬回應,但它會新增自己的 Service Worker 來接管網路請求,因此使其對 browser_context.route()page.route() 不可見。如果您對網路測試和模擬都感興趣,請考慮使用內建的 browser_context.route()page.route() 進行回應模擬
  3. 如果您不僅僅對使用 Service Workers 進行測試和網路模擬感興趣,而且對路由和監聽 Service Workers 本身提出的請求感興趣,請參閱 此實驗性功能