如何在满足条件时中断CasperJS的重复函数

How to break CasperJS' repeat function when a condition is fulfilled?

本文关键字:CasperJS 函数 中断 满足 条件      更新时间:2023-09-26

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

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

在谷歌上搜索特工 001、特工 002、特工 003、特工 004、特工

005、特工 006..... ....'直到特工 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();

repeat循环在导航开始之前就完成了。 repeat 通过在通过 casper.run 触发执行之前将所有迭代展开到队列中来立即执行。使用同步代码时,不能中断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();

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

你应该了解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;
};

从这里你可以看到,一旦重复被称为即重复(numTimes,你的函数(。

您可以将"then"参数视为您要传递的要重复的函数。因此,一旦调用发生,它将在 for 循环中工作。因此,在通话后中断重复是不可能的。在函数中使用要传递给重复的Casper.byPassIf Casper.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++;
    });     
});

这个怎么样?

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,则不会执行循环中的代码。