2016-04-14 83 views
1

這個問題是關於一個履帶在node.js。 A start_url給出了他抓取URL的地方,並將它們「推送」給了一個。 json -file(output.json)。 目前,他只使用start_url運行請求功能,並將收集的URL保存在output.json中。我想,他通過與第一收集網址替換start_url使用保存的網址,並再次收集鏈接...等等...iterate node.js請求功能

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

var start_url = ["http://stackoverflow.com/"] 

var req = function(url){ 
    request(url, function(error, response, html){ 
     var $ = cheerio.load(html); 

     var data = []; 

     $("a").each(function() { 
      var link = $(this); 
       var exurls = {exurl: new Array(link.attr("href"))} 

       data.push(exurls); 

       // Queue "exurls" for "start_url" and call the same function with the new URL (endless loop) 
       // save to "output.json" from time to time, so you can stop it anytime 
     }); 

     fs.writeFile("output.json", JSON.stringify(data, null, 4), function(err){ 
      if(err){ 
       console.log(err); 
      } else { 
       console.log("File successfully written!"); 
      } 
     }); 
    }); 
} 
for (var i = 0; i < start_url.length; i++){ 
    req(start_url[i]); 
} 
+0

我不明白你怎麼想改變你給的代碼:它似乎已經在按你的要求工作:它將所有找到的鏈接排隊,並用找到的URL調用函數('req()')... – MarcoS

+0

@MarcoS:現在,他使用start_url運行請求函數一次,創建.json文件並停止。 –

+0

......並且你要求... – MarcoS

回答

2

所以你可以做的是使函數調用遞歸。下面的例子應該工作:

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

 
var start_url = ["http://stackoverflow.com/"] 
 

 
var req = function(url){ 
 
    var count = 0; 
 
    
 
    request(url, function(error, response, html){ 
 
    var $ = cheerio.load(html); 
 

 
    $("a").each(function() { 
 
     var link = $(this); 
 
     var exurls = {exurl: new Array(link.attr("href"))} 
 

 
     start_url.push(exurls); 
 

 
     // Queue "exurls" for "start_url" and call the same function with the new URL (endless loop) 
 
     // save to "output.json" from time to time, so you can stop it anytime 
 
    }); 
 

 
    try { 
 
     fs.writeFileSync("output.json"); 
 
     console.log("File successfully written!"); 
 
    }catch(err){ 
 
     console.log(err); 
 
    } 
 
     
 
     ++count; 
 
     
 
     if(start_url.length > count) { 
 
     req(start_url[count]); 
 
     } 
 
    }); 
 
} 
 

 
return req(start_url[0]);

這裏的問題是,你完全重寫每次文件。如果這種情況持續一段時間,你將耗盡內存。另一種選擇是創建一個寫流

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

 
    var start_url = ["http://stackoverflow.com/"] 
 
    
 
    var wstream = fs.createWriteStream("output.json"); 
 

 
    var req = function(url){ 
 
     
 
     request(url, function(error, response, html){ 
 
     var $ = cheerio.load(html); 
 

 
     $("a").each(function() { 
 
      var link = $(this); 
 
      var exurls = {exurl: new Array(link.attr("href"))} 
 

 
      start_url.push(exurls); 
 

 
      // Queue "exurls" for "start_url" and call the same function with the new URL (endless loop) 
 
      // save to "output.json" from time to time, so you can stop it anytime 
 
      wstream.write('"'+ exurls + '",'); 
 
     }); 
 
      
 
     start_url.shift(); 
 
     if(start_url.length > 0) { 
 
      return req(start_url[0]); 
 
     } 
 
      
 
      wstream.end(); 
 
     }); 
 
    } 
 

 
    req(start_url[0]);

編輯:切換到基本的隊列,以戰鬥的記憶問題



+0

謝謝。我更喜歡你的第二個解決方案,但是它顯示了一個錯誤......我沒有足夠的內存...... –

+0

這可能是因爲你正在推動'start_url'。變量完全保留在內存中,所以你很快就會耗盡內存。你需要考慮創建一個隊列。我編輯了我的回覆,現在它只是從第一個元素'start_url'繼續抓取,並在每次迭代後移除第一個元素。由於您在每次迭代中最有可能添加多個項目,因此這段時間仍然無法工作。但嘗試一下 – aray12

+0

似乎內存問題是固定的(至少...),但現在我與cheerio'cheerio \ lib \ parse.js:55'發生衝突。爲什麼不讀取output.json(同時)並且每次訪問下一個鏈接。感謝你的付出! –