I try to make a screenshot of www.fallswoodsmith.com with PhantomJS. My code is:
var page = require('webpage').create();
page.viewportSize = { width: 1024, height: 768 };
page.clipRect = {top: 0, left: 0, width: 1024, height: 768};
page.open('http://www.fallswoodsmith.com', function () {
page.render('cache/www.fallswoodsmith.com123567266_1024_768.png', {format: 'png', quality: '10'});
phantom.exit();
});
This page is JS only, so without JS you get no content. For some reason PhantomJS is not executing this JS. I've also tried to set a timeout of 5 secs for the page.render()
and phantom.exit()
, but this did not change something. If I do a console.log(page.content)
before the page.render()
I get the full HTML of the page - just without changes that JS does.
Why does PhantomJS not execute the page's JS?
UPDATE 1: I've added the following debug stuff:
page.onConsoleMessage = function(msg, lineNum, sourceId) {
console.log('CONSOLE: ' + msg + ' (from line #' + lineNum + ' in "' + sourceId + '")');
};
page.onError = function(msg, trace) {
var msgStack = ['ERROR: ' + msg];
if (trace && trace.length) {
msgStack.push('TRACE:');
trace.forEach(function(t) {
msgStack.push(' -> ' + t.file + ': ' + t.line + (t.function ? ' (in function "' + t.function +'")' : ''));
});
}
console.error(msgStack.join('\n'));
};
page.onResourceError = function(resourceError) {
console.log('Unable to load resource (#' + resourceError.id + 'URL:' + resourceError.url + ')');
console.log('Error code: ' + resourceError.errorCode + '. Description: ' + resourceError.errorString);
};
page.onResourceTimeout = function(request) {
console.log('Response (#' + request.id + '): ' + JSON.stringify(request));
};
No console.log() output in my console...
If I may politely ask, who made that site? I would very much recommend not building sites in such a way that they are 100% dependent on JavaScript. Turning off JavaScript and "loading" that site (www.fallswoodsmith.com) results in nothing. zip. nada. zilch. </rant>
Running the screenshot script you have above, I get the following output:
TypeError: 'undefined' is not a function (evaluating 'joinURL.bind(null, staticServerUrl)')
http://static.parastorage.com/services/santa-versions/1.150.0/main-r.js:353 in wixRenderSite
To fix that issue, you can polyfill Function.prototype.bind
(which is missing from PhantomJS 1.x, as per this issue) after the web page object is created but before a URL is loaded (i.e. onInitialized
).
The result:
var page = require('webpage').create();
page.onInitialized = function () {
page.evaluate(function () {
var isFunction = function (obj) {
return typeof obj == 'function' || false;
};
var slice = Array.prototype.slice;
Function.prototype.bind = function bind(obj) {
var args = slice.call(arguments, 1);
var self = this;
var F = function () {};
var bounded = function() {
return self.apply(
this instanceof F ? this : (obj || {}),
args.concat(slice.call(arguments))
);
};
F.prototype = this.prototype || {};
bounded.prototype = new F();
return bounded;
};
});
};
page.open('http://www.fallswoodsmith.com', function () {
setTimeout(function screenshot() {
page.render('WORKS.png', {
format: 'png',
quality: '10',
});
phantom.exit();
}, 10 * 1000);
});
Why wait 10 seconds before taking a screenshot? Well, since the site is completely reliant on JS, there is no obvious event (that I can think of) to wait for that indicates the loading of the page. Your mileage may vary. Increase or decrease the timeout as you see fit.
Note: the output filename above is WORKS.png
.
The above example was tested and works with PhantomJS 1.9.7. The script seems to work with PhantomJS 1.9.8 as well, but 1.9.8 has this issue (Unsafe JavaScript attempt to access frame in 1.9.8) that, while fixed, is not part of any release and causes the following error-looking output:
Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://28011634.js. Domains, protocols and ports must match.
Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://28011634.js. Domains, protocols and ports must match.
Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://28011634.js. Domains, protocols and ports must match.
Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://28011634.js. Domains, protocols and ports must match.
By default, the rendered image will be a full page screenshot. To fix the viewport size, you can add back in the following at the top of the script:
page.viewportSize = {
width: 1024,
height: 768
};
page.clipRect = {
top: 0,
left: 0,
width: 1024,
height: 768
};
.bind
The polyfill found on MDN, doesn't seem to work without a bit of modification, but that, combined with the underscore.js source code and this answer resulted in the above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With