Screenshots 2.0 – Replace PhantomJS with NightmareJS

PhantomJS is nice for really simple stuff like i showed in the last post. But if you try to do more complicated stuff like: Login first and then make a screenshot … you better try NightmareJS.

NightmareJS is a high level wrapper for PhantomJS and it’s much easier to control the browser with it. You install it with:

npn install nightmare

The new screenshot script starts like the other one with the configuration. But then you can simply work with for-loops.


var urls = [];
urls.push('http://www.redbull.com/');
urls.push('http://www.karriere.at/');

var sizes = [];
sizes.push({width: 1024, height: 768});
sizes.push({width: 768, height: 1024});
sizes.push({width: 640, height: 1024});
sizes.push({width: 320, height: 1024});

var clip = true;

var Nightmare = require('nightmare');

for(u in urls) {
    for(s in sizes) {
        var nightmare = new Nightmare();

        var size = sizes[s];
        var filename = 'screen-' + String("0" + u).slice(-2) + '-' + size.width + '.png';
        var url = urls[u];

        nightmare
            .viewport(size.width, size.height)
            .goto(url)
            .wait()
            .screenshot(filename)
            .run(function(err, nightmare){
                console.log('Done.');
            });
    }
}

But i want to do some stuff before i make the screenshot … like a login. There is a use()-method in NightmareJS intended for plugins, but i use it for an encapsulated sub-queue. In the navigate()-function i do the login and then return to the main-queue to take the screenshot.


var urls = [];
urls.push('http://www.karriere.at/jobs/javascript');
urls.push('http://www.karriere.at/');

var sizes = [];
sizes.push({width: 1024, height: 768});
sizes.push({width: 768, height: 1024});
sizes.push({width: 640, height: 1024});
sizes.push({width: 320, height: 1024});

var email = 'test@test.at';
var password = 'test@test.at-password';

var navigate = function(nightmare) {
    return function(nightmare) {
        nightmare
            .click('#userLogin')
            .wait(200)
            .type('#loginForm [name=email]', email)
            .type('#loginForm [name=password]', password)
            .click('#submitBtn button')
            .wait();
    };
}

var Nightmare = require('nightmare');

for(u in urls) {
    for(s in sizes) {
        var nightmare = new Nightmare();

        var size = sizes[s];
        var filename = 'screen-' + String("0" + u).slice(-2) + '-' + size.width + '.png';
        var url = urls[u];

        nightmare
            .viewport(size.width, size.height)
            .goto(url)
            .wait()
            .use(navigate(nightmare))
            .screenshot(filename)
            .run(function(err, nightmare){
                console.log('Done.');
            });
    }
}

PhantomJS – Responsive Screenshots for Different Websites

PhantomJS is a headless browser. That means: It is a full and working browser, you can use it from command line and you can control it by scripts … but it has no window for displaying the websites.

What for?

We use it for creating screenshots or you can test your website automatically because PhantomJS can everything that a normal Webkit browser can. You could also build a crawler for javascript-powered websites or you can write performance monitoring scripts.

Installation is really simple, just download the archive and extract it … voila! Now you can now use the bin/phantomjs.

Screenshots

Here the complete and working script, the screenshots will be in the same folder as the script. You can run it with:
bin/phantomjs screenshots.js


/**
 * Configuration
 */

var urls = [];
urls.push('http://www.redbull.com/');
urls.push('http://www.karriere.at/');
urls.push('http://www.michael-feichtinger.at/');

var sizes = [];
sizes.push({width: 1024, height: 768});
sizes.push({width: 768, height: 1024});
sizes.push({width: 640, height: 1024});
sizes.push({width: 320, height: 1024});

/**
 * if clip is true the screenshot will be cropped to that size
 * else phantomjs will screenshot the whole website
 */
var clip = true;


/**
 * All the logic
 */

var uIdx = 0;
var sIdx = 0;
var webpage = require("webpage");

function next(uIdx, sIdx) {
    if(uIdx < urls.length) {
        screenshot(uIdx, sIdx);
    } else {
        phantom.exit();
    }
}

function screenshot(uIdx, sIdx) {
    
    var size = sizes[sIdx];
    var filename = 'screen-' + String("0" + uIdx).slice(-2) + '-' + size.width + '.png';
    var url = urls[uIdx];

    var page = webpage.create();
    page.viewportSize = size;

    if (clip) {
        page.clipRect = { top: 0, left: 0, width: size.width, height: size.height };    
    }

    page.open(url, function(){
        return window.setTimeout((function() {
            page.render(filename);
            page.close();

            sIdx++;
            if(sIdx >= sizes.length) {
                sIdx = 0;
                uIdx++;
            }

            return next(uIdx, sIdx);
        }), 200);
    });
}

next(uIdx, sIdx);