如何在 puppeteer 中滚动浏览多个 iframe

how to scroll through multiple iframes in puppeteer

我正在尝试使用 puppeteer 生成包含多个 iframe 的 pdf。我遇到的一个问题是,如果我嵌入类似 google 地图的东西,google 地图将延迟加载(它仅在元素位于浏览器的视角时加载。 一种解决方案是在页面上滚动浏览不同的 iframe,并为每个 iframe 设置加载等待时间。

这是我目前所拥有的(能够在 https://try-puppeteer.appspot.com/ 中测试)木偶操纵者:版本 1.9.0,我也在 1.12.0 中尝试过,无法使滚动工作或超时。

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setViewport({
  width: 1280,
  height: 750
});
await page.emulateMedia('screen');
const html = '<iframe src="https://www.google.com/maps/embed?pb=!1m14!1m8!1m3!1d12077.188806999058!2d-73.2243774!3d40.8214352!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x9e562057f79c0860!2sH+Lee+Dennison+Building!5e0!3m2!1sen!2sus!4v1547750310674" height="250" width="600" allowfullscreen=""></iframe><div><iframe src="https://www.google.com/maps/embed?pb=!1m14!1m8!1m3!1d12077.188806999058!2d-73.2243774!3d40.8214352!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x9e562057f79c0860!2sH+Lee+Dennison+Building!5e0!3m2!1sen!2sus!4v1547750310674" height="250" width="600" allowfullscreen=""></iframe></div><div><iframe src="https://www.google.com/maps/embed?pb=!1m14!1m8!1m3!1d12077.188806999058!2d-73.2243774!3d40.8214352!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x9e562057f79c0860!2sH+Lee+Dennison+Building!5e0!3m2!1sen!2sus!4v1547750310674" height="250" width="600" allowfullscreen=""></iframe></div><div><iframe src="https://www.google.com/maps/embed?pb=!1m14!1m8!1m3!1d12077.188806999058!2d-73.2243774!3d40.8214352!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x9e562057f79c0860!2sH+Lee+Dennison+Building!5e0!3m2!1sen!2sus!4v1547750310674" height="250" width="600" allowfullscreen=""></iframe></div>'

await page.setContent(html, { waitUntil: 'networkidle0' });
const frames = await page.mainFrame().childFrames(); // get all the iframes on that page. 
await page.evaluate((frames) => {
     // this part does not work
     for (let i=0, i<frames.length; i++){
        setTimeout(() => {
         document.querySelectorAll('iframe')[i].scrollIntoView();
        }, 2000)
     }
  }, frames)
const pdf = await page.pdf({
  scale: 1,
  printBackground: true,
  margin: { bottom: 0 },
  path: 'screenshot.pdf'
});

await browser.close();

感谢任何帮助!

这段代码有一些问题:

  1. frames 是来自 Node.js 上下文的不可序列化对象,因此它不能按原样在浏览器上下文中传输。
  2. 所有 setTimeout() 回调将在 2 秒后立即调用,因此每一帧都没有足够的时间加载。
  3. 不等待这些 setTimeout() 回调:page.evaluate() returns 在 iframe 加载之前的 2 秒传递和 pdf 创建之前。

你可以试试这个方法:

// page loaded

await page.evaluate(async () => {
  for (const iframe of Array.from(document.querySelectorAll('iframe'))) {
    iframe.scrollIntoView();
    await new Promise((resolve) => { setTimeout(resolve, 2000); });
  }
});

// pdf creation