javascript - How to exit phantom if it hangs on page.open (with example) -


 var system = require("system");       var page;        // user supplied url       var myurl = system.args[1];       // var myurl = 'https://waffles.ch/';        page = require('webpage').create();        // suppress errors output       page.onerror = function(msg, trace) {};        // 5 seconds       page.settings.resourcetimeout = 5000;        // page.settings.javascriptenabled = false;        page.open(myurl, function(status) {            //hack page.open not hooking phantom.onerror           settimeout(function() {               if (status !== "success") {                   console.log(myurl);                   phantom.exit();                   throw new error("unable access network");               } else {                   var pagetitle = myurl.replace(/http.*\/\//g, "").replace("www.", "").split("/")[0];                   var filepath = "img/" + pagetitle + '.jpg';                   page.render(filepath, {format: 'jpeg', quality: '75'});                   console.log(filepath);                   phantom.exit();               }            }, 0);       }); 

using above code take screenshots works fine webpages. running script through console or web app url "https://waffles.ch/", however, causes hang infinitely on page.open (i believe).

the reason assume because url contains js animation doesn't stop running (an aeroplane flying across screen), , causes phantom lock up. known bug??

i'm quite sure js causes hang because if switch off page.settings.javascriptenabled = false; screenshot page rendered without problems.

i can't realistically switch off javascript take screenshots obvious reasons (page.evaluate, redirects etc), here's 2 questions.

1.) there way render screenshot webpage containing animation waffles.ch without having switch off javascript??

2.) if webpage hang, on page.open how can exit phantom , possibly return errror??)

any help/advice appreciated.

phantom version: 2.1.1 os: windows 7 64 bit.

other thing i've tried.(but still hangs above url)

with try/catch

var system = require("system"); var page; // user supplied url var myurl = system.args[1];  var page = require('webpage').create(); page.open(myurl, function (status) {     try {         if (status !== "success") {             console.log("unable access network");             phantom.exit();         } else {             //do stuff dom             var pagetitle = myurl.replace(/http.*\/\//g, "").replace("www.", "").split("/")[0];             var filepath = "img/" + pagetitle + '.jpg';             page.render(filepath, {format: 'jpeg', quality: '75'});             console.log(filepath);             phantom.exit();         }     } catch (ex) {         var fullmessage = "\njavascript exception";         fullmessage += "\nmessage: " + ex.tostring();         (var p in ex) {             fullmessage += "\n" + p.touppercase() + ": " + ex[p];         }         console.log(fullmessage);     } });   // ****************************** 

using waitfor() function. https://github.com/ariya/phantomjs/blob/master/examples/waitfor.js

var system = require("system"); var page; // user supplied url var myurl = system.args[1];  var page = require('webpage').create();  // suppress errors output page.onerror = function(msg, trace) {   console.log("error occurred" + msg);   phantom.exit(); };  // 5 seconds page.settings.resourcetimeout = 5000;  page.open(myurl, function (status) {     // check page load success     if (status !== "success") {         console.log("unable access network");         phantom.exit();     } else {         waitfor(function() {             // check in page if specific element visible             return page.evaluate(function() {                  return $("body").is(":visible");             });         }, function() {            console.log("body visible");            phantom.exit();         });     } }); 

turns out there no way terminate phantom in situation, @ least not but, there way avoid problem.

the root cause implementation of requestanimationframe in phantomjs doesn't play nice tweenjs. number returned callback phantom unix epoch number (but fractional seconds) , tweenjs expects domhighrestimestamp (like performance.now(), starting 0 when process starts). epoch number higher tween end time, every update seen end of tween , causes tween.update slam through next cycle, causing block.

the way fix inject polyfill, including performance.now pollyfil, overwrite phantom's requestanimationframe implimentation, using page.injectjs.

here code needs injected (or st better)...

request-animation-frame.js

// include performance.now polyfill var = (function () {     // in node.js, use process.hrtime.     if (this.window === undefined && this.process !== undefined) {       = function () {         var time = process.hrtime();          // convert [seconds, microseconds] milliseconds.         return time[0] * 1000 + time[1] / 1000;       };     }     // in browser, use window.performance.now if available.     else if (this.window !== undefined &&       window.performance !== undefined &&       window.performance.now !== undefined) {        // must bound, because directly assigning function       // leads invocation exception in chrome.       = window.performance.now.bind(window.performance);     }     // use date.now if available.     else if (date.now !== undefined) {       = date.now;     }     // otherwise, use 'new date().gettime()'.     else {       = function () {         return new date().gettime();       };     }     return   })();  // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating  // requestanimationframe polyfill erik möller. fixes paul irish , tino zijdel  // mit license  // adapted shim floating point milliseconds since page opened // https://developers.google.com/web/updates/2012/05/requestanimationframe-api-now-with-sub-millisecond-precision?hl=en   (function() {   var lasttime = 0;   var raf = window.requestanimationframe;    window.requestanimationframe = function(callback) {     var currtime = now();     var timetocall = math.max(0, 1000/60 - (currtime - lasttime));     var tcb = currtime + timetocall;     var cbprxy = (function (cb, t) {       return function (discard) {         cb(t)       }     })(callback, tcb);     var id = raf       ? raf.call(window, cbprxy)       : window.settimeout(function() { callback(tcb); }, timetocall);      lasttime = currtime + timetocall;      return id;   };    if(!window.cancelanimationframe)     window.cancelanimationframe = cleartimeout  }()); 

and here code put in phantoms outer context inject it...

page.oninitialized = function() {   page.injectjs('request-animation-frame.js'); }; 

in context of question...

/**  * adjusted cool.blue on 08-sep-16.  */ var system = require('system'); var page;  // user supplied url var myurl = system.args[1] || 'https://waffles.ch/';  page = require('webpage').create();  // suppress errors output page.onerror = function(msg, trace) {};  function exitphantom (message) {   console.log(message)   phantom.exit(message.match("error:") ? 1 : 0) }  page.onconsolemessage = function(message) {   system.stdout.write('> ' + message + '\n') };  page.oninitialized = function() {   page.injectjs('request-animation-frame.js'); };  // 5 seconds page.settings.resourcetimeout = 10000;  // page.settings.javascriptenabled = false; page.open(myurl, function(status) {    //hack page.open not hooking phantom.onerror   settimeout(function() {     if (status !== "success") {       exitphantom('error: ' + status);       throw new error("unable access network");     } else {       var pagetitle = myurl.replace(/http.*\/\//g, "").replace("www.", "").split("/")[0];       var filepath = "img/" + pagetitle + '.jpg';       page.render(filepath, {format: 'jpeg', quality: '75'});       console.log(filepath);       exitphantom(status);     }   }, 1000);  }); 

in case, resourcetimeout feature work advertised , protect against over-long load times , page uses similar animation techniques work fine.


Comments

Popular posts from this blog

java - Jasper subreport showing only one entry from the JSON data source when embedded in the Title band -

mapreduce - Resource manager does not transit to active state from standby -

serialization - Convert Any type in scala to Array[Byte] and back -