中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

使用async、enterproxy控制并發(fā)數(shù)量的方法詳解

聊聊并發(fā)與并行

成都創(chuàng)新互聯(lián)公司服務(wù)項(xiàng)目包括下冶網(wǎng)站建設(shè)、下冶網(wǎng)站制作、下冶網(wǎng)頁(yè)制作以及下冶網(wǎng)絡(luò)營(yíng)銷(xiāo)策劃等。多年來(lái),我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,下冶網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到下冶省份的部分城市,未來(lái)相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

并發(fā),在操作系統(tǒng)中,是指一個(gè)時(shí)間段中有幾個(gè)程序都處于已啟動(dòng)運(yùn)行到運(yùn)行完畢之間,且這幾個(gè)程序都是在同一個(gè)處理機(jī)上運(yùn)行,但任一個(gè)時(shí)刻點(diǎn)上只有一個(gè)程序在處理機(jī)上運(yùn)行。

并發(fā)我們經(jīng)常提及之,不管是web server,app并發(fā)無(wú)處不在,操作系統(tǒng)中,指一個(gè)時(shí)間段中幾個(gè)程序處于已經(jīng)啟動(dòng)運(yùn)行到完畢之間,且這幾個(gè)程序都是在同一處理機(jī)上運(yùn)行,并且任一個(gè)時(shí)間點(diǎn)只有一個(gè)程序在處理機(jī)上運(yùn)行。很多網(wǎng)站都有并發(fā)連接數(shù)量的限制,所以當(dāng)請(qǐng)求發(fā)送太快的時(shí)候會(huì)導(dǎo)致返回值為空或報(bào)錯(cuò)。更有甚者,有些網(wǎng)站可能因?yàn)槟惆l(fā)出的并發(fā)連接數(shù)量過(guò)多而當(dāng)你是在惡意請(qǐng)求,封掉你的ip。

相對(duì)于并發(fā),并行可能陌生了不少,并行指一組程序按獨(dú)立異步的速度執(zhí)行,不等于時(shí)間上的重疊(同一個(gè)時(shí)刻發(fā)生),通過(guò)增加cpu核心來(lái)實(shí)現(xiàn)多個(gè)程序(任務(wù))的同時(shí)進(jìn)行。沒(méi)錯(cuò),并行做到了多任務(wù)的同時(shí)進(jìn)行

使用enterproxy控制并發(fā)數(shù)量

enterproxy是樸靈大大為主要貢獻(xiàn)的工具,帶來(lái)一種事件式編程的思維變化,利用事件機(jī)制解耦復(fù)雜業(yè)務(wù)邏輯,解決了回調(diào)函數(shù)耦合性的詬病,將串行等待變成并行等待,提升多異步協(xié)作場(chǎng)景下的執(zhí)行效率

我們?nèi)绾问褂胑nterproxy控制并發(fā)數(shù)量?通常如果我們不使用enterproxy和自制的計(jì)數(shù)器,我們?nèi)绻ト∪齻€(gè)源:

這種深層嵌套,串行的方式

 var render = function (template, data) {
 _.template(template, data);
 };
$.get("template", function (template) {
 // something
 $.get("data", function (data) {
 // something
 $.get("l10n", function (l10n) {
 // something
 render(template, data, l10n);
 });
 });
});

除去這種過(guò)去深層嵌套的方法,我們常規(guī)的寫(xiě)法的自己維護(hù)一個(gè)計(jì)數(shù)器

(function(){
 var count = 0;
 var result = {};
 
 $.get('template',function(data){
 result.data1 = data;
 count++;
 handle();
 })
 $.get('data',function(data){
 result.data2 = data;
 count++;
 handle();
 })
 $.get('l10n',function(data){
 result.data3 = data;
 count++;
 handle();
 })

 function handle(){
 if(count === 3){
  var html = fuck(result.data1,result.data2,result.data3);
  render(html);
 }
 }
})();

在這里,enterproxy就可以起到這個(gè)計(jì)數(shù)器的作用,它幫你管理這些異步操作是否完成,完成之后,他會(huì)自動(dòng)調(diào)用你提供的處理函數(shù),并將抓取到數(shù)據(jù)當(dāng)做參數(shù)傳遞過(guò)來(lái)

