我正在尝试使用Node构建基本的webcrawler。我已经尝试了很多我能找到的爬虫模块,而且它们都没有对我有用,所以我想我会尝试自己动手。基本上,我正在使用“请求”模块,并递归调用我在页面上找到的每个链接的“获取”函数[请求]。
它似乎运行良好,在100页后,内存使用率仍然很低,但在大约14页之后,我收到一个Node警告,指出最大事件发射器和可能的内存泄漏。
这是一种安全的方式来编写网络浏览器吗?有什么我需要考虑的吗?有没有更好的方法呢?
谢谢!
更新:以下代码:
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 :(得分:2)
对于给定的事件发射器,您正在达到节点的非常保守/低阈值max event listeners。最有可能的是,您的代码中有一个错误,您可以将侦听器反复添加到可以重用它们的同一个发射器中。您需要发布代码以便我们对其进行分析,但是您有合理的需要增加此值,或者您错误地将冗余侦听器添加到同一个发射器。
您可能还想了解maxSockets参数,但可能无法对其进行调整,因为这可能会将您的代码从行为良好的抓取工具转移到令人讨厌的拒绝服务机器人。