2013-03-20 85 views
0

我試圖建立一個基本的webcrawler使用節點。我已經嘗試了許多我能找到的爬蟲模塊,並且他們中的任何一個都不適合我,所以我想我會嘗試推出自己的爬蟲模塊。基本上,我正在使用「請求」模塊,並遞歸調用每個鏈接上的「獲取」函數[請求],我在頁面上找到。自定義NodeJS Webcrawler

這似乎運作良好,並經過100頁,內存使用率仍然較低,但經過約14頁,我得到一個節點警告有關最大事件發射器和一個可能的內存泄漏。

這是一個安全的方式去寫一個webcrawler?我需要考慮什麼嗎?有沒有更好的方法去解決它?

謝謝!

UPDATE:代碼如下:

var request = require('request'); 
var $  = require('jquery'); 
var _  = require("underscore"); 
var S  = require('string'); 
var jsdom = require('jsdom'); 

var startURL = 'http://www.cnn.com/sitemap/'; 
var host  = 'http://www.cnn.com'; 
var blocked  = []; 
var totalDepth = 1; 

var urls  = []; 
var ignored  = []; 
var results  = []; 
var counter  = 0; 

processURL(startURL,totalDepth); 

function processURL(url,depth) { 

    request(url, function (error, response, html) { 

     if (!error && response.statusCode == 200) { 

     var title = html.match("<title>(.*?)</title>"); 
      title=title ? title[1] : ''; 


     var myURL=url; 
     myURL = myURL.split(',').join(' '); 
     title = title.split(',').join(' '); 
     displayURL = myURL.replace(host,''); 
     results.push(myURL + ',' + title); 
     counter++; 

     if(results.length==100) { 
      saveResults(); 
     } 


     if(depth>0) { 
      jsdom.env({ 
       html: html, 
       scripts: ['http://code.jquery.com/jquery-1.7.min.js'] 
       }, function (err, window) { 
       var $ = window.jQuery; 
       if($!=undefined) { 
       $('a').each(function() { 
        var href=$(this).attr('href'); 
        href=fixURL(href); 
        if(checkURL(href)) { 
         addToQueue(href,depth-1);      
        } 
       }) 
       } 
      }); 
     } 
    } 
}); 
} 

var int=setInterval(function(){checkExit()},10000); 

function checkExit() { 

    if(results.length==0) { 
     process.exit(); 
    } 

    saveResults(); 

} 

function checkURL(url) { 

    if(url==undefined) return false; 
    if(url=='') return false; 
    if(url=='#') return false; 
    if(url=='') return false; 
    if(url=='/') return false; 
    if(S(url).startsWith('#')) return false; 
    if(url.indexOf('javascript')==0) return false; 

    if(url.indexOf("/")==0) { 
     url=host+url; 
    } 

    if(_.contains(urls,url)) {   
     return false; 
    } 

    if(_.contains(ignored,url)) {   
     return false; 
    }  

    $.each(blocked,function(i,d) { 
     if(S(url).contains(d)) { 
      ignored.push(url); 
      return false; 
     } 
    }) 

    if(url.indexOf('http')==0) { 
     if(S(url).startsWith(host)) { 
      return true; 
    } else 
      return false; 
    } 

    return true;     
} 

function addToQueue(url,depth) { 

    if(_.contains(urls,url)) {   
     return false; 
    } 

    if(url.indexOf("/")==0) { 
     url=host+url; 
    } 

    if(!validURL(url)) { 
     return; 
    } 

    processURL(url,depth); 
    urls.push(url); 

} 

function saveResults() { 
    var csv = ''; 
    $.each(results,function(i,d) { 
     csv+=d + '\n'; 
    }) 
    writeData(csv); 
    results = []; 
} 

function writeData(data) { 
    var fs = require('fs');  
    fs.appendFile(__dirname+'/results.csv', data, function(err) { 
     if(err) { 
      console.log(err); 
     } else { 
      console.log("******The file was saved!******");    
     } 
    }); 
} 

function validURL(value) { 
    var urlregex = new RegExp("^(http:\/\/www.|https:\/\/www.|ftp:\/\/www.|www.){1}([0-9A-Za-z]+\.)"); 
    if (urlregex.test(value)) { 
     return (true); 
    } 
    return (false); 
} 

function fixURL(url) { 
    if(url==undefined) return ''; 
    if(url.indexOf("/")==0) { 
     return host+url; 
    } else { 
     return url; 
    } 
} 
+0

發佈您的當前代碼。 – Blender 2013-03-20 02:57:05

+0

我認爲關於內存泄漏的更普遍的問題很有趣。你可能想把重點放在你的問題上:http://stackoverflow.com/questions/13983204/nodejs-warning-possible-eventemitter-memory-leak-detected-11-listeners-added – 2013-03-20 03:01:09

回答

2

你打的max event listeners節點的非常保守/低門檻對於一個給定事件發射器。最有可能的是,您的代碼中存在一個錯誤,您需要將監聽器反覆添加到同一個發射器,以便重複使用它們。您需要發佈您的代碼以便我們分析它,但是您有合理的需要增加此值,或者您錯誤地將冗餘偵聽器添加到同一個發射器。

您可能還想了解maxSockets參數,但可能不會對其進行調整,因爲這可能會將您的代碼從性能良好的爬網程序轉變爲惡意拒絕服務機器人。