簡體   English   中英

表單提交后 Puppeteer 等待頁面加載

[英]Puppeteer wait page load after form submit

我使用以下代碼提交表單,我希望 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'});

如何使用 puppeteer 等待頁面加載?

您可以異步等待導航以避免在重定向時獲得null

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

如果 page.click 已觸發導航,這將對您有所幫助。

await page.waitForNavigation();

根據官方文檔,您應該使用:

page.waitForNavigation(選項)

  • options < Object > 導航參數可能具有以下屬性:
    • timeout < number > 最大導航時間,以毫秒為單位,默認為 30 秒,傳遞0以禁用超時。 可以使用page.setDefaultNavigationTimeout(timeout)方法更改默認值。
    • waitUntil < 字符串| Array < string >> 何時認為導航成功,默認為load 給定一組事件字符串,在觸發所有事件后,導航被認為是成功的。 事件可以是:
      • load - 考慮在觸發load事件時完成導航。
      • domcontentloaded - 考慮在觸發DOMContentLoaded事件時完成導航。
      • networkidle0 - 當至少500毫秒沒有超過 0 個網絡連接時,認為導航已完成。
      • networkidle2 - 當至少500毫秒沒有超過 2 個網絡連接時,認為導航已完成。
  • 返回:< Promise <[?Response]>> Promise 解析為主要資源響應。 在多次重定向的情況下,導航將使用上次重定向的響應進行解析。 如果由於 History API 的使用而導航到不同的錨點或導航,導航將解析為null

可讀性:

您可以使用page.waitForNavigation()等待頁面導航:

await page.waitForNavigation();

性能:

但是由於page.waitForNavigation()page.mainFrame().waitForNavigation()的快捷方式,我們可以使用以下內容來提高性能:

await page._frameManager._mainFrame.waitForNavigation();

有時即使使用await page.waitForNavigation()仍然會導致Error: Execution context was destroyed, most likely because of a navigation.

就我而言,這是因為頁面多次重定向。 API表示默認waitUntil選項是Load -這需要我等待導航每個重定向(3次)。

只使用單個實例page.waitForNavigationwaitUntil選項networkidle2在我的情況下工作良好:

await button.click();

await page.waitForNavigation({waitUntil: 'networkidle2'});

最后,API 建議使用Promise.All來防止競爭條件。 我不需要這個,但提供它是為了完整性

await Promise.all([button.click(), page.waitForNavigation({waitUntil:'networkidle2'})])

如果所有其他方法都失敗了,您可以按照Puppeteer github 問題上的建議使用page.waitForSelector — 或者在我的情況下使用page.waitForXPath()

我知道現在回答這個有點晚了。 對於那些在執行waitForNavigation 時遇到異常情況的人可能會有所幫助。

(node:14531) UnhandledPromiseRejectionWarning: TimeoutError: Navigation Timeout Exceeded: Promise.then (/home/user/nodejs/node_modules/puppeteer/lib/LifecycleWatcher.js:142:21) at -- ASYNC -- at Frame 超過 30000ms。 (/home/user/nodejs/node_modules/puppeteer/lib/helper.js:111:15) 在 Page.waitForNavigation (/home/user/nodejs/node_modules/puppeteer/lib/Page.js:649:49) 在 Page . (/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'});

同樣,如果你要進入一個新頁面,代碼應該像

await page.goto('here goes url', {waitUntil: 'domcontentloaded'});

我建議將 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)
    }
}

現在你可以使用它

await loadUrl(page, "https://www.google.com")
await Promise.all([
      page.click(selectors.submit),
      page.waitForNavigation({ waitUntil: 'networkidle0' }),
]);

這將是使用的第一優先級,因為它等待所有網絡完成並假設它在 500 毫秒內沒有超過 0 個網絡調用時完成。

你也可以使用

await page.waitForNavigation({ waitUntil: 'Load' })

否則,你可以使用

await page.waitForResponse(response => response.ok())

這個函數也可以用在不同的地方,因為它只允許在所有調用都成功時,即所有響應狀態都正常時,即 (200-299) 繼續進行

這對我有用:

await Promise.all([
    page.goto(URL),
    page.waitForNavigation({ waitUntil: 'networkidle0' }),
]);
console.log('page loaded')

出於某種原因,我無法點擊按鈕(處理了一個事件,而不是在表單中)

<button onclick="someFunction();" class="button button2">Submit</button>

問題是頁面是在服務器端呈現的。 因此,每當我等待輸入字段時,按鈕都不存在await page.waitForSelector('button.button2')

解決方案是在Promise綁定page.goto(URL)page.waitForNavigation({ waitUntil: 'networkidle0' })

await Promise.all([
    page.goto(URL),
    page.waitForNavigation({ waitUntil: 'networkidle0' }),
]);
console.log('page loaded')

await page.waitForSelector('button.button2')
console.log('button is here');

我遇到了一個場景,其中有經典的 POST-303-GET 並且涉及input[type=submit] 在這種情況下,按鈕的click似乎在關聯表單提交和重定向之后才會解析,因此解決方案是刪除waitForNavigation ,因為它是在重定向之后執行的,因此超時。

如果提交表單會打開其他頁面,那么您可能只想等待該頁面中的選擇器。 我經常在使用page.waitForNavigation()遇到問題,因為它的選項並不能真正確保我們有效地導航到另一個頁面。

// login page
page.click("#login");
// homepage, after login
page.waitForSelector("#home", {visible: true}); // page.waitForXpath()

當然,您可以增加選擇器的等待時間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM