【问题标题】:How to stop a loop when clicking asynchronously in CasperJS在 CasperJS 中异步单击时如何停止循环
【发布时间】:2015-09-06 12:06:36
【问题描述】:

我正在使用 CasperJS 抓取多个页面,但我卡住了。

最大页数为 200,但如果下面的 XPath 不存在,我想停止执行(对于第 200 页之前的页面)。

如何设置i变量?

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));
        });

    });
}

【问题讨论】:

  • 你可以用break;转义循环
  • @DanielCheung 你会把它放在哪里?
  • 除了发明时间机器之外,您无法停止循环,因为它已经在 6 秒前运行。你需要重新思考逻辑。
  • 你把它放在 if 语句中?
  • @DanielCheung 你会把它放在哪里?你知道主逻辑是异步运行的吗?

标签: javascript if-statement for-loop xpath casperjs


【解决方案1】:

CasperJS 提供了exists() 函数。所以,你可以像这样重写你的代码:

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);
}

我还添加了一个 IIFE,以便您在回调中拥有正确的 i。如需更多信息,请参阅JavaScript closure inside loops – simple practical example

这可行,但如果假设链接 100 不存在,那么链接 101 和 102 等也不存在,则效率不高。你会等待很多(6 秒乘以 100)。在这种情况下,由于 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();

请注意,现在您已经递归了,您可以通过显式查看页面上的内容和不存在的内容来定义正确的结束条件。

【讨论】:

  • 感谢您的回答!我得到了这个,我注意到你在 if 语句下错过了“else”,但我真的很感激
  • 缺少else是故意的,因为我想减少JavaScript回调的嵌套,但我确实忘记了return语句。
  • 非常感谢您阅读我的问题 2...(已编辑问题)
  • 答案已经很大了,我不明白你在问什么。当已有答案时,请不要编辑您的问题以提出后续问题。您可以发布一个新问题,其中包含您的问题的完整描述以及您想要完成的任务。然后,您可以包含指向上一个问题的链接。
  • 哦,对不起,我会记住你的建议。我是这项服务的新手。我会提出一个新问题:)
猜你喜欢
  • 2021-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多