【问题标题】:How to break CasperJS' repeat function when a condition is fulfilled?满足条件时如何打破 CasperJS 的重复功能?
【发布时间】:2014-12-08 14:04:12
【问题描述】:

我想知道我是否可以打破 casper.repeat 循环。

我有这个脚本可以做到这一点..:

在 google 上搜索 agent 001、agent 002、agent 003、agent 004、agent 005、agent 006 .....'til agent 011。

我希望它在找到文本“詹姆斯邦德”后停止循环。

现在它找到并打印出来,但我不知道是否以及如何停止 casper.repeat 循环。

var casper = require("casper").create({
  clientScript: ["jquery.min.js"],
  verbose: true,
  logLevel: "info"
});
var mouse = require("mouse").create(casper);
var x = require('casper').selectXPath;
var webPage = require('webpage');
var page = webPage.create();

casper.on("remote.message", function(msg){
    this.echo("remote> " + msg);
    var test = msg;
    if( test.indexOf('James Bond') >= 0){
    casper.echo("Am Gasit James Bond");
}
});

casper.userAgent('Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36')
casper.start("https://www.google.com/ncr", function() {
      this.echo("\nINCEPUTUL INCEPUTULUI TITLUL PAGINII IN START (LINIA DE MAI JOS)\n"+this.getTitle()+"\n");
      }).viewport(1366,768);
casper.options.waitTimeout = 30000;
var variabila_mea = "agent ";
var numTimes = 11, count = 1;
casper.repeat(numTimes, function() {
if (count < 10) {
var i = "00"+count;
    casper.waitForSelector(x('//*[@id="gbqfq"]'), function(){
        this.evaluate(function(count, variabila_mea, i, numar) {
            document.getElementsByClassName('gbqfif')[0].value=variabila_mea+i;
            document.forms[0].submit();
            nextPage(count);
        }, ++count,variabila_mea , i,"00000");
        console.log(variabila_mea);

        casper.waitForSelector(x('//*[@id="gbqfq"]'), function(){
            var inputValue = casper.evaluate(function () {
                console.log("\n\n\n"+document.getElementsByClassName('rc')[0].outerHTML+"\n\n\n");
            });
        });

        casper.wait(1000, function(){
        console.log("\n_____________________");
        casper.capture('aa'+i+'.png');
        console.log("_____________________\n");
        });
    });

    } else if (count < 100 && count > 9) {
    var i = "0"+count;
    casper.waitForSelector(x('//*[@id="gbqfq"]'), function(){
        this.evaluate(function(count, variabila_mea, i, numar) {
            document.getElementsByClassName('gbqfif')[0].value=variabila_mea+i;
            document.forms[0].submit();
            nextPage(count);
        }, ++count,variabila_mea , i,"00000");
        console.log(variabila_mea);

        casper.waitForSelector(x('//*[@id="gbqfq"]'), function(){
            var inputValue = casper.evaluate(function () {
                console.log("\n\n\n"+document.getElementsByClassName('rc')[0].outerHTML+"\n\n\n");
            });
        });

        casper.wait(1000, function(){
        console.log("\n_____________________");
        casper.capture('aa'+i+'.png');
        console.log("_____________________\n");
        });
    });

    } else {
    var i = count;
    casper.waitForSelector(x('//*[@id="gbqfq"]'), function(){
        this.evaluate(function(count, variabila_mea, i, numar) {
            document.getElementsByClassName('gbqfif')[0].value=variabila_mea+i;
            document.forms[0].submit();
            nextPage(count);
        }, ++count,variabila_mea , i,"00000");
        console.log(variabila_mea);

        casper.waitForSelector(x('//*[@id="gbqfq"]'), function(){
            var inputValue = casper.evaluate(function () {
                console.log("\n\n\n"+document.getElementsByClassName('rc')[0].outerHTML+"\n\n\n");
            });
        });

        casper.wait(1000, function(){
        console.log("\n_____________________");
        casper.capture('aa'+i+'.png');
        console.log("\n_____________________");
        });
    });

    }

});
casper.run();

【问题讨论】:

    标签: javascript casperjs


    【解决方案1】:

    repeat 循环在导航开始之前就完成了。在casper.run 触发执行之前,通过将所有迭代展开到队列中立即执行repeat。当使用同步代码时,您不能中断repeat 循环,当实际安排步骤时,您当然不能中断repeat 循环。但是您仍然可以通过使用递归来实现您想要实现的目标。

    你需要将你的循环体定义为一个函数,并使其尾递归。

    function loopBody(index, numTimes){
        if (conditionFailed || index >= numTimes) {
            return;
        }
        this.then(function(){
            // do something useful
        });
        this.then(function(){
            loopBody.call(this, index+1, numTimes);
        });
    }
    
    casper.start(url).then(function(){
        loopBody.call(this, 0, numTimes);
    }).run();
    

    在您的情况下,可能需要一个全局变量来跟踪在每个“循环”迭代中发现的内容。

    【讨论】:

    • 感谢您的澄清。我会尝试调整我的代码。
    • 太棒了!!! @Artjom:看起来你回答了所有 CasperJS 和 PhantomJS 问题:-)
    • @mandeep_m91 好吧,不。差远了。我统计了 28% 的 CasperJS 问题和 13% 的 PhantomJS 问题。我的金牌还有很长的路要走。
    • @ArtjomB。好吧,在过去的几周里,你对我帮助很大。真的很感激。
    【解决方案2】:

    你应该了解casper.repeat();的工作原理 重复的内部结构如下。取自 git hub

    /**
     * Repeats a step a given number of times.
     * @param  Number    times  Number of times to repeat step
     * @aram   function  then   The step closure
     * @return Casper
     * @see    Casper#then
     */
    Casper.prototype.repeat = function repeat(times, then) {
        "use strict";
        for (var i = 0; i < times; i++) {
            this.then(then);
        }
        return this;
    };
    

    从这里你可以看到,一旦调用repeat,即repeat (numTimes,your function)。

    您可以将“then”参数视为您传递的要重复的函数。因此,一旦发生调用,它将在 for 循环中工作。所以在通话后打破重复是不可能的。在传递给重复的函数中使用Casper.byPassIfCasper.byPassUnless 以绕过执行。 使用它可以跳过函数内的步骤。这意味着重复只有在达到结束计数后才会停止。但它不会执行任何步骤,因为您正在绕过具有上述功能的那些。对旁路功能的进一步解释不在此问题范围内。其实这是解决方法,你可以试试。希望它会有所帮助。如果需要进一步澄清,请随时询问。享受!!!

    示例下面的循环将执行 10 次,但只打印 1 到 5。

    var i=1;
    loopcount=10
    casper.repeat(loopCount, function() {
        casper.thenBypassIf(function() {
            return i >5;
        }, 1);
        casper.then(function() {
            this.echo (i);
        });
        casper.then(function() {
            i++;
        });     
    });
    

    【讨论】:

      【解决方案3】:

      这个怎么样?

      casper.keep_looping = true;
      
      casper.repeat(some_counter, function() {
          if (casper.keep_looping)
          {
              if (i_no_longer_want_to_loop) {
                  casper.keep_looping = false;
              }
          }
      });
      

      既然没有办法打破 casper.repeat 循环(至少我在文档中没有找到它),那么也许避免执行循环内代码就足够了。上面的代码将运行循环,直到“some_counter”耗尽,但如果将“i_no_longer_want_to_loop”变量设置为true,则循环中的代码将不会执行。

      【讨论】:

        猜你喜欢
        • 2020-04-21
        • 2013-12-28
        • 2021-03-01
        • 1970-01-01
        • 2010-11-06
        • 2016-01-20
        • 1970-01-01
        • 1970-01-01
        • 2019-07-14
        相关资源
        最近更新 更多