前言

Playwright 可以导航到 URL 并处理由页面交互引起的导航。本篇涵盖了等待页面导航和加载完成的常见场景。

导航生命周期

导航从更改页面 URL 或通过与页面交互(例如,单击链接)开始。导航意图可能会被取消,例如,在点击未解析的 DNS 地址或转换为文件下载时。
解析响应标头并更新会话历史记录后,将提交导航。只有在导航成功(提交)后,页面才会开始加载文档。
加载包括通过网络获取剩余的响应主体、解析、执行脚本和触发加载事件:

调用 page.goto(url) 后页面加载过程:

  • page.url 设定新的 url
  • document 文档内容通过网络加载并解析
  • page.on("domcontentloaded") 事件触发
  • 执行页面的 js 脚本,页面执行一些脚本并加载 css 和图像等资源
  • page.on("load") 事件触发
  • 页面执行动态加载的脚本
  • networkidle 当 500 毫秒内没有新的网络请求时触发

事件状态

导航到 URL 会自动等待页面触发事件load。如果页面之前进行了客户端重定向load,page.goto()将自动等待重定向页面触发事件load。

从源码可以看到 wait_until 等待的事件可以支持["commit", "domcontentloaded", "load", "networkidle"] 四个参数,默认是等待load 触发。

wait_until:Union[“commit”,“domcontentloaded”,“load”,“networkidle”,无]当认为操作成功时,默认为“加载”。事件可以是:

  • domcontentloaded: 在触发“domcontentloaded”事件时完成操作。
  • load: 触发 load事件时完成操作。
  • networkidle: 当 500 毫秒内没有新的网络请求时触发,认为操作已完成。
  • commit:考虑在接收到网络响应并且文档开始加载时完成操作。
def goto(
    self,
    url: str,
    *,
    timeout: typing.Optional[float] = None,
    wait_until: typing.Optional[
        Literal["commit", "domcontentloaded", "load", "networkidle"]
    ] = None,
    referer: typing.Optional[str] = None
) -> typing.Optional["Response"]:

如果我们希望ajax 也请求完成了,再继续下一步,那么可以覆盖默认行为以等待特定事件,例如 networkidle.
(对于 clickfill 等操作会自动等待元素出现。)

# Navigate and wait until network is idle
page.goto("https://example.com", wait_until="networkidle")

等待元素

在延迟加载的页面中,使用locator.wait_for()等待元素可见是很有用的。或者,像page.click()这样的页面交互会自动等待元素。

# 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()

页面交互

click/fill 会自动等待

在下面的场景中,locator.click()启动导航,然后等待导航完成。
默认情况下,locator.click()将等待导航步骤完成。这可以与导航页面上的页面交互相结合,该页面交互将自动等待元素。

# 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")

自定义等待

locator.click可以结合page.wait_for_load_state()来等待加载事件。

page.locator("button").click()  # Click triggers navigation
page.wait_for_load_state("networkidle")  # This waits for the "networkidle"

等待元素

在延迟加载的页面中,使用locator.wait_for()等待元素可见是很有用的。或者,像locator.click()这样的页面交互会自动等待元素。

# 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")

异步导航

单击一个元素可以在启动导航之前触发异步处理。在这些情况下,建议显式调用page.expect_navigation()。例如:

  • 导航是从setTimeout
  • 页面在导航前等待网络请求
# 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.get_by_text("Navigate after timeout").click()

多重导航

击一个元素可能会触发多个导航。在这些情况下,建议将 page.expect_navigation() 显式指向特定的 url。例如:

  • load事件后发出的客户端重定向
  • 多次推送到历史状态
# 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()

加载弹出窗口

打开弹出窗口时,显式调用page.wait_for_load_state()可确保将弹出窗口加载到所需状态。

with page.expect_popup() as popup_info:
    page.get_by_text("Open popup").click() # Opens popup
popup = popup_info.value
popup.wait_for_load_state("load")

高级模式

对于具有复杂加载模式的页面,page.wait_for_function()是定义自定义等待条件的强大且可扩展的方法。

page.goto("http://example.com")
page.wait_for_function("() => window.amILoadedYet()")
# Ready to take a screenshot, according to the page itself.
page.screenshot()

timeout 等待超时

timeout 参数可以设置页面加载超时时间, 默认是30秒, 传递“0”以禁用超时。

timeout : Union[float, None]
            Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value can
            be changed by using the `browser_context.set_default_navigation_timeout()`,
            `browser_context.set_default_timeout()`, `page.set_default_navigation_timeout()` or
            `page.set_default_timeout()` methods.

更改默认值可以使用 以下方法更改

  • browser_context.set_fault_navigation_timeout()进行更改,
  • browser_context.set_fault_timeout()
  • page.set_fault_navigation_timeout)
  • page.set_fault_timeout()

文章转自:https://www.cnblogs.com/yoyoketang/p/17159121.html