var ep = new enterproxy();
ep.all('data_event1','data_event2','data_event3',function(data1,data2,data3){
 var html = fuck(data1,data2,data3);
 render(html);
})

$.get('http:example1',function(data){
 ep.emit('data_event1',data);
})

$.get('http:example2',function(data){
 ep.emit('data_event2',data);
})

$.get('http:example3',function(data){
 ep.emit('data_event3',data);
})

enterproxy還提供了其他不少場(chǎng)景所需的API,可以自行學(xué)習(xí)下這個(gè)API enterproxy

使用async控制并發(fā)數(shù)量

假如我們有40個(gè)請(qǐng)求需要發(fā)出,很多網(wǎng)站可能會(huì)因?yàn)槟惆l(fā)出的并發(fā)連接數(shù)太多而當(dāng)你是在惡意請(qǐng)求,把你的IP封掉。
所以我們總是需要控制并發(fā)數(shù)量,然后慢慢抓取完這40個(gè)鏈接。

使用async中mapLimit控制一次性并發(fā)數(shù)量為5,一次性只抓取5個(gè)鏈接。

 async.mapLimit(arr, 5, function (url, callback) {
 // something
 }, function (error, result) {
 console.log("result: ")
 console.log(result);
 })

我們首先應(yīng)該知道什么是并發(fā),為什么需要限制并發(fā)數(shù)量,都有哪些處理方案。然后就可以去文檔具體看一下API如何使用。async文檔可以很好的學(xué)習(xí)這些語(yǔ)法。

模擬一組數(shù)據(jù),這里返回的數(shù)據(jù)是假的,返回的延時(shí)是隨機(jī)的。

var concurreyCount = 0;
var fetchUrl = function(url,callback){
 // delay 的值在 2000 以內(nèi),是個(gè)隨機(jī)的整數(shù) 模擬延時(shí)
 var delay = parseInt((Math.random()* 10000000) % 2000,10);
 concurreyCount++;
 console.log('現(xiàn)在并發(fā)數(shù)是 ' , concurreyCount , ' 正在抓取的是' , url , ' 耗時(shí)' + delay + '毫秒');
 setTimeout(function(){
 concurreyCount--;
 callback(null,url + ' html content');
 },delay);
}

var urls = [];
for(var i = 0;i<30;i++){
 urls.push('http://datasource_' + i)
}

然后我們使用async.mapLimit來(lái)并發(fā)抓取,并獲取結(jié)果。

async.mapLimit(urls,5,function(url,callback){
 fetchUrl(url,callbcak);
},function(err,result){
 console.log('result: ');
 console.log(result);
})

模擬摘自alsotang

運(yùn)行輸出后得到以下結(jié)果

使用async、enterproxy控制并發(fā)數(shù)量的方法詳解

我們發(fā)現(xiàn),并發(fā)數(shù)從1開(kāi)始增長(zhǎng),但是增長(zhǎng)到5時(shí),就不在增加。然有任務(wù)時(shí)就繼續(xù)抓取,并發(fā)連接數(shù)量始終控制在5個(gè)。

完成node簡(jiǎn)易爬蟲(chóng)系統(tǒng)

因?yàn)閍lsotang前輩的《node包教不包會(huì)》教程例子中使用的eventproxy控制的并發(fā)數(shù)量,我們就來(lái)完成一個(gè)使用async控制并發(fā)數(shù)量的node簡(jiǎn)易爬蟲(chóng)。

爬取的目標(biāo)就是本站首頁(yè)(手動(dòng)護(hù)臉)

第一步,首先我們需要用到以下的模塊:

  • url : 用于url解析,這里用到url.resolve()生成一個(gè)合法的域名
  • async : 一個(gè)實(shí)用的模塊,提供了強(qiáng)大的功能和異步JavaScript工作
  • cheerio : 為服務(wù)器特別定制的,快速,靈活,實(shí)施的jQuery核心實(shí)現(xiàn)
  • superagent : nodejs里一個(gè)非常方便的客戶端請(qǐng)求代理模塊

通過(guò)npm安裝依賴模塊

使用async、enterproxy控制并發(fā)數(shù)量的方法詳解

第二步,通過(guò)require引入依賴模塊,確定爬取對(duì)象URL:

