导航
Playwright 可以导航到 URL 并处理由页面交互引起的导航。本指南涵盖了等待页面导航和加载完成的常见场景。
Navigation lifecycle
Playwright 将在页面中显示新文档的过程分为 导航 和 加载。
导航开始 通过更改页面 URL 或与页面交互(例如,点击链接)。导航意图可能会被取消,例如,在点击未解析的 DNS 地址时,或者转换为文件下载。
导航已提交 当响应头已被解析并且会话历史记录已更新时。只有在导航成功(已提交)后,页面才开始 加载 文档。
加载 涵盖通过网络获取剩余响应体、解析、执行脚本和触发加载事件:
- page.url 设置为新 url
- 文档内容通过网络加载并解析
- page.on("domcontentloaded") 事件被触发
- 页面执行一些脚本并加载资源,如样式表和图像
- page.on("load") 事件被触发
- 页面执行动态加载的脚本
- 当 500 毫秒内没有新的网络请求时,触发
networkidle
Scenarios initiated by browser UI
可以通过更改 URL 栏、重新加载页面或在会话历史记录中后退或前进引发导航。
Auto-wait
导航到 URL 会自动等待页面触发 load 事件。如果页面在 load 之前执行客户端重定向,page.goto(url, **kwargs) 将自动等待重定向的页面触发 load 事件。
- Sync
- Async
# Navigate the page
page.goto("https://example.com")
# Navigate the page
await page.goto("https://example.com")
Custom wait
覆盖默认行为以等待特定事件,例如 networkidle。
- Sync
- Async
# Navigate and wait until network is idle
page.goto("https://example.com", wait_until="networkidle")
# Navigate and wait until network is idle
await page.goto("https://example.com", wait_until="networkidle")
Wait for element
在延迟加载的页面中,使用 locator.wait_for(**kwargs) 等待元素可见可能很有用。或者,像 page.click(selector, **kwargs) 这样的页面交互会自动等待元素。
- Sync
- Async
# Navigate and wait for element
page.goto("https://example.com")
page.get_by_text("example domain").wait_for()
# Navigate and click element
# Click will auto-wait for the element
page.goto("https://example.com")
page.get_by_text("example domain").click()
# Navigate and wait for element
await page.goto("https://example.com")
await page.get_by_text("example domain").wait_for()
# Navigate and click element
# Click will auto-wait for the element
await page.goto("https://example.com")
await page.get_by_text("example domain").click()
Scenarios initiated by page interaction
在以下场景中,locator.click(**kwargs) 启动导航,然后等待导航完成。
Auto-wait
默认情况下,locator.click(**kwargs) 将等待导航步骤完成。这可以与导航页面上的页面交互结合使用,后者将自动等待元素。
- Sync
- Async
# Click will auto-wait for navigation to complete
page.get_by_text("Login").click()
# Fill will auto-wait for element on navigated page
page.get_by_label("User Name").fill("John Doe")
# Click will auto-wait for navigation to complete
await page.get_by_text("Login").click()
# Fill will auto-wait for element on navigated page
await page.get_by_label("User Name").fill("John Doe")
Custom wait
locator.click 可以与 page.wait_for_load_state(**kwargs) 结合使用以等待加载事件。
- Sync
- Async
page.locator("button").click(); # Click triggers navigation
page.wait_for_load_state("networkidle"); # This waits for the "networkidle"
await page.locator("button").click(); # Click triggers navigation
await page.wait_for_load_state("networkidle"); # This waits for the "networkidle"
Wait for element
在延迟加载的页面中,使用 locator.wait_for(**kwargs) 等待元素可见可能很有用。或者,像 locator.click(**kwargs) 这样的页面交互会自动等待元素。
- Sync
- Async
# Click triggers navigation
page.get_by_text("Login").click()
# Click will auto-wait for the element
page.get_by_label("User Name").wait_for()
# Click triggers navigation
page.get_by_text("Login").click()
# Fill will auto-wait for element
page.get_by_label("User Name").fill("John Doe")
# Click will auto-wait for the element and trigger navigation
await page.get_by_text("Login").click()
# Wait for the element
await page.get_by_label("User Name").wait_for()
# Click triggers navigation
await page.get_by_text("Login").click()
# Fill will auto-wait for element
await page.get_by_label("User Name").fill("John Doe")
Asynchronous navigation
点击元素可能会在启动导航之前触发异步处理。在这些情况下,建议显式调用 page.expect_navigation(**kwargs)。例如:
- 导航从
setTimeout触发 - 页面在导航前等待网络请求
- Sync
- Async
# Waits for the next navigation. Using Python context manager
# prevents a race condition between clicking and waiting for a navigation.
with page.expect_navigation():
# Triggers a navigation after a timeout
page.locator("a").click()
# Waits for the next navigation. Using Python context manager
# prevents a race condition between clicking and waiting for a navigation.
async with page.expect_navigation():
# Triggers a navigation after a timeout
await page.locator("div.delayed-navigation").click()
Multiple navigations
点击元素可能会触发多次导航。在这些情况下,建议显式 page.expect_navigation(**kwargs) 到特定 url。例如:
load事件后发出的客户端重定向- 多次推送到历史状态
- Sync
- Async
# Using Python context manager prevents a race condition
# between clicking and waiting for a navigation.
with page.expect_navigation(url="**/login"):
# Triggers a navigation with a script redirect
page.get_by_text("Click me").click()
# Using Python context manager prevents a race condition
# between clicking and waiting for a navigation.
async with page.expect_navigation(url="**/login"):
# Triggers a navigation with a script redirect
await page.get_by_text("Click me").click()
Loading a popup
打开弹出窗口时,显式调用 page.wait_for_load_state(**kwargs) 可确保弹出窗口加载到所需状态。
- Sync
- Async
with page.expect_popup() as popup_info:
page.locator('a[target="_blank"]').click() # Opens popup
popup = popup_info.value
popup.wait_for_load_state("load")
async with page.expect_popup() as popup_info:
await page.locator('a[target="_blank"]').click() # Opens popup
popup = await popup_info.value
await popup.wait_for_load_state("load")
Advanced patterns
对于具有复杂加载模式的页面,page.wait_for_function(expression, **kwargs) 是定义自定义等待条件的强大且可扩展的方法。
- Sync
- Async
page.goto("http://example.com")
page.wait_for_function("() => window.amILoadedYet()")
# Ready to take a screenshot, according to the page itself.
page.screenshot()
await page.goto("http://example.com")
await page.wait_for_function("() => window.amILoadedYet()")
# Ready to take a screenshot, according to the page itself.
await page.screenshot()