Puppeteer中的wait

错误起因:

错误一:

"Execution context was destroyed, most likely because of a navigation"错误通常发生在使用 Puppeteer 或类似工具时,尝试在页面导航后继续操作页面元素或执行其他操作时。这个错误的主要原因是页面导航导致当前页面的执行环境被销毁,而后续的操作仍然在尝试使用已经销毁的页面上下文,从而导致错误。

错误二:

”TimeoutError: Navigation timeout of 120000 ms exceeded“这个错误通常是由页面导航超时引起的。它意味着 Puppeteer 在规定的时间内无法完成页面加载。在你的情况下,超时时间设置为 120000 毫秒(即 2 分钟),但页面加载时间超过了这个阈值。

处理方法

Puppeteer 提供了多种超时相关的操作,用于控制在执行自动化测试或网页操作时的超时行为。以下是 Puppeteer 中常用的超时相关操作:

  1. page.setDefaultTimeout(timeout)

    • 设置页面操作的默认超时时间,单位为毫秒。如果操作未在超时时间内完成,将会抛出错误。默认超时时间为 30 秒。
  2. page.setDefaultNavigationTimeout(timeout)

    • 设置页面导航的默认超时时间,单位为毫秒。如果页面导航未在超时时间内完成,将会抛出错误。默认超时时间为 30 秒。
  3. page.waitForTimeout(timeout)

    • 在页面上等待指定的时间,单位为毫秒。这不是一个超时操作,而是一个简单的等待操作。
  4. page.waitForNavigation(options)

    • 等待页面导航完成,可以设置超时时间和其他选项。如果页面导航未在超时时间内完成,将会抛出错误。
  5. page.waitForSelector(selector[, options])

    • 等待指定的 CSS 选择器匹配到一个元素,可以设置超时时间和其他选项。如果选择器未在超时时间内匹配到元素,将会抛出错误。
  6. page.waitForXPath(xpath[, options])

    • 等待匹配指定 XPath 表达式的元素出现,可以设置超时时间和其他选项。如果 XPath 表达式未在超时时间内匹配到元素,将会抛出错误。
  7. page.waitForFunction(pageFunction, options[, ...args])

    • 等待页面上的 JavaScript 函数返回 true,可以设置超时时间和其他选项。如果函数未在超时时间内返回 true,将会抛出错误。
  8. page.waitForRequest(urlOrPredicate[, options])page.waitForResponse(urlOrPredicate[, options])

    • 等待特定的网络请求或响应,可以设置超时时间和其他选项。如果请求或响应未在超时时间内完成,将会抛出错误。

实例列表

函数:waitForNavigation(options)

解释:
等待框架完成导航。当你运行的代码间接导致框架导航时,这个函数非常有用。使用 History API 改变 URL 被视为一次导航。

示例:

const [response] = await Promise.all([
  // 导航完成后,这个 promise 解析
  frame.waitForNavigation(),
  // 点击链接间接导致了一次导航
  frame.click('a.my-link'),
]);

在这个示例中,使用了 waitForNavigation 函数等待框架导航完成。Promise.all 包裹了两个异步操作,其中之一是点击链接,以确保等待正确地同步。

函数:waitForSelector(selector, options)

解释:
等待当前页面中匹配指定选择器的元素出现。与 Frame.waitForSelector 不同,此方法不会跨页面导航,也不会在元素从 DOM 中移除后继续等待。

示例:

import puppeteer from 'puppeteer';

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  let currentURL;
  page
    .mainFrame()
    .waitForSelector('img')
    .then(() => console.log('第一个带有图片的 URL: ' + currentURL));

  for (currentURL of [
    'https://example.com',
    'https://google.com',
    'https://bbc.com',
  ]) {
    await page.goto(currentURL);
  }
  await browser.close();
})();

函数:waitForXPath(xpath, options)

解释:
等待当前页面中匹配给定 XPath 表达式的元素出现。此方法可以跨页面导航,并且如果在调用该方法时 XPath 已经存在,则立即返回。

示例:

