Как да прекъсна повторната функция на CasperJS, когато дадено условие е изпълнено?

Искам да знам дали мога да прекъсна casper.repeat цикъл.

Имам този скрипт, който прави това...:

Търси в Google агент 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();

person user215379    schedule 08.12.2014    source източник


Отговори (3)


Цикълът 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();

Във вашия случай вероятно е необходима глобална променлива, за да се проследи какво се намира във всяка итерация на "цикъл".

person Artjom B.    schedule 08.12.2014
comment
Благодаря за пояснението. Ще се опитам да адаптирам кода си. - person user215379; 08.12.2014
comment
страхотност!!! @Artjom: Изглежда, че всички въпроси за CasperJS и PhantomJS са отговорени от вас :-) - person Mandeep Singh; 09.11.2015
comment
@mandeep_m91 Е, не. Дори не е близо. Преброявам 28% от въпросите на CasperJS и 13% от въпросите за PhantomJS. Все още имам дълъг път за моите златни значки. - person Artjom B.; 09.11.2015
comment
@ArtjomB. добре, ти ми помогна много през последните няколко седмици. Наистина го оценявам. - person Mandeep Singh; 09.11.2015

Трябва да разберете работата на 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++;
    });     
});
person Arjun Nagathankandy    schedule 28.10.2016

Какво ще кажете за това?

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.

person Adam Witorean    schedule 12.10.2015