Nodejs使用eventproxy控制并发数
博客专区 > webphp 的博客 > 博客详情
Nodejs使用eventproxy控制并发数
webphp 发表于5个月前
Nodejs使用eventproxy控制并发数
  • 发表于 5个月前
  • 阅读 11
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 新注册用户 域名抢购1元起>>>   

昨天在使用 superagent 与 cheerio 完成简单爬虫已经可以利用superagent简单的实现网页爬虫功能,可以根据给定的url地址获取文章列表标题、链接、发布时间等功能,今天使用eventproxy控制并发数的功能,需要取出每个主题的第一条评论,这就要求我们对每个主题的链接发起请求,并用 cheerio 去取出其中的第一条评论
这次要用到三个库superagent cheerio eventproxy  eventproxy的学习文档https://github.com/JacksonTian/eventproxy#%E9%87%8D%E5%A4%8D%E5%BC%82%E6%AD%A5%E5%8D%8F%E4%BD%9C

eventproxy的特点:

  1. 利用事件机制解耦复杂业务逻辑
  2. 移除被广为诟病的深度callback嵌套问题
  3. 将串行等待变成并行等待,提升多异步协作场景下的执行效率
  4. 友好的Error handling
  5. 无平台依赖,适合前后端,能用于浏览器和Node.js
  6. 兼容CMD,AMD以及CommonJS模块环境

要得到的效果是:

[ { title: '置顶\n\n\n\n CNode社区 for Ionic [2015-02-07更新][1.2.1已上架
][求issue]',
href: 'https://cnodejs.org/topic/545aee5a3e1f39344c5b3b3e',
comment1: '看起来还比较粗糙嘛' },
{ title: '回馈各位Noder,Iris来给大家送亚马逊礼品卡~!',
href: 'https://cnodejs.org/topic/554060bc208c44bf37c24d93',
comment1: '《深夜食堂》有书~' },
]

首先安装eventproxy库

npm install eventproxy

其次在app.js中写好路由,

var superagent = require('./routes/superagent');
app.get('/superagent/eventurl', superagent.eventurl);//superagent请求网页爬虫之先获取列表的url地址。在获取文章内部的第一个评论内容

/routes/superagent.js

第一步先获取列表中的所的url地址

var eventproxy = require('eventproxy');//处理nodejs并发的插件
var cheerio = require('cheerio');//类似于jquery库
var superagent = require('superagent');//为了做网页爬虫,引入superagent,http 方面的库,可以发起 get 或 post 请求 (npm install superagent)
var url = require('url');// url 模块是 Node.js 标准库里面的
exports.eventurl = function(req, res){
	var cnodeUrl = 'https://cnodejs.org/';
	superagent.get(cnodeUrl)
		.end(function(err, res) {
			if ( err ) {
				return console.error( err );
			};
			var topicUrls = [];
			var $ = cheerio.load(res.text);
			// 获取首页所有的链接
			$("#topic_list .topic_title").each(function(index, element){
				var $element = $(element);
				// $element.attr('href') 本来的样子是 /topic/542acd7d5d28233425538b04
      			// 我们用 url.resolve 来自动推断出完整 url,变成
			    // https://cnodejs.org/topic/542acd7d5d28233425538b04 的形式
      			// 具体请看 http://nodejs.org/api/url.html#url_url_resolve_from_to 的示例
				var href = url.resolve(cnodeUrl, $element.attr('href') );
				topicUrls.push(href);
			});
                        console.log(topicUrls);
               })

}

可以到到以下结果

[
'https://cnodejs.org/topic/55483b6bd6c067e36e41ab51'
'https://cnodejs.org/topic/5546ce60c5441de9545a3c10'
'https://cnodejs.org/topic/53c1f593400ca4581b79c5de'
'https://cnodejs.org/topic/5546f173c5441de9545a3c89'
'https://cnodejs.org/topic/554796f5d6c067e36e41aae2'
'https://cnodejs.org/topic/55422cbbbce63fb638715418'
'https://cnodejs.org/topic/5543ac050a21a480669ebe89'
'https://cnodejs.org/topic/5544bbe30a21a480669ebed0'
]

这时候我们已经得到所有 url 的地址了,接下来,我们把这些地址都抓取一遍,就完成了,在这里说一下eventproxy,如果我们不用eventproxy库的话,传统的写法是定义一个变量,
var count =0,然后每次抓取成功以后count++,由于我们不知道在抓取的时候那个url是先完成的,只能用count == N的时候,然后在执行下一个函数。而eventproxy就起到了计数数的作用,eventproxy可以帮我们管理那个请求是否已经成功,完成之后会自动调用处理函数。下面用eventproxy来处理
全部代码为:

exports.eventurl = function(req, res){
	var cnodeUrl = 'https://cnodejs.org/';
	superagent.get(cnodeUrl)
		.end(function(err, res) {
			if ( err ) {
				return console.error( err );
			};
			var topicUrls = [];
			var $ = cheerio.load(res.text);
			// 获取首页所有的链接
			$("#topic_list .topic_title").each(function(index, element){
				var $element = $(element);
				// $element.attr('href') 本来的样子是 /topic/542acd7d5d28233425538b04
      			// 我们用 url.resolve 来自动推断出完整 url,变成
			    // https://cnodejs.org/topic/542acd7d5d28233425538b04 的形式
      			// 具体请看 http://nodejs.org/api/url.html#url_url_resolve_from_to 的示例
				var href = url.resolve(cnodeUrl, $element.attr('href') );
				topicUrls.push(href);
			});

			// 得到 topicUrls 之后
			// 得到一个 eventproxy 的实例
			var ep = new eventproxy();
			// 命令 ep 重复监听 topicUrls.length 次(在这里也就是 40 次) `topic_html` 事件再行动
			ep.after('topic_html', topicUrls.length, function(topics){
				// topics 是个数组,包含了 40 次 ep.emit('topic_html', pair) 中的那 40 个 pair
				// 开始行动
				topics = topics.map(function(topicPair){
					 // 接下来都是 jquery 的用法了
					var topicUrl = topicPair[0];
					var topicHtml = topicPair[1];
					var $ = cheerio.load( topicHtml );
					return ({
						title: $(".topic_full_title").text().trim(),
						href:topicUrl,
						comment1:$('.reply_content').eq(0).text().trim(),
					});
				});
				console.log( 'final:' );
				console.log( topics );
				// res.send( topic );
			});

			topicUrls.forEach(function(topicUrl){
				superagent.get(topicUrl)
					.end(function(err, res){
						console.log( 'fetch' + topicUrl + 'successful' );
						ep.emit('topic_html', [topicUrl, res.text]);
					})
			})
		})

}

eventproxy内部的一些函数使用正在学习,比如.emit... 大家也可以查看中文文档,https://github.com/JacksonTian/eventproxy#%E9%87%8D%E5%A4%8D%E5%BC%82%E6%AD%A5%E5%8D%8F%E4%BD%9C

 

标签: eventproxy nodejs
共有 人打赏支持
粉丝 2
博文 89
码字总数 90487
×
webphp
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: