3

这是一个有点棘手的问题。

我对 javascript 非常熟悉,但是我在一个使用 PhantomJS 和 CasperJS 自动抓取网站的项目中。这些对我来说是全新的主题。

我能够弄清楚如何使用 Casper 和导航、登录页面等,但是它很笨拙,因为一般流程似乎是:

casper.start('http://google.fr/');

casper.then(function() {
    this.echo("I'm in your google.");
});

casper.then(function() {
    this.echo('Now, let me write something');
});

casper.then(function() {
    this.echo('Oh well.');
});

casper.run();

我的问题是我想对网站做各种各样的事情,这取决于从中获得的数据。我不能预先布局导航序列,也不能让它改变。我希望这是有道理的。

为了解决这个问题,我创建了一个带有内置函数的 Javascript Navigator 对象。我的一般概念是:

navigator.logIn(function() 
{
  navigator.actionA(parameters, function() 
  {
    if (navigator.data.a == navigator.data.b) {
      navigator.actionB();
    } else {
      navigator.actionC();
    }
  });
});

并且嵌入在这些函数中的每一个函数中都将是 casper 函数。

这是我的实际代码的缩短版本,并且事情开始变得时髦:

var casper = require('casper').create({
    clientScripts:  [ 'jquery.min.js' ],
    onError: function(self, m) {  
        console.log('FATAL:' + m);
        self.exit();              
    },
});

var navigator = new _Navigator();

function _Navigator() { }

_Navigator.prototype.logIn = function(aCallback)
{
  var self = this;

  casper.start('https://website/login.asp', function() 
  {
    if (1 == 1) {
      this.evaluate(function() {
        $("input[name=blah]").val('blahblah');
      });

      // ... A LOT MORE CODE
      aCallback();
    }
  });  
}

_Navigator.prototype.search = function(aDataSet, aCallback)
{
  var self = this;

  console.log('this works');
  casper.then(function(){
    console.log('this works');
  });

  var firstName = 'foobar';

  casper.then(function(){
    console.log('this works');
    this.evaluate(function()
    {
      console.log('this no longer works!!');
      $('input[id=blah]').val(firstName);
      aCallback();
    });
  });
}

navigator.logIn(function() {
  // LOG IN RUNS, AND CALLS BACK SUCCESSFULLY...
  navigator.search({'dataset'}, function() 
  {
    console.log('This never runs');
  });
});

casper.run();

你会注意到在 navigator.login 函数中,我调用了 casper.start(); 在这种情况下,评估函数可以正常工作,但是我在该 casper.start(); 中执行了一个回调函数;在我的回调中,我调用了下一个函数 navigator.search,我想它在技术上仍在 casper.start 中执行?

当我尝试在第一个回调函数调用的这个新函数中运行 casper.evaluate 时,除了 casper.evaluate 不再起作用之外,一切似乎都表现良好!它似乎吃掉了这个功能,而不是打印任何控制台日志或任何东西。

我已经尝试了一切。我不确定如何正确执行此操作。有人对我做错了什么有任何建议吗?谢谢。

4

2 回答 2

4

我知道这已经很老了,但是:这里发生的事情是两个问题的结合:

  • casper.evaluate()似乎吃掉了当前堆栈中的所有错误 -onError不会从.evaluate()回调内部运行。

  • .evaluate中使用的函数不是标准闭包——它们是沙盒的,并且无法访问其范围之外的变量,除非作为显式参数传递给casper.evaluate. 因此,在您调用的评估函数中,范围内aCallback()没有aCallback,并且该函数将失败(静默)并带有ReferenceError.

于 2013-09-10T23:04:04.217 回答
0

casper.evaluate() 是无头浏览器会话的窗口。传递给评估的函数中发生的任何事情都不会出现在本地控制台上。但是,您可以通过设置侦听器记录从评估返回的任何值或打印所有输出:

  casper.on('remote.message', function(message) {
    console.log(message);
  });
于 2014-01-20T05:10:35.027 回答