2012-09-23 7 views
11

PhantomJSノードモジュール(https://github.com/sgentle/phantomjs-node)を使用してFacebookページをスクラップしていますが、そのページを評価しようとすると、渡された関数は評価されません。スタンドアロンのスクリプトで実行して、Nodeインタプリタで実行すると、Express.jsアプリケーションの同じコードが機能しません。Phantomjsはpage.evaluate関数で関数を実行しません

これは私のコード

facebookScraper.prototype.scrapeFeed = function (url, cb) { 
    f = ':scrapeFeed:'; 

    var evaluator = function (s) { 
     var posts = []; 

     for (var i = 0; i < FEED_ITEMS; i++) { 
      log.info(__filename+f+' iterating step ' + i); 
      log.info(__filename+f+util.inspect(document, false, null)); 
     } 

     return { 
      news: posts 
     }; 
    } 

    phantom.create(function (ph) { 
     ph.createPage(function (page) { 
      log.fine(__filename+f+' opening url ' + url); 
      page.open(url, function (status) { 
       log.fine(__filename+f+' opened site? ' + status); 
       setTimeout(function() { 
        page.evaluate(evaluator, function (result) { 
         log.info(__filename+f+'Scraped feed: ' + util.inspect(result, false, null)); 
         cb(result, ph); 
        }); 
       }, 5000); 
      }); 
     }); 
    }); 
}; 

私が手に出力されます:

{"level":"fine","message":"PATH/fb_regular.js:scrapeFeed: opening url <URL> ","timestamp":"2012-09-23T18:35:10.151Z"} 
{"level":"fine","message":"PATH/fb_regular.js:scrapeFeed: opened site? success","timestamp":"2012-09-23T18:35:12.682Z"} 
{"level":"info","message":"PATH/fb_regular.js:scrapeFeed: Scraped feed: null","timestamp":"2012-09-23T18:35:12.687Z"} 

だから、あなたが見るように、それはヌルでファントムコールバック関数(評価関数の2番目のパラメータ)を呼び出します最初のパラメータは実行されません(私の評価関数は、反復ステップXを出力します)。

誰でも問題の原因を知ることができます。

答えて

23

使用しているPhantomJSのバージョンは不明ですが、バージョン1.6のドキュメントでは、評価されたスクリプト内のログには含まれているページに結果が記録されます。あなたのコンソールにはログインしません。あなたがページonConsoleMessageイベントへのロギングをバインドする必要があることを取得するには、次の結果が利用可能でないためとして

page.onConsoleMessage = function (msg) { console.log(msg); }; 

:page.evaluate機能はそれほどのような引数を取りに - 最初のものは、実行する機能であり、残りはその関数への入力として渡されます。結果は直接返されます。

var title = page.evaluate(function (s) { 
    return document.querySelector(s).innerText; 
}, 'title'); 
console.log(title); 
9

evaluateを含む環境で定義された変数のいずれもcbあるいはphantomオブジェクトまたはユーザーが定義した可能性のある機能を含む、利用できないことを意味し、サンドボックスモードで実行されます。

evaluateの追加引数として明示的に情報をサンドボックスにトンネリングできます。

page.evaluate(function(cb){...}, cb); 
4

PhantomJS」page.evaluate()機能は、DOMのコンテキスト(ページコンテキスト)への扉です。この関数を使用してDOMにアクセスすることは可能です。関数はサンドボックス化されているので、その外部で定義された変数を使用することはできず、明示的に渡す必要があります。

注:そこかかわらず、内外に渡すことができるかの限界(docs)です引数はとevaluate関数に戻り値は、単純なプリミティブオブジェクトでなければなりません。経験則:JSONを使ってシリアル化できるのであれば問題ありません。

クロージャ、関数、DOMノードなどではありません!

phantomjs-nodeは、PhantomJSとノードの間のブリッジです。phantomJS自体とは少し異なるAPIを持っています。 PhantomJSで同期している関数は、phantomjs-nodeでは何も返しませんが、結果が渡されるコールバックをとります。コールバックは外部コンテキストで実行され、サンドボックス化されません。

引数は、この方法で渡すことができます。

page.evaluate(function(arg1, arg2){ 
    // use arg1 and arg2 in the page 
    // return `result` 
}, function(result){ 
    // use `result` in the node context 
}, "some arg1", "another arg"); 
+1

phantomjsノードブリッジの最新バージョンではなく、約束を返す必要がありますコールバック関数に頼っています。 –

+0

これは本当に助けてくれました。ありがとうございます –

+0

'evaluate'関数の中でいくつかのことを試してみると約6時間かかります...その中に別の関数がある場合や、何か非プリミティブ型の場合は関数の実行を開始しません...一つの重要なこと。 **ドキュメントを読むことを忘れないでください** –

2

次のページを評価するために私のために働いた:

page.evaluate(function(s) { 
    return document.querySelector(s) 
}, 'body').then(res => { 
    console.log(res) 
}) 
関連する問題