puppeteer使用问题总结

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

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进阶之12306买票 开始准备工作 安装 cnpm i puppeteer 因为要使用到asyn...
    Winterdog阅读 6,578评论 0 5
  • phantomjs实现了一个无界面的webkit浏览器。虽然没有界面,但dom渲染、js运行、网络访问、canva...
    卍卍_卐卐阅读 38,649评论 1 13
  •   JavaScript 与 HTML 之间的交互是通过事件实现的。   事件,就是文档或浏览器窗口中发生的一些特...
    霜天晓阅读 3,526评论 1 11
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,877评论 0 38
  • 1.puppeteer简介 puppeteer是一个node库,是Google chrome团队官方的无界面(he...
    伊人风采_690d阅读 7,687评论 0 11