简体   繁体   中英

Screenshot of multiple HTML pages using PhantomJS

So as everyone has mentioned in this github issue , the viewport size function in phantomJS doesn't behave as a lot of people expected.

I am trying to take screenshots of a web app for an iPad. The site has a position:fixed; footer and header. When I take a screenshot I only want to be able to see what would be viewable on the screen when you first load the page, so i've used the following code to clip the page to the size I want.

page.clipRect = { top: 0, left: 0, width: 1024, height: 768 };

Because the site has a position: fixed; header and footer when I do this and take a screenshot, the footer is missing when the content on the page forces a scroll. (Its right at the bottom of the page)

在此输入图像描述

In the replies, one solution would be to load the page you would like to take a screenshot of into an object with the height and width you of your preference, and then take a screenshot of the object instead.

All the code snippets with this implemented, assume you have a single URL that you would like to take a screenshot of. I would like to take screenshots of multiple html files. I am not fluent in Javascript at all and I'm really struggling to merge these solutions into my code.


This solution takes a single webpage and converts it into multiple images of differnet sizes using a json file.

While this solution is more along the lines that i'm looking for but again, just a single web page. Please note that iframe doesn't work and the iframe code would need to be replaced with an object with a data attribute with a value of the html page to be loaded.

And a final solution , which is more complete than the others, but again is just a single URL


I have been using the following code in the past, and its worked perfectly with web apps built to specific dimensions, but this one has been built slightly differently which is why the screenshots are being a nightmare.

var system = require('system');
var dest = system.args[1];
var files = system.args[2].split(',');

function takeScreenshot(destName, index) {
    var page = require('webpage').create();

    // Open the target HTML file
    page.open(dest+'/'+destName+'/'+destName+'.html', function(status) {

        // Only capture 1024x768 area 
        page.clipRect = { top: 0, left: 0, width: 1024, height: 768 };

        // Save as PNG
        page.render(dest+'/'+destName+'/'+destName+'-full.png');

        // Send output to be caught by progress bar
        console.log('OK');

        // If the lop has finished exit, otherwise clean memory
        if(files.length == 0) {
        phantom.exit();
        } else {
            page.close();
            takeScreenshot(files.shift());
        }
    });

}

takeScreenshot(files.shift());

dest variable is the destination of the screenshots.

files is an array of files that I would like to take a screenshot of.

It should be easy to combine the final solution with your existing code. The idea is to move the actual code into a function and call the function with the new URL after the previous one finished. When you look into the "final solution", the spots where we are finished with the current page are denoted with phantom.exit(); . From there you can trigger further screenshots.

Here is the complete script, modified from the version of DEfusion:

var args = require('system').args,
    resourceWait  = 300,
    maxRenderWait = 10000,
    mode          = args[3] || 'iframe',
    dest          = args[1],
    files         = args[2].split(','),
    page          = require('webpage').create(),
    count         = 0,
    forcedRenderTimeout,
    renderTimeout;

page.viewportSize = { width: 1024, height : 768 };

function doRender() {
    page.render(filename);
    next();
}

page.onResourceRequested = function (req) {
    count += 1;
    clearTimeout(renderTimeout);
};

page.onResourceReceived = function (res) {
    if (!res.stage || res.stage === 'end') {
        count -= 1;
        if (count === 0) {
            clearTimeout(forcedRenderTimeout);
            renderTimeout = setTimeout(doRender, resourceWait);
        }
    }
};

page.onConsoleMessage = function (msg) {
    console.log("from page: " + msg);
};

function evaluateJsWithArgs(func) {
    var args = [].slice.call(arguments, 1);
    var fn = "function() { return (" + func.toString() + ").apply(this, " + JSON.stringify(args) + "); }";
    return page.evaluate(fn);
};

function next(error){
    if (!error) {
        if (files.length == 0){
            phantom.exit();
        } else {
            takeScreenshot(files.shift());
        }
    }
}

function takeScreenshot(file){
    var url = dest+'/'+file+'/'+file+'.html';
    filename = dest+'/'+file+'/'+file+'-full.png';
    if(mode == 'iframe') {
        // use iFrame
        page.open('about:blank', function (status) {
            if (status !== "success") {
                console.log('Unable to load url');
                next(true);
            } else {
                page.includeJs(
                    "https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js",
                    function() {
                        evaluateJsWithArgs(
                            function(url, w, h) {
                                $('body')
                                    .css({margin: 0, padding: 0})
                                    .append('<object data="' + url + '" width="'+ w + '" height="' + h + '" id="screen-frame" />');
                                $('#screen-frame')
                                    .width(w)
                                    .height(h);
                            },
                            url,
                            page.viewportSize.width,
                            page.viewportSize.height
                        );
                    }
                );

                forcedRenderTimeout = setTimeout(function () {
                    doRender();
                }, maxRenderWait);
            }
        });
    } else {
        // resize body
        page.open(url, function(status) {
            if (status !== "success") {
                console.log('Unable to load url');
                next(true);
            } else {
                page.includeJs(
                    "https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js",
                    function() {
                        evaluateJsWithArgs(
                            function(w,h) {
                               $('body, html').css({
                                    width: w + 'px',
                                    height: h + 'px',
                                    overflow: 'hidden'
                               });
                            },
                            page.viewportSize.width,
                            page.viewportSize.height
                        );

                        forcedRenderTimeout = setTimeout(function () {
                            doRender();
                        }, maxRenderWait);
                    }
                );
            }
        });
    }
}

takeScreenshot(files.shift());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM