表单提交后,Puppeteer等待页面加载

red*_*hka 50 javascript puppeteer

我使用以下代码提交表单,我希望Puppeteer在表单提交后等待页面加载.

await page.click("button[type=submit]");

//how to wait until the new page loads before taking screenshot?
// i don't want this:
// await page.waitFor(1*1000);  //? unwanted workaround
await page.screenshot({path: 'example.png'});
Run Code Online (Sandbox Code Playgroud)

如何与木偶戏等待页面加载?

Md.*_*her 47

您可以异步等待导航以避免null进行重定向,

await Promise.all([
      page.click("button[type=submit]"),
      page.waitForNavigation({ waitUntil: 'networkidle0' }),
]);
Run Code Online (Sandbox Code Playgroud)

如果page.click已触发导航,这将对您有所帮助.

  • 这是一个竞争条件。https://github.com/puppeteer/puppeteer/issues/1412#issuecomment-345294748 应该使用这个:`let nav = page.waitForNavigation(); 等待 page.click("按钮[type=提交]"); 等待导航;` https://github.com/puppeteer/puppeteer/issues/1412#issuecomment-345294748 (4认同)
  • `networkidle`现在应该设置为`networkidle2`https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagewaitfornavigationoptions (3认同)

red*_*hka 35

await page.waitForNavigation();
Run Code Online (Sandbox Code Playgroud)

  • 这和 `await Promise.all([page.click..., page.waitForNavigation...]);` 有什么区别? (7认同)

Gra*_*ler 20

根据官方文档,您应该使用:

page.waitForNavigation(选项)

  • options< Object >可能具有以下属性的导航参数:
    • timeout< number >最大导航时间(以毫秒为单位),默认为30秒,传递0给禁用超时.可以使用page.setDefaultNavigationTimeout(timeout)方法更改默认值.
    • waitUntil< string | 数组 < string >>何时考虑导航成功,默认为load.给定一系列事件字符串,在触发所有事件后,导航被认为是成功的.活动可以是:
      • load- 考虑在load事件被触发时完成导航.
      • domcontentloaded- 考虑在DOMContentLoaded事件被触发时完成导航.
      • networkidle0- 当网络连接数不超过0且至少为500ms 时,请考虑完成导航.
      • networkidle2- 当网络连接数不超过2 500ms 时,请考虑完成导航.
  • 返回:< Promise <[?Response] >> Promise,它解析为主要资源响应.如果有多个重定向,导航将使用上次重定向的响应进行解析.如果由于使用History API而导航到其他锚点或导航,导航将解决null.

可读性:

您可以使用page.waitForNavigation()等待页面导航:

await page.waitForNavigation();
Run Code Online (Sandbox Code Playgroud)

性能:

但由于page.waitForNavigation()是快捷方式page.mainFrame().waitForNavigation(),我们可以使用以下内容进行小的性能提升:

await page._frameManager._mainFrame.waitForNavigation();
Run Code Online (Sandbox Code Playgroud)

  • 性能提示是一个过早的优化,对现实世界的性能没有任何实际意义。另外,升级 puppeteer 后它更有可能崩溃,因为它使用内部 API (17认同)

Nat*_*ngs 17

有时即使使用await page.waitForNavigation()仍会导致Error: Execution context was destroyed, most likely because of a navigation.

就我而言,这是因为页面多次重定向。该API表示默认waitUntil选项Load-这种要求我等待导航每个重定向(3次)。

在我的情况下,仅使用page.waitForNavigation带有waitUntil选项的单个实例networkidle2效果很好:

await button.click();

await page.waitForNavigation({waitUntil: 'networkidle2'});
Run Code Online (Sandbox Code Playgroud)

最后,API 建议使用 aPromise.All来防止竞争条件。 我不需要这个,但提供它是为了完整性

await Promise.all([button.click(), page.waitForNavigation({waitUntil:'networkidle2'})])
Run Code Online (Sandbox Code Playgroud)

如果所有其他方法都失败了,您可以page.waitForSelector按照Puppeteer github 问题上的建议使用——或者在我的情况下,page.waitForXPath()

  • 我的重定向持续了很长时间,以至于只有“networkidle0”可以正常工作。 (4认同)
  • 一年多后,我回来说,“networkidle0”可能会神秘地失败(心跳、webpack hmr 等)。在我当前的脚本中,我正在使用“page.waitForSelector” (3认同)

Yur*_*ive 7

上述答案都没有解决我的问题。有时 waitForNavigation 只是超时。我想出了使用 waitForFunction 的其他解决方案,检查文档是否处于就绪状态。

await page.waitForFunction(() => document.readyState === "complete");
Run Code Online (Sandbox Code Playgroud)


Den*_*ish 5

await Promise.all([
      page.click(selectors.submit),
      page.waitForNavigation({ waitUntil: 'networkidle0' }),
]);
Run Code Online (Sandbox Code Playgroud)

这将是要使用的第一优先级,因为它会等待所有网络完成,并假设在 500 毫秒内没有超过 0 个网络调用时完成。

你也可以使用

await page.waitForNavigation({ waitUntil: 'load' })
Run Code Online (Sandbox Code Playgroud)

否则,你可以使用

await page.waitForResponse(response => response.ok())
Run Code Online (Sandbox Code Playgroud)

该函数也可以用在各种地方,因为它只允许在所有调用都成功时(即所有响应状态都正常时,即(200-299))继续进行

  • `等待直到:'加载'`。仅小写字母有效。参考:https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#pagewaitfornavigationoptions (2认同)

Aus*_*tin 5

我知道回答这个问题有点晚了。这对于在执行waitForNavigation时遇到异常的人可能会有所帮助。

(节点:14531)UnhandledPromiseRejectionWarning:超时错误:导航超时超过:Promise处超过30000ms。然后(/home/user/nodejs/node_modules/puppeteer/lib/LifecycleWatcher.js:142:21)在-ASYNC-在框架处。(/home/user/nodejs/node_modules/puppeteer/lib/helper.js:111:15)位于Page.waitForNavigation(/home/user/nodejs/node_modules/puppeteer/lib/Page.js:649:49) 。(/home/user/nodejs/node_modules/puppeteer/lib/helper.js:112:23)位于/home/user/nodejs/user/puppeteer/example7.js:14:12

适用于我的正确代码如下。

await page.click('button[id=start]', {waitUntil: 'domcontentloaded'});
Run Code Online (Sandbox Code Playgroud)

同样,如果您要转到新页面,则代码应类似于

await page.goto('here goes url', {waitUntil: 'domcontentloaded'});
Run Code Online (Sandbox Code Playgroud)


And*_*llo 5

我建议将 page.to 包装在一个包装器中并等待加载所有内容

这是我的包装纸

loadUrl: async function (page, url) {
    try {
        await page.goto(url, {
            timeout: 20000,
            waitUntil: ['load', 'domcontentloaded', 'networkidle0', 'networkidle2']
        })
    } catch (error) {
        throw new Error("url " + url + " url not loaded -> " + error)
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你可以使用它

await loadUrl(page, "https://www.google.com")
Run Code Online (Sandbox Code Playgroud)