Node爬蟲之——使用async.mapLimit控制請求並發


一般我們在寫爬蟲的時候,很多網站會因為你並發請求數太多當做是在惡意請求,封掉你的IP,為了防止這種情況的發生,我們一般會在代碼里控制並發請求數,Node里面一般借助async模塊來實現。

1. async.mapLimit方法

mapLimit(arr, limit, iterator, callback)

arr中一般是多個請求的url,limit為並發限制次數,mapLimit方法將arr中的每一項依次拿給iterator去執行,執行結果傳給最后的callback;

2. async.mapLimit方法應用

下面是之前寫過的一個簡單的爬蟲示例,將爬取到的新聞標題和路徑保存在一個Excel表格中,限制並發數為3,代碼如下

webSpider.js:

//request調用url主函數 (mapLimit iterator)
function main(option, callback) {
	n++;
	timeline[option] = new Date().getTime();
	console.log('現在的並發數是', n, ',正在抓取的是', option);
	request(option, function(err, res, body) {
		if(!err && res.statusCode == 200){
			var $ = cheerio.load(body);
			$('#post_list .post_item').each(function(index, element) {
				// console.log(element);
				var item = [$(element).find('.post_item_body h3 a').text(),$(element).find('.post_item_body h3 a').attr('href')];
				dataArr[0].data.push(item);
			});
			console.log('抓取', option, '結束,耗時:', new Date().getTime()-timeline[option], '毫秒');
			n--;
			callback(null, 'done!');
		}else{
			console.log(err);
			n--;
			callback(err, null);
		}
	});
}

//限制請求並發數為3
async.mapLimit(options, 3, main.bind(this), function(err, result){
	if(err) {
		console.log(err);
	} else {
		fs.writeFile('data/cnbNews.xlsx', xlsx.build(dataArr), 'utf-8', function(err){
			if(err){
				console.log('write file error!');
			}else{
				console.log('write file success!');
			}
		});
	}
});

這里迭代器里面第二個參數callback(即請求每一條url完成之后的回調方法)是關鍵,沒有異常的情況下所有options中的url都請求完成之后會回調mapLimit方法的回調方法進行后續操作(如這里的生成文件),如果單條url請求異常,回調方法中會接收到err並報出錯誤,不能執行后續生成文件的操作。

async.mapLimit(options, 3, function(option, callback) {
	request(option, main);
	callback(null);
}, function(err, result) {
	if(err) {
		console.log(err);
	} else {
		console.log('done!');
	}
});

如上,網上有些資料中是在迭代器中request方法執行完成之后調用callback,因為request方法異步接收請求數據,這種寫法會使async.mapLimit方法limit參數無效,導致無法達到限制請求並發數的目的,這里需要注意下。

執行webSpider.js,

node webSpider.js

3. 總結

執行結果可以看到並發數依次增加,增加到3時不再繼續增加,等待前面一條請求執行完成后才會請求下一條,這樣的話,如果我們需要爬取1000條數據,就可以並發10條請求,慢慢爬完這1000個鏈接,這樣就不用擔心因並發太多被封IP這種情況發生了。完整代碼已上傳GitHub,有興趣去試試吧!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM