如何在casperjs中循环

时间:2013-09-16 18:51:00

标签: javascript phantomjs casperjs

我试图点击“下一个”按钮N次并每次抓取页面源。我知道我可以在远程网站上运行任意函数,所以我只使用远程函数nextPage()而不是click()我如何运行以下任意次数:

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

casper.start('http://www.example.com', function() {

    this.echo(this.getHTML());
    this.echo('-------------------------');

    var numTimes = 4, count = 2;

    casper.repeat(numTimes, function() {
        this.thenEvaluate(function() {
            nextPage(++count);
        });

        this.then(function() {
            this.echo(this.getHTML());
            this.echo('-------------------------');
        });
    });

});

'我'这是我尝试在javascript for循环中使用的索引。

所以tl;博士:我想舔'下一个',打印页面来源,点击'下一步',打印页面来源,点击'下一步'...继续N次。

3 个答案:

答案 0 :(得分:7)

首先,您可以将值传递给远程页面上下文(即thenEvaluate函数,如下所示:

    this.thenEvaluate(function(remoteCount) {
        nextPage(remoteCount);
    }, ++count);

但是,Casper#repeat可能不适合在此处使用,因为循环不会等待每个页面加载然后捕获内容。

您可能更愿意设计基于事件的链接。

代码的工作流程是:

  1. 拥有一个全局变量(或至少是下面提到的函数可访问的变量)来存储countlimit

  2. 收听load.finished事件并在此处抓取HTML,然后调用下一页。

  3. 简化代码可以是:

    var casper = require('casper').create();
    
    var limit = 5, count = 1;
    
    casper.on('load.finished', function (status) {
        if (status !== 'success') {
            this.echo ("Failed to load page.");
        }
        else {
            this.echo(this.getHTML());
            this.echo('-------------------------');
        }
    
    
    
        if(++count > limit) {
            this.echo ("Finished!");
    
        }
        else {
            this.evaluate(function(remoteCount) {
                nextPage(remoteCount);
                // [Edit the line below was added later]
                console.log(remoteCount);
                return remoteCount;
            }, count);
    
        }
    
    });
    
    casper.start('http://www.example.com').run();
    
      

    注意:如果您使用高负载的JS进程页面等,您可能还需要在调用nextPage之前添加wait

    this.wait( 
       1000, // in ms
       function () {
            this.evaluate(function(remoteCount) {
                nextPage(remoteCount);
            }, count);
       }
    );     
    
      

    [EDIT ADDED]以下事件监听器将帮助您进行调试。

    // help is tracing page's console.log 
    casper.on('remote.message', function(msg) { 
        console.log('[Remote Page] ' + msg); 
    }); 
    
    // Print out all the error messages from the web page 
    casper.on("page.error", function(msg, trace) { 
        casper.echo("[Remote Page Error] " + msg, "ERROR"); 
        casper.echo("[Remote Error trace] " + JSON.stringify(trace, undefined, 4)); 
    });
    

答案 1 :(得分:4)

您可以尝试使用Casper#repeat

在大多数情况下,这应该是你想要的:

var numTimes = 10, count = 1;

casper.repeat(numTimes, function() {
    this.thenEvaluate(function(count) {
        nextPage(count);
    }, ++count);

    this.then(function() {
        this.echo(this.getHTML());
        this.echo('-------------------------');
    });
});

答案 2 :(得分:1)

var global_page_links = [];

casper.then(function(){
    for(var i=1; i<=5; i++){    
        // you just add all your links to array, and use it in casper.each()
        global_page_links.push(YOUR_LINK);
    }

    this.each(global_page_links, function(self, link) {
        if (link){
            self.thenOpen(link, function() {
                console.log("OPENED: "+this.getCurrentUrl());
                // do here what you need, evaluate() etc.
            });
        }
    });
});

这是问题的答案,如何在casperjs中使用for()来启动多个链接