var url = require("url");
var async = require("async");
var cheerio = require("cheerio");
var superagent = require("superagent");
var baseUrl = 'http://www.chenqaq.com';

第三步:使用superagent請(qǐng)求目標(biāo)URL,并使用cheerio處理baseUrl得到目標(biāo)內(nèi)容url,并保存在數(shù)組arr中

superagent.get(baseUrl)
 .end(function (err, res) {
 if (err) {
  return console.error(err);
 }
 var arr = [];
 var $ = cheerio.load(res.text);
 // 下面和jQuery操作是一樣一樣的..
 $(".post-list .post-title-link").each(function (idx, element) {
  $element = $(element);
  var _url = url.resolve(baseUrl, $element.attr("href"));
  arr.push(_url);
 });
 // 驗(yàn)證得到的所有文章鏈接集合
 output(arr);
 // 第四步:接下來(lái)遍歷arr,解析每一個(gè)頁(yè)面需要的信息
})

我們需要一個(gè)函數(shù)驗(yàn)證抓取的url對(duì)象,很簡(jiǎn)單我們只需要一個(gè)函數(shù)遍歷arr并打印出來(lái)就可以:

function output(arr){
 for(var i = 0;i<arr.length;i++){
  console.log(arr[i]);
 }
}

第四步:我們需要遍歷得到的URL對(duì)象,解析每一個(gè)頁(yè)面需要的信息。

這里就需要用到async控制并發(fā)數(shù)量,如果你上一步獲取了一個(gè)龐大的arr數(shù)組,有多個(gè)url需要請(qǐng)求,如果同時(shí)發(fā)出多個(gè)請(qǐng)求,一些網(wǎng)站就可能會(huì)把你的行為當(dāng)做惡意請(qǐng)求而封掉你的ip

async.mapLimit(arr,3,function(url,callback){
 superagent.get(url)
  .end(function(err,mes){
   if(err){
    console.error(err);
    console.log('message info ' + JSON.stringify(mes));
   }
   console.log('「fetch」' + url + ' successful!');
   var $ = cheerio.load(mes.text);
   var jsonData = {
    title:$('.post-card-title').text().trim(),
    href: url,
   };
   callback(null,jsonData);
  },function(error,results){
   console.log('results ');
   console.log(results);
  })
 })

得到上一步保存url地址的數(shù)組arr,限制最大并發(fā)數(shù)量為3,然后用一個(gè)回調(diào)函數(shù)處理 「該回調(diào)函數(shù)比較特殊,在iteratee方法中一定要調(diào)用該回調(diào)函數(shù),有三種方式」

  • callback(null) 調(diào)用成功
  • callback(null,data) 調(diào)用成功,并且返回?cái)?shù)據(jù)data追加到results
  • callback(data) 調(diào)用失敗,不會(huì)再繼續(xù)循環(huán),直接到最后的callback

好了,到這里我們的node簡(jiǎn)易的小爬蟲(chóng)就完成了,來(lái)看看效果吧

使用async、enterproxy控制并發(fā)數(shù)量的方法詳解

嗨呀,首頁(yè)數(shù)據(jù)好少,但是成功了呢。

參考資料

Node.js 包教不包會(huì) - alsotang

enterproxy

async

async Documentation

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)創(chuàng)新互聯(lián)的支持。

分享名稱:使用async、enterproxy控制并發(fā)數(shù)量的方法詳解
文章起源:http://www.rwnh.cn/article36/igpdsg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站設(shè)計(jì)、網(wǎng)站內(nèi)鏈、定制網(wǎng)站、電子商務(wù)、網(wǎng)站改版、做網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

微信小程序開(kāi)發(fā)
和龙市| 九龙城区| 德保县| 图们市| 沙坪坝区| 香格里拉县| 河曲县| 师宗县| 获嘉县| 兴义市| 多伦县| 合肥市| 佛学| 石狮市| 墨竹工卡县| 毕节市| 贞丰县| 凤冈县| 丰城市| 临夏市| 墨玉县| 保山市| 呼图壁县| 鹤山市| 万州区| 遵化市| 天峨县| 彭水| 永兴县| 都兰县| 息烽县| 永修县| 民勤县| 隆安县| 赣州市| 海伦市| 施甸县| 兴隆县| 峡江县| 津南区| 贵州省|