2017-10-07 11 views
0

これは、ノードjsで書かれたWebスクレイピング・コードです。
キューに十分なURLがある場合、このコードは常に5つの同時リクエストを保持しますか?
コンソールに別の理由が表示されるのはなぜですか?
リミット・コンカレント・オペレーションnodejs

var request = require("request"); 
var cheerio = require("cheerio"); 
var fs = require('fs'); 

var concurrent_requests = 0; 
var queue = []; 
var baseUrl = "https://angularjs.org/"; 

function makeApiCall(url){ 
    if(url) { 
     queue.unshift(url); 
    } 
    if(concurrent_requests<5) { 
     var nextUrl = queue.pop(); 
     if(nextUrl) { 
      concurrent_requests++; 
      request(nextUrl, function (error, response, body) { 
       var invalidUrl; 
       concurrent_requests--; 
       if(body) { 
        var $ = cheerio.load(body); 
        var anchors = $("a"); 
        var data = ""; 
        for (var i = 0; i < anchors.length; i++) { 
         url = $(anchors[i]).attr("href"); 
         if(!url || url === "#" || url === "javascript:void(0)"){ 
          invalidUrl = true; 
         } 
         else{ 
          invalidUrl = false; 
         } 

         if (!invalidUrl) { 
          makeApiCall(url); 
          data += url + ", " + nextUrl + "\n"; 
         } 
        } 
        //console.log(data); 
        fs.appendFile('urls.csv',data, function (err) { 
         if (err) throw err; 
        }); 
       } 
       else{ 
        makeApiCall(); 
       } 
      }); 
     } 
    } 
    console.log(concurrent_requests); 

} 


makeApiCall(baseUrl); 
+1

のようなループを使用することは、一度に1つの要求を持っています。 –

+0

少し明確にしていただけますか? –

+0

答えを確認 –

答えて

1

Becoz、あなたは、if文で5以上のものを要求しないようにする条件を持っています。

IF(concurrent_requests < 5){

この解決策は、特定の再帰呼び出し後のスタックの上に行くようにスケーラブルではありません。

希望します。

+0

少し明確にしていただけますか? –

1

コンディションが 個未満の場合はif条件を使用してチェックします。しかし、覚えているのはifステートメント、 ループではありません。それは、それが一度だけ呼び出されることを意味します。

makeApiCall ファンクションへの再帰呼び出しを要求のコールバックにしています。要求のコールバックは、要求が満たされたときにのみ を実行します。

上記の2つの点を念頭に置いて、if条件でconcurrent_requests<5を呼び出して、リクエストメソッドを呼び出すと、プログラムが理想的になります。要求IDが満たされた後、リクエストのコールバックが実行されます。これは、ロジックの後にmakeApiCallを再度呼び出した後です。したがって、すべての呼び出しでは、要求を1回だけ呼び出してから解決するまで待ってから、次の要求に進むためにプログラムのみが処理されます。

あなたは同時リクエストをしたい場合は、この

function makeApiCall(url){ 
    if(url) { 
     queue.unshift(url); 
    } 
    // Use a loop here 
    while(concurrent_requests<5) { 
     var nextUrl = queue.pop(); 
     if(nextUrl) { 
      concurrent_requests++; 
      request(nextUrl, function (error, response, body) { 
       var invalidUrl; 
       concurrent_requests--; 
       if(body) { 
         ... 
         if (!invalidUrl) { 
          makeApiCall(url); 
          data += url + ", " + nextUrl + "\n"; 
         } 
        } 
        ... 
       } 
       else{ 
        makeApiCall(); 
       } 
      }); 
     } 
     else{ 
      // Remember to break out of loop when queue is empty to avoid infinite loop. 
      break; 
     } 
    } 
    console.log(concurrent_requests); 

} 
関連する問題