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

时间:2012-09-23 18:47:04

标签: javascript node.js phantomjs

我正在使用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函数中的第二个参数),但它不执行第一个参数(我的求值函数,它打印迭代步骤X)。 / p>

有谁知道问题是什么?

5 个答案:

答案 0 :(得分:26)

我不确定您使用的是哪个版本的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);

答案 1 :(得分:10)

evaluate以沙盒模式运行,这意味着包含环境中定义的变量都不可用,包括cb甚至phantom对象或您可能使用的任何函数定义了。

您可以将信息显式隧道传输到沙箱,作为evaluate的其他参数。

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

答案 2 :(得分: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");

答案 3 :(得分:2)

以下是我评估页面的方法:

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

答案 4 :(得分:0)

有人有一个评估块,里面只有一个console.log行,它永远不会执行,它并不总是沙盒问题。

请参阅链接:On PhantomJS I can't include jQuery and without jQuery I can't post form data