Login to a website and take screenshot using PhantomJS on the server side

Login to a website and take screenshot using PhantomJS on the server side

In this blog I will discuss about taking screenshots using PhantomJS by logging in to a site and taking screenshot a particular link or URL. I am not going describe how PhantomJS can be invoked on the server side.

Taking screenshots of visualizations with SVGs is not an easy task at least in Java. I have tried to produce the pdf of web pages with SVG content using the Apache Batik library but was not very successful. So, I have tried the alternatives and one of the options was PhantomJs.

PhantomJS is a headless browser and is capable of taking screenshots of complex visualizations otherwise difficult to capture. So, phantom is as good as Mozilla or Chrome but runs in-memory, so it is headless. PhantomJS has many applications and one of them is that it can be used to produce quality reports in different file formats like pdf and images.

Using ProcessBuilder API in Java we can invoke PhantomJS by providing the path of the Phantom executable, a javascript file that the PhantomJS uses to render the web page, and the location of the file where you want to save the generated file by PhantomJS. Once the pdf is generated it can be used for any purpose like mailing it or scheduling it or serving the user with a downloadable file.

The following is the screenshot.js file from PhantomJS web site. I have modified the code to log in using PhantomJS and take the screenshot and save it as a file on the file system.

 

//Here the command-line arguments that you've passed when invoking the PhantomJS executable 
//are obtained as an array. In this case I have passed phantom-js.exe as first argument, 
//the screenshot.js as the second argument.

//Note that The third argument is accessed as args[1] in the javascript file and the numbering continues.
var system = require('system');

// Web Address (URL) of the page to capture
var url = system.args[1];

// File name of the captured image
var file = system.args[2];

var reportPage = require('webpage').create();

// Browser size - height and width in pixels
// Change the viewport to 480x320 to emulate the iPhone
reportPage.viewportSize = {
    width: 1920,
    height: 1080
};

reportPage.paperSize = {
    format: 'A4',
    orientation: 'portrait',
    footer: {
        height: "1.0cm",
        contents: phantom.callback(function (pageNum, numPages) {
            return "<div style='font-size:13px;font-weight:normal;'>
                    <span style='text-align:left'>Confidential</span>
                    <span style='margin-left:44em'>" + pageNum + " of " + numPages + "</span></div>";
        })
    }
};

reportPage.settings.localToRemoteUrlAccessEnabled = true;
reportPage.settings.webSecurityEnabled = false;

// Set the User Agent String
// You can change it to iPad or Android for mobile screenshot
reportPage.settings.userAgent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.56 Safari/536.5";

var loginPage = require('webpage').create();

function getLoginUrl() {
    var loginUrl,
        domain = system.args[3],
        username = system.args[4],
        passCode = system.args[5],
        organization = system.args[6];

    //Form the login url. As a GET Request.
    loginUrl = domain + "?j_organization=" + organization + "&j_username=" 
               + username + "&j_password=" + passCode;

    return loginUrl;
}

function saveReport() {
    var logoutPage = require('webpage').create();
    reportPage.open(url, function (status) {
        if (status !== "success") {
            console.log("Fatal Error. Could not open web page : " + url);
            phantom.exit();
        } else {
            window.setTimeout(function () {
                reportPage.render(file);
                console.log("Download the screenshot : " + file);
                //Logout
                logoutPage.open("./j_spring_security_logout");
                phantom.exit();
            }, 3000);
        }
    });
}

//Now if login is successful, take the screenshot
loginPage.open(getLoginUrl(), function (loginStatus) {
    if (loginStatus !== "success") {
        console.log("Fatal Error. Couldn't login to get the report screenshot.");
    } else {
        // Render the screenshot image
        saveReport();
    }
});

 

Also note that when we start a process using command-line/shell script, do not forget the read the InputStream, and the ErrorStream of the java.lang.Process.
Hope you have followed the comments and understood the how to part of it. If you have any questions, please post them so that I will answer the questions.

Wish you happy coding and thanks for reading the article.


–Rajasekhar
Java BI Developer,
Helical IT Solutions.

PhantomJS and its “Render” function

PhantomJS – The Headless Webkit browser & its “Render” function

In this blog, we will have a quick introduction of PhantomJS and talk about its “Screen Capture” feature to render webpages or parts of webpages into images or PDFs.

PhantomJS is a headless browser which has a JavaScript API. It can be used for headless web-testing, page automation, network monitoring and the likes. It supports various test frameworks like Jasmine, Capybara, QUnit, Mocha, WebDriver, YUI Test, BusterJS, FuncUnit, Robot Framework. It has a native support for various web standards like DOM handling, CSS selectors, SVG, JSON etc. It can access and manipulate webpages with the standard DOM API or with libraries like JQuery. As PhantomJS permits the inspection of network traffic, it is suitable to build various analyses on the network behavior and performance as well.

PhantomJS – Screen Capture using “Render” function

Among one of its many capabilities, is the capability to programmatically capture web contents, including SVG and Canvas and save them as images or PDFs.
PhantomJS uses WebKit which is an open source web browser engine. As it uses a real layout and rendering engine, it can capture a web page as a screenshot. Because PhantomJS can render anything on the web page, it can be used to convert contents not only in HTML and CSS, but also SVG and Canvas. The PDFs are generated with selectable texts and embedded fonts.
The function used for this is –

render(filename [, {format, quality}]) {void}

Renders the web page to an image buffer and saves it as the specified filename. The output format is automatically set based on the file extension.

Supported formats:
PNG
GIF
JPEG
PDF

Quality:An integer between 0 and 100.

Working Example:

var webPage = require('webpage');
var page = webPage.create();

page.viewportSize = { width: 1920, height: 1080 };
page.open("http://www.google.com", function start(status) {
page.render('google_home.jpeg', {format: 'jpeg', quality: '100'});
phantom.exit();
});

You can selectively render contents in the webpage by using another function –

clipRect {object}
This property defines the rectangular area of the web page to be rasterized when page.render is invoked. If no clipping rectangle is set, page.render will process the entire web page.

Working Example –

var webPage = require('webpage');
var page = webPage.create();
page.clipRect = {
  top: 14,
  left: 3,
  width: 400,
  height: 300
};

You might want to render only a single element, for example your content div or a SVG, for this, you can use the element.getBoundingClientRect and PhantomJS page.clipRect together to get the desired output.

Shraddha
Helical IT Solutions