如何使用puppeteer拍摄多个网站的完整屏幕截图?

时间:2019-06-27 23:36:56

标签: javascript node.js puppeteer browser-automation

我正在尝试使用带有puppeteer的Node.js截屏。我没有使用page.screenshot(),因为屏幕截图需要包含整个桌面。相反,我正在使用ImageMagick的import命令进行屏幕截图。

我当前的代码大部分时间都有效。但有时,它会失败,并产生奇怪的结果,例如:

  • 选项卡已切换,但屏幕截图包含了旧页面的一半。
  • 页面已切换,但为空白。
  • 添加延迟有效但并不理想,因为有时页面加载非常慢。

问题似乎是page.bringToFront()没有等待页面完全加载。

我是Node和puppeteer的新手。请提出一种方法:

  1. 在Chrome中加载页面。
  2. 加载后切换到页面。
  3. 通过执行命令行工具为桌面截图。

在代码中添加延迟似乎不是最佳解决方案。

任何有关代码改进的建议都会有所帮助。

const puppeteer = require('puppeteer');
const execSync = require('child_process').execSync;
const sleep = require('sleep'); 

(async () => {
    const browser = await puppeteer.launch({
        headless: false,
        args: [
            '--ignore-certificate-errors',
            '--no-sandbox',
            '--disable-infobars',
            '--disable-setuid-sandbox',
            '--incognito',
            '--window-size=1600,1200',
            '--start-maximized',
            "--disable-gpu"],
        // slowMo: 250, // slow down by 1550ms
    });

    await browser.newPage();
    await browser.newPage();
    const pages = await browser.pages();
    await Promise.all([
        grabpage(pages[0], 'https://www.cnn.com', 'cnn'),
        grabpage(pages[1], 'https://www.bbc.com', 'bbc'),
        grabpage(pages[2], 'https://www.rediff.com', 'rediff'),
    ]);
    // Someday we will close the browser also.
})();

async function grabpage(page, url, path) {
    await page.goto(url);
    var infront =page.bringToFront();
    infront.then(
        sleep.sleep(5),
        execSync('import -window root ' + path +'.jpg'),
    );
    console.log('took Screenshot: '+path+'.jpg')
}

Rediff page not loaded fully without sleep

1 个答案:

答案 0 :(得分:1)

通过尝试与Promise.all并行运行所有内容,使一切都变得混乱。因为您只有一个browser实例,所以当您并行运行grabpage 3次时,它们都在争夺对浏览器的控制权,并且可以进入彼此的await之间。 / p>

我还建议您打开和关闭grabpage中的各个页面。您必须将其切换为传递browser并执行const page = await browser.newPage();

所以你最终得到

(async () => {
    const browser = await puppeteer.launch({
      headless: false,
      args: [
            '--ignore-certificate-errors',
            '--no-sandbox',
            '--disable-infobars',
            '--disable-setuid-sandbox',
            '--incognito',
            '--window-size=1600,1200',
            '--start-maximized',
            "--disable-gpu"],
      //      slowMo: 250, // slow down by 1550ms
    });

    await grabpage(browser, 'https://www.cnn.com', 'cnn'),
    await grabpage(browser, 'https://www.bbc.com', 'bbc'),
    await grabpage(browser, 'https://www.rediff.com', 'rediff'),
})();

async function grabpage(browser, url, path) {
  const page = await browser.newPage();
  await page.goto(url);
  execSync('import -window root ' + path +'.jpg')
  // await page.screenshot({path: `${path}.png`}); //if you just need to take a screenshot, not the whole desktop
  await page.close();
}

不确定是否需要使用完整的桌面,即使您start-maximized也是如此。我猜您在乎屏幕截图中的一小部分操作系统镶边。