Puppeteer:屏幕截图惰性图像不起作用[重复]

2024-03-07

我似乎无法捕获屏幕截图https://today.line.me/HK/pc https://today.line.me/HK/pc成功地。

在我的 Puppeteer 脚本中,我还启动了滚动到页面底部并再次向上滚动以确保加载图像。但由于某种原因,它似乎不适用于上面的 URL 行。

function wait (ms) {
 return new Promise(resolve => setTimeout(() => resolve(), ms));
}

const puppeteer = require('puppeteer');

async function run() {
let browser = await puppeteer.launch({headless: false});
let page = await browser.newPage();
await page.goto('https://today.line.me/HK/pc', {waitUntil: 'load'});
//https://today.line.me/HK/pc
// Get the height of the rendered page
  const bodyHandle = await page.$('body');
  const { height } = await bodyHandle.boundingBox();
  await bodyHandle.dispose();

  // Scroll one viewport at a time, pausing to let content load
  const viewportHeight = page.viewport().height+200;
  let viewportIncr = 0;
  while (viewportIncr + viewportHeight < height) {
    await page.evaluate(_viewportHeight => {
      window.scrollBy(0, _viewportHeight);
    }, viewportHeight);
    await wait(4000);
    viewportIncr = viewportIncr + viewportHeight;
  }

  // Scroll back to top
  await page.evaluate(_ => {
    window.scrollTo(0, 0);

  });

 // Some extra delay to let images load
 await wait(2000);

await page.setViewport({ width: 1366, height: 768});
await page.screenshot({ path: './image.png', fullPage: true });
}

run();

对于任何想知道的人来说,有很多策略可以在 Puppeteer 中渲染延迟加载的图像或资源,但并非所有策略都同样有效。您尝试截屏的网站中的小实现细节可能会改变最终结果,因此,如果您希望实现能够在多种案例场景中正常运行,您将需要隔离每个通用案例并单独解决。

我知道这一点是因为我经营一家小型公司截图API https://www.getscreenshotapi.com服务人员和我必须单独处理许多案件。这是该项目的一项艰巨任务,因为似乎总是有新的问题需要通过每天使用的新库和 UI 技术来解决。

话虽这么说,我认为有一些渲染策略具有良好的覆盖范围。也许最好的方法是像OP那样将等待和滚动页面结合起来,但也要确保考虑到操作的顺序。这是 OP 原始代码的稍微修改版本。

//Scroll and Wait Strategy

function waitFor (ms) {
  return new Promise(resolve => setTimeout(() => resolve(), ms));
}

async function capturePage(browser, url) {
  // Load the page that you're trying to screenshot.
  const page = await browser.newPage();
  await page.goto(url, {waitUntil: 'load'}); // Wait until networkidle2 could work better.


  // Set the viewport before scrolling
  await page.setViewport({ width: 1366, height: 768});

  // Get the height of the page after navigating to it.
  // This strategy to calculate height doesn't work always though. 
  const bodyHandle = await page.$('body');
  const { height } = await bodyHandle.boundingBox();
  await bodyHandle.dispose();

  // Scroll viewport by viewport, allow the content to load
  const calculatedVh = page.viewport().height;
  let vhIncrease = 0;
  while (vhIncrease + calculatedVh < height) {
    // Here we pass the calculated viewport height to the context
    // of the page and we scroll by that amount
    await page.evaluate(_calculatedVh => {
      window.scrollBy(0, _calculatedVh);
    }, calculatedVh);
    await waitFor(300);
    vhIncrease = vhIncrease + calculatedVh;
  }

  // Setting the viewport to the full height might reveal extra elements
  await page.setViewport({ width: 1366, height: calculatedVh});

  // Wait for a little bit more
  await waitFor(1000);

  // Scroll back to the top of the page by using evaluate again.
  await page.evaluate(_ => {
    window.scrollTo(0, 0);
  });

  return await page.screenshot({type: 'png'});
}

这里的一些主要区别是:

  • 您希望从一开始就设置视口并使用该固定视口进行操作。

  • 您可以更改等待时间并引入任意等待来进行实验。有时,这会导致网络事件背后的元素被揭露。

  • 将视口更改为页面的完整高度也可以显示元素,就像滚动一样。您可以使用垂直显示器在真实的浏览器中进行测试。但是,请确保返回到原始视口高度,因为视口也会影响预期的渲染。

这里需要理解的一件事是,单独等待并不一定会触发惰性资产的加载。滚动文档的高度允许视口显示那些需要在视口内加载的元素。

另一个需要注意的是,有时您需要等待相对较长的时间才能加载资源,因此在上面的示例中,您可能需要尝试每次滚动后等待的时间量。另外,正如我提到的,一般执行中的任意等待有时会影响资产是否加载。

一般来说,当使用 Puppeteer 进行屏幕截图时,您需要确保您的逻辑类似于真实的用户行为。您的目标是重现渲染场景,就好像有人在计算机中启动 Chrome 并导航到该网站一样。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Puppeteer:屏幕截图惰性图像不起作用[重复] 的相关文章

随机推荐