puppeteer使用问题总结

puppeteer的内部窗口和打开的外部窗口大小不一致

puppeteer使用问题总结_第1张图片
images

我们可以看到右侧和下边栏都有一个大的空白。
我们使用下面代码

const browser = await puppeteer.launch({
      headless: false
});
const page = await browser.newPage();
await page.goto('https://google.com');

关于这个原因是因为默认情况下开启了ViewPort的功能,这里可以通过defaultViewport:null选项来禁用

const browser = await puppeteer.launch({
      headless: false,
      defaultViewport: null
});

waitUntil

waitUntil代表什么时候才认为导航加载成功。

  • load: window.onload事件被触发时候完成导航,某些情况下它根本不会发生。
  • domcontentloaded: Domcontentloaded事件触发时候认为导航成功
  • networkidle0: 在 500ms 内没有网络连接时就算成功(全部的request结束),才认为导航结束
  • networkidle2: 500ms 内有不超过 2 个网络连接时就算成功(还有两个以下的request),就认为导航完成。

我们对比了下加载时长 networkidle0> networkidle2>load>domcontentloaded

使用networkidle0的时候,随时可能网络加载时间在2s以上。我们希望500ms的时长是可配置的,因为500ms太长了。

function waitForNetworkIdle(page, timeout, maxInflightRequests = 0) {
  page.on('request', onRequestStarted);
  page.on('requestfinished', onRequestFinished);
  page.on('requestfailed', onRequestFinished);

  let inflight = 0;
  let fulfill;
  let promise = new Promise(x => fulfill = x);
  let timeoutId = setTimeout(onTimeoutDone, timeout);
  return promise;

  function onTimeoutDone() {
    page.removeListener('request', onRequestStarted);
    page.removeListener('requestfinished', onRequestFinished);
    page.removeListener('requestfailed', onRequestFinished);
    fulfill();
  }

  function onRequestStarted() {
    ++inflight;
    if (inflight > maxInflightRequests)
      clearTimeout(timeoutId);
  }

  function onRequestFinished() {
    if (inflight === 0)
      return;
    --inflight;
    if (inflight === maxInflightRequests)
      timeoutId = setTimeout(onTimeoutDone, timeout);
  }
}

// Example
await Promise.all([
  page.goto('https://google.com'),
  waitForNetworkIdle(page, 500, 0), // 和 'networkidle0'效果相同
]);

evaluate, evaluateHandle, exposeFunction

evaluate

page.evaluate(pageFunction, …args) 返回的是一个可序列化的对象。

const result = await  page.evaluate((x) => {
  return x;
}, 'abc')

上面这段代码可以返回abc字段

const result = await page.evaluate(
      x => {
        return x;
      },
      () => 'abc'
);
console.log(result); // 返回undefined

exposeFunction

这个 API 用来在页面注册全局函数,因为有时候需要在页面处理一些操作的时候需要用到一些函数,虽然可以通过 page.evaluate() API 在页面定义函数。

await page.exposeFunction('md5', text => '__' + text);
const result = await page.evaluate(() => {
    return window.md5('abc');
});
console.log(result); // 返回 __abc

但是这里也需要注意一点,exposeFunction 也不能传递,也是需要序列化的对象

evaluateHandle

Page.evaluateHandle(pageFunction, …args) 在 Page 上下文执行一个 pageFunction, 返回 JSHandle 实体

evaluateHandle可以传递一个字符串或者函数,返回promise对象。

const func = () => 'abc';
const handle = await page.evaluateHandle(`(${func.toString()})`);
const abc = await page.evaluate(a => {
      return a();
}, handle);

你可能感兴趣的:(puppeteer使用问题总结)