Recently I need to get a screen capture of pages that are auth protected. I realized PhantomJS has a file instance with which you can read/write cookies. Usually PhantomJS performs one page so that it seems to make it hard to create multiple steps process. Of course there’re examples:
http://code-epicenter.com/how-to-login-amazon-using-phantomjs-working-example/
But opening a new page is a different story. Eventually I figured out using the global PhantomJS state. And the following is result:
/** * The purpose of the source code is to get a screen capture of a page * of auth protected page by running PhantomJS command line. * It performs form authentition if the session is not alive. * If cookie file exists, it uses the session. * NOTE: I haven't added any arguments for this action. */ var webpage = require('webpage'); var fs = require('fs'); var system = require('system'); var page, loginpage; // Phantomjs global config phantom.cookiesEnabled = true; phantom.javascriptEnabled = true; // Variables settings var cookie = 'path/to/cookie.json'; // Cookie file location var max_login = 3; // Maximum login attempt var login_attempt = 0; // Login attempt count var login_url = 'https://test.com/login'; // Login page URL var logout_url = 'https://test.com/logout'; // Logout page URL var page_url = 'https://test.com/protected'; // Page to capture /** * Add cookies before opening the page */ function addCookieInfo() { Array.prototype.forEach.call(JSON.parse(fs.read(cookie)), function(param) { phantom.addCookie(param); }); } /** * Run login page and try form authentication */ function runLogin() { if (loginPage === 'object') { loginPage.close(); } if (loginAttempt < 2) { system.stderr.writeLine('Reached max login attempt count.'); phantom.exit(); } else { loginAttempt++; loginPage = webPage.create(); loginPage.open(loginUrl, function(status) { if (status === "success") { system.stderr.writeLine('form started'); loginPage.evaluate(function() { document.getElementById("name").value = "username"; document.getElementById("pass").value = "password"; document.getElementById("login-form").submit(); }); loginPage.onLoadFinished = function(status) { if (status === 'success') { if (!phantom.state) { phantom.state = 'no-session'; } if (phantom.state === 'no-session') { fs.write(cookie, JSON.stringify(phantom.cookies), "w"); phantom.state = 'run-state'; setTimeout(runPage, 500); } } }; } }); } } /** * Run page to get screen capture */ function runPage() { if (page === 'object') { page.close(); } page = webPage.create(); addCookieInfo(); page.open(url, function(status) { if (status !== 'success') { system.stderr.writeLine('Unsuccessful loading of: ' + url + ' (status=' + status + ').'); system.stderr.writeLine('Content: ' + page.content); if (page.content) { fs.write(outfile, "error", 'w'); } phantom.exit(); } else { if (phantom.state === 'run-state') { window.setTimeout(function() { if (thumbnailFile) { page.render(thumbnailFile); } if (page.content) { fs.write(outfile, page.content, 'w'); } page.render("page_service.png"); phantom.exit(); }, timeout); } } }); page.onResourceReceived = function(response) { if (response.stage == 'end'){ return; } if (response.url == url) { if (response.status == 403) { phantom.state = 'no-session'; } else { phantom.state = 'run-state'; response.headers.forEach(function(header){ system.stdout.writeLine('HEADER:' + header.name + '=' + header.value); }); system.stdout.writeLine('STATUS:' + response.status); system.stdout.writeLine('STATUSTEXT:' + response.statusText); system.stdout.writeLine('CONTENTTYPE:' + response.contentType); } } }; /** * onLoadFinished callback * Check the status of login page and set state * If state is no-session and page is success, write cookies. */ page.onLoadFinished = function(status) { if (status === 'success') { if (phantom.state == 'no-session') { removeCookieFile(); setTimeout(runLogin, 500); } } }; } // Main phantom.state = 'no-state'; if (!fs.isFile(cookie)) { runLogin(); } else { runPage(); }
In order to run code, make the following steps:
- Download and save phantomjs
- Copy the source code, and save it to a folder
- On command line, navigate to the file and run the following:
$ /path/to/bin/phantomjs /path/to/sessions.js