木偶不等页面加载完成

时间:2019-05-31 19:21:09

标签: javascript node.js puppeteer

我写了一个脚本来拍摄网页上50个尺寸图表的屏幕截图。每个图表都包含在一个元素中。有趣的是,仅捕获了前三个表格图表,其余的PNG文件为空白,完全为白色。

由于图表是从数据库中提取的,所以我认为可能是在截屏之前尚未完成页面的加载,因此我添加了{“ waitUntil”:“ networkidle0”},但这并没有解决任何问题。尽管如此,该脚本仅创建前三个图表的屏幕截图,分别为0.png,1.png和2.png。其余的PNG文件3.png-49.png均已创建,但只有白色数据。

可能是什么问题?如果我在浏览器上访问该页面,则所有50个图表均完美加载,那么为什么Puppeteer仅截取前三个屏幕截图?这是我的脚本:

const puppeteer = require( 'puppeteer' );

( async() => {
    const browser = await puppeteer.launch();

    const page = await browser.newPage();
    await page.goto( 'http://www.example.com/size-charts.php', { "waitUntil": "networkidle0" } );

    // Get a list of all elements.
    const elements = await page.$$( 'div.chartContainer' );

    for( let i = 0; i < elements.length; i++ ) {
        try {
            // get screenshot of a particular element
            await elements[ i ].screenshot( { path: `${ i }.png` } );
        }
        catch( e ) {
            console.log( `Couldn't take a screenshot of the element with the index of: ${ i }. Reason: `, e );
        }
    }

    await browser.close();
} )();

2 个答案:

答案 0 :(得分:0)

虽然实际解决方案可以/应该等待每个元素可见,但是还有其他可能的解决方案。

可能的解决方案1 ​​

您可以滚动到该元素,等待一段时间以正确呈现,然后截取屏幕截图。

elementHandle.screenshot()滚动到该元素,但是没有办法延迟或等待该元素可见。

quick search on official repo显示,在此次活动中至少有19个未解决的问题提到blank screenshot

相反,在截屏之前,我们可以使用自定义.evaluate或.hover等滚动到元素。

  

elementHandle.hover():此方法在需要时将元素滚动到视图中,然后使用page.mouse将鼠标悬停在元素的中心。如果该元素与DOM分离,则该方法将引发错误。

让我们使用它,

// Get a list of all elements.
const elements = await page.$$('div.chartContainer');

for (let i = 0; i < elements.length; i++) {
  // scrolls into view and hovers the element
  await elements[i].hover();

  // wait for some random number 
  await page.waitFor(1000);

  // get screenshot of a particular element
  await elements[i].screenshot({
    path: `${ i }.png`
  });
}

可能的解决方案2

有人报告说,使用elementHandle.boundingBox()解决了他们的问题。它的作用是,获取元素的位置,高度,宽度等,并将其用于屏幕截图。

// Get a list of all elements.
const elements = await page.$$('div.chartContainer');

for (let i = 0; i < elements.length; i++) {
  // get screenshot of a particular area
  await page.screenshot({ // <-- use page here
    path: `${ i }.png`,
    clip: await elements[i].boundingBox() // <-- use clip here
  });
}

答案 1 :(得分:0)

我将回答自己的问题,希望它可以帮助其他人。在我的特定情况下,解决方案是将视口高度设置为非常大的数字,例如:

page.setViewport( { width: 1920, height: 100000 } );

此后,该脚本能够创建所有选定元素的屏幕截图。