import puppeteer from 'puppeteer';

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  let currentURL;
  page
    .waitForXPath('//img')
    .then(() => console.log('第一个带有图片的 URL: ' + currentURL));
  for (currentURL of [
    'https://example.com',
    'https://google.com',
    'https://bbc.com',
  ]) {
    await page.goto(currentURL);
  }
  await browser.close();
})();

这两个示例展示了如何使用 waitForSelector 和 waitForXPath 等待页面上特定元素的出现。在每次页面加载完成后,代码都会等待页面上的图片元素出现,然后输出第一个带有图片的 URL。

函数:waitForFunction(pageFunction, options)

解释:
等待页面上下文中的函数执行完成。

示例:

import puppeteer from 'puppeteer';

// 观察视口大小变化
(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  const watchDog = page.waitForFunction('window.innerWidth < 100');
  await page.setViewport({width: 50, height: 50});
  await watchDog;
  await browser.close();
})();

// 从 Node.js 传递参数到 waitForFunction 函数的断言
const selector = '.foo';
await page.waitForFunction(
  selector => !!document.querySelector(selector),
  {},
  selector
);

// waitForFunction 的断言也可以是异步的
const username = 'github-username';
await page.waitForFunction(
  async username => {
    const githubResponse = await fetch(
      `https://api.github.com/users/${username}`
    );
    const githubUser = await githubResponse.json();
    // 展示头像
    const img = document.createElement('img');
    img.src = githubUser.avatar_url;
    // 等待 3 秒
    await new Promise((resolve, reject) => setTimeout(resolve, 3000));
    img.remove();
  },
  {},
  username
);

在这个示例中,waitForFunction 函数被用来等待页面上下文中的函数执行完成。第一个示例观察了视口大小的变化,第二个示例传递了参数给断言函数,第三个示例展示了断言函数可以是异步的情况。

函数:waitForRequest(urlOrPredicate, options)

解释:
等待匹配给定 URL 或断言的请求。

示例:

const firstRequest = await page.waitForRequest(
  'https://example.com/resource'
);
const finalRequest = await page.waitForRequest(
  request => request.url() === 'https://example.com'
);
return finalRequest.response()?.ok();

在这个示例中,waitForRequest 函数用于等待与给定 URL 匹配的请求。第一个示例等待第一个请求完成,第二个示例使用断言等待特定的请求。

函数:waitForResponse(urlOrPredicate, options)

解释:
等待匹配给定 URL 或断言的响应。

示例:

const firstResponse = await page.waitForResponse(
  'https://example.com/resource'
);
const finalResponse = await page.waitForResponse(
  response =>
    response.url() === 'https://example.com' && response.status() === 200
);
const finalResponse = await page.waitForResponse(async response => {
  return (await response.text()).includes('<html>');
});
return finalResponse.ok();

在这个示例中,waitForResponse 函数用于等待与给定 URL 匹配的响应。第一个示例等待第一个响应完成,第二个示例使用断言等待特定的响应,第三个示例使用异步断言等待满足条件的响应。

函数:waitForFrame(urlOrPredicate, options)

解释:
等待满足给定条件的框架出现。

示例:

const frame = await page.waitForFrame(async frame => {
  return frame.name() === 'Test';
});

在这个示例中,waitForFrame 函数用于等待满足条件的框架出现。它可以接受一个异步断言函数作为参数,用于判断框架是否满足条件。

函数:waitForNetworkIdle(options)

解释:
等待网络空闲状态。

示例:

await page.waitForNetworkIdle();

在这个示例中,waitForNetworkIdle 函数用于等待网络处于空闲状态。

函数:waitForDevicePrompt(options)

解释:
此方法通常与触发来自 WebBluetooth 等 API 的设备请求的操作耦合。

示例:

const [devicePrompt] = Promise.all([
  page.waitForDevicePrompt(),
  page.click('#connect-bluetooth'),
]);
await devicePrompt.select(
  await devicePrompt.waitForDevice(({name}) => name.includes('My Device'))
);

这个示例中,waitForDevicePrompt 函数用于等待设备提示。在点击连接蓝牙按钮后,它选择了一个设备,并等待设备的出现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值