How to stop a loop when clicking asynchronously in CasperJS

五迷三道 提交于 2019-12-11 13:16:14

问题


I'm crawling multiple pages using CasperJS, but I got stuck.

The maximum number of pages are 200 but I want to stop the execution if the XPath below doesn't exist (for a page before the 200th).

How can I set up i variable?

var casper = require('casper').create();
var x = require('casper').selectXPath;

for (var i=1; i <=200; i++) {
    casper.wait(6000, function() {

        casper.thenClick(x('//*[@id="mArticle"]/div[2]/a['+i+']'), function (){
            console.log('Searching dic');
            words = words.concat(this.evaluate(getWords));
        });

    });
}

回答1:


CasperJS provides the exists() function. So, you can rewrite your code like this:

for (var i=1; i <=200; i++) {
    (function(i){
        casper.wait(6000, function() {
            var button = x('//*[@id="mArticle"]/div[2]/a['+i+']');
            if (!this.exists(button)) {
                this.echo(i + " not available");
                return; // the following `thenClick()` is not executed
            }
            this.thenClick(button, function (){
                console.log('Searching dic');
                words = words.concat(this.evaluate(getWords));
            });
        });
    })(i);
}

I've also added an IIFE, so that you have the correct i inside of the callback. For more information, see JavaScript closure inside loops – simple practical example.

This works, but it is not very efficient if one would assume that if link 100 is not there, then link 101 and 102 etc. are also not there. You would wait a lot (6 seconds times 100). In that case you need to do this recursively, because of the asynchronous nature of CasperJS:

function execOnce(casper, i, max){
    // end condition
    if (i === max) {
        return;
    }
    casper.wait(6000, function() {
        var button = x('//*[@id="mArticle"]/div[2]/a['+i+']');
        if (!this.exists(button)) {
            this.echo(i + " not available");
            return;
        }
        this.thenClick(button, function (){
            console.log('Searching dic');
            words = words.concat(this.evaluate(getWords));

            // recursive step
            execOnce(this, i+1, max);
        });
    });
};

casper.start(url);

// start the recursive chain
casper.then(function(){
    execOnce(this, 1, 200);
});

casper.run();

Note that now that you have it recursively, you can define a proper end condition by explicitly looking on the page what's there and what isn't.



来源:https://stackoverflow.com/questions/32423373/how-to-stop-a-loop-when-clicking-asynchronously-in-casperjs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!