2013-09-16 38 views
4

我試圖點擊一個'下一個'按鈕N次並且每次抓取頁面源。我明白,我可以運行在遠程站點上的任意功能,所以不是點擊()我只需要使用遙控功能下一頁()如何運行下面的任意次數:如何在casperjs中循環

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循環中使用。

So tl; dr:我想舔'下一個',打印頁面源代碼,點擊'下一步',打印頁面源代碼,點擊'下一步'...繼續N次。

回答

7

首先,您可以將值傳遞給遠程頁面的上下文(即到thenEvaluate功能是這樣的:

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

然而,Casper#repeat可能不是一個很好的函數,因爲循環不會等待每個頁面加載並捕獲內容。

你可能更願意設計一個基於事件的鏈接。

代碼的工作流將是:

  1. 有一個全局變量(或在-至少一個可變訪問下面提到的功能)來存儲countlimit

  2. 收聽load.finished事件並在此處獲取HTML,然後調用下一頁。

簡化代碼可以是:

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流程等的高負荷,你可能還需要調用之前下一頁添加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)); 
}); 
+0

非常感謝你的代碼sudipto。我幾乎在那裏,只有一個奇怪的問題。它適用於每一頁,但第二個。看起來nextPage函數在評估函數的第一次迭代中有一個空值?我不確定發生了什麼事。但這裏是代碼: http://pastebin.com/QJvA2nap 和這裏的輸出:http://pastebin.com/kKZHiLKM – Joe

+1

好的。首先添加這兩個事件監聽器: '//幫助正在跟蹤頁面的console.log casper.on('remote.message',function(msg){ console.log('[Remote Page]'+ msg); (「page.error」,函數(msg,trace)){casper.echo(「[Remote Page Error]」){ });' '{//打印出網頁中的所有錯誤消息 + msg,「ERROR」); casper.echo(「[Remote Error trace]」+ JSON.stringify(trace,undefined,4)); });' – sudipto

+1

上述2個事件偵聽器將偵聽遠程頁面錯誤和console.log通過JS在遠程頁面中調用(你可以從'evaluate'函數中調用它,現在,在'evaluate'函數中,在寫入之前'return remoteCount;'添加這行'console.log(remoteCount);'。這將顯示直接從頁面收到的值。在這種情況下也是如此,我們需要深入挖掘。 – sudipto

3

你可以嘗試使用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('-------------------------'); 
    }); 
}); 
+0

非常感謝你的幫助。我試着將頁面調整爲我的腳本,但我仍然無法將它轉到不同的頁面,每次都輸出相同的頁面。看起來nextPage(++ count)不會觸發。但nextPage(5)確實會觸發。看起來,我不能將變量傳遞給thenEvaluate函數,我一直試圖找出如何。也許這是我缺乏JavaScript知識,但沒有組合似乎爲我工作。 – Joe

+0

@hedix:內部評估中使用的變量'count'應該存在於遠程頁面作用域中,或者作爲參數通過評估函數傳遞。 – sudipto

+0

@sudipto是的,它看起來像我忘了把它作爲一個參數傳遞。感謝您指出了這一點。 – hexid

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推出幾個環節