2012-09-23 62 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"} 

所以,你看,它調用幻影回調函數用空(在評價函數的第二個參數)參數,但它不執行第一個參數(我的計算器函數,它打印迭代步驟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和節點之間的橋樑。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"); 
+1

的phantomjs節點橋的最新版本應該返回一個承諾,而不是依靠回調函數。 –

+0

這真的對我有幫助,謝謝 –

+0

嗯,我在'evaluate'函數內部嘗試了一些東西,失去了大約6個小時......如果裏面還有另一個函數,或者任何非原始類型,它甚至不會啓動函數執行...一件重要的事情。 **不要忘記閱讀文件** –

2

以下爲我工作,以評估頁面:

page.evaluate(function(s) { 
    return document.querySelector(s) 
}, 'body').then(res => { 
    console.log(res) 
})