Phantomjs不会在page.evaluate函数中执行函数

我正在使用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参数的phantomcallback函数(evaluate函数中的第二个参数),但是它不执行第一个参数(我的计算器函数,它打印迭代步骤X)。

任何人都知道问题是什么?

我不确定你正在使用什么版本的PhantomJS,但是对于版本1.6以上的文档logging,评估脚本内部会logging结果到包含的页面中。 它不会login到您的控制台。 为了得到这个,你将不得不把日志logging绑定到onsole消息事件的页面上:

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

至于结果不可用:page.evaluate函数接受像这样的参数 – 第一个是要执行的函数,其余的是作为input传递给该函数。 结果直接返回:

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

evaluate是在沙箱模式下运行的,这意味着在包含环境中定义的variables都不可用,包括cb甚至phantom对象或您可能已经定义的任何函数。

您可以显式地将信息隧道作为额外的参数来evaluate

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

PhantomJS的page.evaluate()函数是DOM上下文(页面上下文)的大门。 只有通过这个函数才能访问DOM。 由于函数是沙盒,所以不能使用在其外部定义的variables,而必须显式地传递它们。 ( 文档 )有什么限制可以传入和传出:

注意: evaluate函数的参数和返回值必须是一个简单的原始对象。 经验法则:如果它可以通过JSON序列化,那么它是好的。

闭包,函数,DOM节点等不起作用!

phantomjs-node是PhantomJS和node.js之间的一个桥梁,因此与PhantomJS本身的API略有不同。 在PhantomJS中同步的函数不会在phantomjs-node中返回任何内容,而是在传入结果的地方进行callback。callback将在外部上下文中执行,而不是沙盒。

参数可以这样传递:

 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"); 

以下工作为我评估一个页面:

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

有人有一个只有一个console.log内线的评估块,它永远不会执行,它并不总是一个沙箱问题。

请参阅链接: 在PhantomJS我不能包括jQuery和没有jQuery我不能张贴表单数据