Node.jsasync和enterproxy控制并发数量

拉并发与互为

起我们常常提及的,不管是web
server,app并发无处不在,操作系统被,指一个时间段受到几只次处于已经起步运行及为止之间,且这几个次都是在同等处理机上运行,并且任一个光阴接触仅生一个程序在拍卖机上运行。很多网站都产生起连接数量的界定,所以当呼吁发送太抢之时光会招致返回值为空或报错。更有甚者,有些网站可能为若有的出现连接数量过多而当您是于恶意请求,封掉你的ip。

相对于并发,并履行或陌生了诸多,并行指一组先后按照独立异步的快执行,不顶时间达的重合(同一个天天发生),通过加cpu核心来实现多单程序(任务)的而开展。没错,并行做到了大半任务的又拓展

动enterproxy控制并发数量

enterproxy是朴灵大大为要贡献的家伙,带来同样栽事件式编程的琢磨转变,利用事件机制解耦复杂工作逻辑,解决了回调函数耦合性的骂,将串行等待变成并行等待,提升多异步协作场景下之执行效率

我们什么样使enterproxy控制并发数量?通常如我们不动enterproxy和自制的计数器,我们如果抓到手三独出自:

这种深层嵌套,串行的法门

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);
    });
  });
});

除此之外这种过去深层嵌套的章程,我们健康的写法的友好维护一个计数器

(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就足以由至此计数器的意图,它帮助您管理这些异步操作是否成功,完成之后,他会见自行调用你提供的处理函数,并以办案到手到多少作参数传递过来

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还提供了外很多状况所待的API,可以活动学习下者API
enterproxy

应用async控制并发数量

若是我们出40独请求需要发,很多网站或者会见以您闹的出现连接数最好多如当您是当恶意请求,把您的IP封掉。
故此我们连要控制并发数量,然后逐步抓到手完就40个链接。

使用async中mapLimit控制一次性并发数量也5,一次性就抓到手5独链接。

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

咱先是应该明了什么是并发,为什么用限并发数量,都发生什么样处理方案。然后就可以错过文档具体看一下API如何运用。async文档好很好之攻这些语法。

法一组数,这里归的数额是借用的,返回的延时是随机的。

var concurreyCount = 0;
var fetchUrl = function(url,callback){
    // delay 的值在 2000 以内,是个随机的整数 模拟延时
    var delay =  parseInt((Math.random()* 10000000) % 2000,10);
    concurreyCount++;
    console.log('现在并发数是 ' , concurreyCount , ' 正在抓取的是' , url , ' 耗时' + 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来并作抓到手,并获得结果。

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

仿照摘自alsotang

运转输出后获得以下结果

Node.js 1

俺们发现,并发数从1开加强,但是增长至5时,就未以增加。然有任务时即便继续抓取,并作连接数量始终控制以5只。

完成node简易爬虫系统

因为alsotang前辈的《node包教不包会》课例子中以的eventproxy控制的产出数量,我们便来形成一个施用async控制并发数量的node简易爬虫。

爬取的对象即是本站首页(手动护脸)

第一步,首先我们得运用以下的模块:

  • url : 用于url解析,这里用url.resolve()变化一个官的域名
  • async : 一个实用的模块,提供了强有力的效益以及异步JavaScript工作
  • cheerio : 为服务器特别定制的,快速,灵活,实施之jQuery核心实现
  • superagent : nodejs里一个挺好之客户端请求代理模块

    通过npm安依赖模块

Node.js 2

老二步,通过require引入依赖模块,确定爬取对象URL:

var url = require("url");
var async = require("async");
var cheerio = require("cheerio");
var superagent = require("superagent");

var baseUrl = 'http://www.chenqaq.com';

老三步:使用superagent请求目标URL,并采用cheerio处理baseUrl得到目标内容url,并保存于数组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);
    });

    // 验证得到的所有文章链接集合
    output(arr);
    // 第四步:接下来遍历arr,解析每一个页面需要的信息

})

咱们用一个函数验证抓取的url对象,很粗略我们只是需要一个函数通历arr并打印出来就足以:

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

季步:我们得遍历得到的URL对象,解析每一个页面需要之音讯。

此地虽需要以async支配并发数量,如果您及同一步获取了一个高大之arr数组,有差不多个url需要请,如果同时发出多只请求,一些网站就可能会见管你的行为作恶意请求而封掉你的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地址之数组arr,限制最酷起数量为3,然后据此一个回调函数处理
「该回调函数比较特别,在iteratee方法被必要调用该回调函数,有三栽方法」

  • callback(null) 调用成功
  • callback(null,data) 调用成功,并且返回数据data追加至results
  • callback(data) 调用黄,不见面更持续循环,直接到最后之callback

哼了,到这里我们的node简易的有点爬虫就水到渠成了,来看看效果吧

Node.js 3

喂呀,首页数据好少,但是成功了呢。

参考资料

Node.js 包教不包会Node.js –
alsotang

enterproxy

async

async Documentation