【问题标题】:Navigate page till rendering last frame not networkidel导航页面直到渲染最后一帧而不是networkidel
【发布时间】:2018-05-13 20:37:58
【问题描述】:

我正在为大 html 截屏,但每次我尝试截取图像时,输出图像中都会出现很大的空白。

我做了很多测试,发现在load事件之后渲染了帧,所以我没有在捕获的图像中得到它。

这是显示性能的图像 显示load 事件的红线和该行之后的帧。

我尝试阅读该软件包的所有文档,但我是一名土木工程师,对编程知之甚少,我尽了最大努力,但找不到解决方案。

page.goto 中有 4 个选项,它们不能解决问题,这是文档的 url。 https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagegotourl-options

这是我的代码

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('D:\Image_2.HTML', {waitUntil: 'load'});
  function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
console.log(page.frames())
  await page.screenshot({path: 'example.png',fullPage : true});

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

【问题讨论】:

    标签: javascript node.js google-chrome google-chrome-devtools puppeteer


    【解决方案1】:

    我使用另一个包解决了这个问题,问题在于写入图像而不是渲染。所以我把大图分成四等份。

    /* Dependencies */
    const chromeLauncher = require('lighthouse/chrome-launcher/chrome-launcher');
    const CDP = require('chrome-remote-interface');
    const fs = require('fs');
    
    /** ARGUMENTS AND CONFIGUIRATION
     * expects arguments to be
     * -w int (width)
     * -h int (height)
     * -p int (port)
     * --url string (url)
     */
    
    const argv = require('minimist')(process.argv.slice(2));
    const windowWidth = argv.w ? argv.w : 1024;
    const windowHeight = argv.h ? argv.h : 1024;
    const filename = argv.filename;
    const filename2 = argv.filename2;
    const filename3 = argv.filename3;
    const filename4 = argv.filename4;
    
    headless=true
    const launchConfig = {
        chromeFlags: [
            `--window-size=${windowWidth},${windowHeight}`,
            '--disable-gpu',
         headless ? '--headless' : ''
         ]
    }
    //function sleep(ms) {
     // return new Promise(resolve => setTimeout(resolve, ms));
    //}
    
    
    function saveScreenshot(imageData, pageURL) {
        fs.writeFile(
            filename,
            imageData.data, {encoding:'base64'},
            (err)=>{
                console.warn('error', "1");
            }
        );
    
    }
    function saveScreenshot2(imageData, pageURL) {
        fs.writeFile(
            filename2,
            imageData.data, {encoding:'base64'},
            (err)=>{
                console.warn('error', "2");
            }
        );
    
    }
    function saveScreenshot3(imageData, pageURL) {
        fs.writeFile(
            filename3,
            imageData.data, {encoding:'base64'},
            (err)=>{
                console.warn('error', "3");
            }
        );
    
    }
    function saveScreenshot4(imageData, pageURL) {
        fs.writeFile(
            filename4,
            imageData.data, {encoding:'base64'},
            (err)=>{
                console.warn('error', "4");
            }
        );
    
    }
    
    async function launchChrome(headless = true) {
      return await chromeLauncher.launch(launchConfig);
    }
    
     async function saveScreenShotFromURL(pageURL) {
         const chrome = await launchChrome();
         const protocol = await CDP({port: chrome.port});
         const {Page, Runtime} = protocol;
    
         await Promise.all([Page.enable(), Runtime.enable()]);
    
         Page.navigate({url: pageURL});
         Page.loadEventFired(async () => {
    
         const screenshot = await Page.captureScreenshot({clip : {x:0,y:0,width : 3100,height : 3030,scale : 1}});
         const screenshot2 =await  Page.captureScreenshot({clip : {x:0,y:3030,width : 3100,height : 3030,scale : 1}});
         const screenshot3 =await  Page.captureScreenshot({clip : {x:3100,y:0,width : 3100,height : 3030,scale : 1}});
         const screenshot4 = await Page.captureScreenshot({clip : {x:3100,y:3030,width : 3100,height : 3030,scale : 1}});
    
            Promise.resolve( screenshot).then((imageData)=>{
                saveScreenshot(imageData,pageURL);
            });
            Promise.resolve( screenshot2).then((imageData)=>{
                saveScreenshot2(imageData,pageURL);
            });
            Promise.resolve( screenshot3).then((imageData)=>{
                saveScreenshot3(imageData,pageURL);
            });
            Promise.resolve( screenshot4).then((imageData)=>{
                saveScreenshot4(imageData,pageURL);
            });
    
            protocol.close();
            chrome.kill();
         });
     }
    

    saveScreenShotFromURL(argv.url) 如果您知道如何async 同时打印 4 张图像,请帮助我。

    【讨论】:

    • 为什么是固定数字 4?
    • 抱歉回复晚了,你的意思是我为什么把大图分成4张小图?,你可以把它改成很多很多小图,4个是假设的。
    【解决方案2】:

    您发布的脚本定义了sleep 函数,但没有调用它。 如果您等待足够的时间,您就会使页面达到所需的状态。

    注意:您可以使用await page.waitFor() 方法“睡觉”。

    const puppeteer = require('puppeteer');
    
    (async () => {
      const browser = await puppeteer.launch();
      const page = await browser.newPage();
      await page.goto('D:\Image_2.HTML', {waitUntil: 'load'});
      // wait for 2 seconds
      await page.waitFor(2000); 
      await page.screenshot({path: 'example.png',fullPage : true});
      await browser.close();
    })();
    

    一般来说,“我的页面何时加载”这个问题没有很好的答案。 page.goto 中可用的 waitUntil 选项只是常见的启发式方法,它们可能在多种情况下失败。

    很难说你的情况出了什么问题;通常需要了解网页内部的工作情况才能确定其所需的加载状态。

    【讨论】:

    • 非常感谢您的回复,sleep 并没有解决问题,请稍等,要我上传文件给您并通过聊天发送链接吗?
    • html 渲染完美,但问题是,加载事件后有帧渲染,所以当我捕获屏幕时,未渲染的帧被写为空白。
    • 我在想什么,如果在html中渲染图像后可以截图,因为我的html是一张地图,由许多相互合成的图像组成
    • 当 waitUntil:'load' 然后在它后面写 waitfor ,它什么也不做,因为页面在加载事件之后停止渲染,如果有类似 WaitUntil : 'FinishRendering' 的东西,并且渲染总是在加载事件之后完成。
    • @OmarAbdEl-Naser 啊,我现在明白了。不幸的是,这是图像光栅化错误。 github.com/GoogleChrome/puppeteer/issues/477
    猜你喜欢
    • 1970-01-01
    • 2022-12-17
    • 2019-11-29
    • 2021-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多