15

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

これは私のコードです

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"}

ご覧のとおり、null 引数を指定してファントム コールバック関数 (evaluate 関数の 2 番目のパラメーター) を呼び出しますが、最初のパラメーター (反復ステップ X を出力する私の評価関数) は実行しません。

誰が問題が何であるか知っていますか?

4

5 に答える 5

28

使用している 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);
于 2012-09-23T19:36:02.207 に答える
10

evaluateはサンドボックス モードで実行されます。つまり、含まれている環境で定義されている変数はcbphantomオブジェクトや定義済みの関数を含めて使用できません。

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

page.evaluate(function(cb){...},  cb); 
于 2012-11-29T09:46:29.953 に答える
5

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

注:関数への引数と戻り値はevaluate、単純なプリミティブ オブジェクトでなければなりません。経験則: JSON 経由でシリアル化できる場合は問題ありません。

クロージャ、関数、DOM ノードなどは機能しません!

phantomjs-nodeは PhantomJS と node.js の間のブリッジであり、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");
于 2015-07-07T07:33:58.677 に答える
0
于 2013-04-06T14:48:51.807 に答える