我正在尝试使用 Node.js 构建一个基本的网络爬虫。我已经尝试了尽可能多的爬虫模块,但它们都不适合我,所以我想我会尝试自己动手。基本上,我正在使用“请求”模块,并为我在页面上找到的每个链接递归调用“请求”函数。
它似乎运行良好,在 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;
}
}