2016-09-07 13 views
1
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 from output 
     page.onError = function(msg, trace) {}; 

     // 5 seconds 
     page.settings.resourceTimeout = 5000; 

     // page.settings.javascriptEnabled = false; 

     page.open(myurl, function(status) { 

      //hack for page.open not hooking into phantom.onError 
      setTimeout(function() { 
       if (status !== "success") { 
        console.log(myurl); 
        phantom.exit(); 
        throw new Error("Unable to 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); 
     }); 

上記のコードを使用すると、ほとんどのWebページで正常に動作します。 URL "https://waffles.ch/"を持つコンソールまたはWebアプリケーションを介してスクリプトを実行すると、それは無限にpage.open(私は信じて)にハングアップします。ページが開いているときにファントムを終了する方法(例)

このURLには、実行を停止しない飛行機(画面上を飛行する飛行機)がいくつか含まれていて、ファンタムがロックアップする原因が考えられます。これは既知のバグですか?

JSは、page.settings.javascriptEnabled = false;でスイッチをオフにすると、ページのスクリーンショットが問題なくレンダリングされるため、JSがハングする原因になります。

明らかに私は2つの質問があるので、明らかにスクリーンショットを撮るためにjavascriptをオフにすることはできません(page.evaluate、redirectsなど)。

1.)JavaScriptをオフにすることなくwaffles.chのようなアニメーションを含むウェブページのスクリーンショットをレンダリングする方法はありますか?

2)Webページがどのように私はファントムを終了することができ、おそらくも?? errrorを返すpage.openに、ハングアップした場合)

すべてのヘルプ/アドバイスをいただければ幸いです。

ファントムバージョン:2.1.1 OS:Windows 7 64ビット。 waitfor()機能を使用して、私は。試してみました(それでも上記URLでハング)しました

他の事

の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 to access network"); 
      phantom.exit(); 
     } else { 
      //do some stuff with the 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(); 
     for (var p in ex) { 
      fullMessage += "\n" + p.toUpperCase() + ": " + ex[p]; 
     } 
     console.log(fullMessage); 
    } 
}); 


// ****************************** 

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 from 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 for page load success 
    if (status !== "success") { 
     console.log("Unable to access network"); 
     phantom.exit(); 
    } else { 
     waitFor(function() { 
      // Check in the page if a specific element is now visible 
      return page.evaluate(function() { 

       return $("body").is(":visible"); 
      }); 
     }, function() { 
      console.log("body is visible"); 
      phantom.exit(); 
     }); 
    } 
}); 
+0

ウォッチドッグタイマーを設定すると、タイムアウトが許可されていればタグ付きメッセージを 'console.log'に出力できます。ランナーコンテキストのメッセージを、 'phantom.exit()'ステートメントを発行できる 'onConsoleMessage'リスナーで解析することができます。 –

+0

あなたは私が今までに見たonErrorコールバックを奇妙に使用しています。エラーを無視するだけです。エラーを監視し、その出力を抑止する必要はありません。 – Vaviloff

+0

@Cool Blue、以前はウォッチドッグタイマーについて聞いたことがありません。このスクリプトはあなたの提案を達成するでしょうか? https://github.com/GCheung55/watchout –

答えて

1

問題を回避する方法はあり、少なくともそれ自体によって、この状況でファントムを終了させる方法はありませんが判明したが。

phantomJsの​​の実装がtweenJsでうまく動作しないという根本的な原因があります。ファントムによってコールバックに返された数値はUNIXエポック番号です(小数点以下は秒数)。tweenJsはDOMHighResTimeStampを返します(performance.now()から取得します。プロセス開始時にゼロから開始します)。エポック番号は常にトゥイーンの終了時刻よりもはるかに高いので、すべての更新はトゥイーンの終わりとみなされ、TWEEN.updateが次のサイクルにスムーズしてブロックされます。

それを修正する方法はpage.injectJsを使用して、ファントムの​​implimentationを上書きするために、performance.now pollyfil含め、ポリフィルを注入することです。ここで

を注射する必要のあるコード(またはSTが良い)である...

要求アニメーション-frame.js

// Include a performance.now polyfill 
var now = (function() { 
    // In node.js, use process.hrtime. 
    if (this.window === undefined && this.process !== undefined) { 
     now = function() { 
     var time = process.hrtime(); 

     // Convert [seconds, microseconds] to milliseconds. 
     return time[0] * 1000 + time[1]/1000; 
     }; 
    } 
    // In a browser, use window.performance.now if it is available. 
    else if (this.window !== undefined && 
     window.performance !== undefined && 
     window.performance.now !== undefined) { 

     // This must be bound, because directly assigning this function 
     // leads to an invocation exception in Chrome. 
     now = window.performance.now.bind(window.performance); 
    } 
    // Use Date.now if it is available. 
    else if (Date.now !== undefined) { 
     now = Date.now; 
    } 
    // Otherwise, use 'new Date().getTime()'. 
    else { 
     now = function() { 
     return new Date().getTime(); 
     }; 
    } 
    return now 
    })(); 

// http://paulirish.com/2011/requestanimationframe-for-smart-animating/ 
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating 

// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel 

// MIT license 

// Adapted to shim floating point milliseconds since the page was 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 

}()); 

、ここでファントムに置くためのコードでありますそれを注入する外部のコンテキスト...あなたの質問の文脈では

page.onInitialized = function() { 
    page.injectJs('request-animation-frame.js'); 
}; 

...この場合

/** 
* Adjusted by 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 from 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 for page.open not hooking into phantom.onError 
    setTimeout(function() { 
    if (status !== "success") { 
     exitPhantom('Error: ' + status); 
     throw new Error("Unable to 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); 

}); 

は、resourceTimeout機能が宣伝通りに動作し、過負荷に長い時間と同様のアニメーション技術を使用して任意のページから保護しますうまく動作します。

+0

"https://waffles.ch"でこのスクリプトをテストしましたか?それは私のために働いていない。私が 'phantomjs script.js https:// waffles.ch'でコンソールを使用しても、それはまだハングアップします。 Phantomj.exeはコンソール/ Webページを閉じた後でも閉じず、メモリの使用量が増え続けます。私は 'page.open'に詰まっていると思うので、それに含まれているコードは読んでいません。 –

+0

はい、ロード・コールバックはそれを行う場所ではありません。 [onLoadStarted](http://phantomjs.org/api/webpage/handler/on-load-started.html)コールバックからタイムアウトを設定できますが、resourceTimeoutと同じ問題があります。バグがあります。最大約1.6秒の時間を設定するとうまくいきますが、それ以上のことは興味を失います。 –

+0

@ turrican_34、私は根本的な原因を理解し、私の答えを更新しました。 –

関連する問題