爬取 CNode(https://cnodejs.org/) 社区首页的标题和详情页的第一条评论,以及评论的做者,做者积分,最后以json格式打印html
注意:不少网站有并发链接数的限制,因此当请求发送太快的时候会致使返回值为空或报错。node
安装依赖 express superagent cheerio eventproxyjquery
$ npm install express superagent cheerio eventproxy --save
新建app.js 抓取全部的urlexpress
// 引入依赖 var express = require('express'); var eventproxy = require('eventproxy'); var superagent = require('superagent'); var cheerio = require('cheerio'); var app = express(); // url 模块是 Node.js 标准库里面的 var url = require('url'); var cnodeUrl = 'https://cnodejs.org/'; app.get('/', function(req, res, next) { // 用 superagent 去抓取 https://cnodejs.org/ 的内容 superagent.get(cnodeUrl) .end(function(err, sres) { if (err) { return next(err); } // sres.text 里面存储着网页的 html 内容,将它传给 cheerio.load 以后,就能够获得一个实现了 jquery 接口的变量,咱们习惯性地将它命名为 `$` // 剩下就都是 jquery 的内容了 var $ = cheerio.load(sres.text); var topicUrls = []; // 获取全部连接 $('#topic_list .topic_title').each(function(index, elem) { var $element = $(elem); // url.resolve 来自动推断出完整 url var href = url.resolve(cnodeUrl, $element.attr('href')); topicUrls.push(href); }); res.send(topicUrls); }); }); app.listen(3000, function (req, res) { console.log('app is running at port 3000'); });
运行node app.js
npm
var ep = new eventproxy(); ep.all('data1_event', 'data2_event', 'data3_event', function (data1, data2, data3) { var html = fuck(data1, data2, data3); render(html); }); $.get('http://data1_source', function (data) { ep.emit('data1_event', data); }); $.get('http://data2_source', function (data) { ep.emit('data2_event', data); }); $.get('http://data3_source', function (data) { ep.emit('data3_event', data); });
ep.all('data1_event', 'data2_event', 'data3_event', function (data1, data2, data3) {});
json
这一句,监听了三个事件,分别是 data1_event
, data2_event
, data3_event
,每次当一个源的数据抓取完成时,就经过 ep.emit()
来告诉 ep
本身,某某事件已经完成了。数组
当三个事件未同时完成时,ep.emit()
调用以后不会作任何事;当三个事件都完成的时候,就会调用末尾的那个回调函数,来对它们进行统一处理。并发
// 引入依赖 var express = require('express'); var eventproxy = require('eventproxy'); var superagent = require('superagent'); var cheerio = require('cheerio'); // url 模块是 Node.js 标准库里面的 var url = require('url'); var app = express(); var ep = new eventproxy(); // 获得一个 eventproxy 的实例 var cnodeUrl = 'https://cnodejs.org/'; app.get('/', function(req, res, next) { // 用 superagent 去抓取 https://cnodejs.org/ 的内容 superagent.get(cnodeUrl) .end(function(err, sres) { if (err) { return next(err); } // sres.text 里面存储着网页的 html 内容,将它传给 cheerio.load 以后,就能够获得一个实现了 jquery 接口的变量,咱们习惯性地将它命名为 `$` // 剩下就都是 jquery 的内容了 var $ = cheerio.load(sres.text); var topicUrls = []; // 获取全部连接 $('#topic_list .topic_title').each(function(index, elem) { var $element = $(elem); // url.resolve 来自动推断出完整 url var href = url.resolve(cnodeUrl, $element.attr('href')); topicUrls.push(href); }); // 命令 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) { var topicUrl = topicpair[0]; var topicHtml = topicpair[1]; var $ = cheerio.load(topicHtml); return ({ title: $('.topic_full_title').text().trim(), href: topicUrl, comment: $('.reply_content').eq(0).text().trim(), }); }); res.send(topics); }) topicUrls.forEach(function(topicUrl) { superagent.get(topicUrl) .end(function(uerr, ures) { console.log('success:' + topicUrl); ep.emit('topic_html', [topicUrl, ures.text]); }); }); }); }); app.listen(3000, function (req, res) { console.log('app is running at port 3000'); });