对于任何想知道的人来说,有很多策略可以在 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 并导航到该网站一样。