目标
爬取 CNode(https://cnodejs.org/) 社区首页的标题和详情页的第一条评论,以及评论的作者,作者积分,最后以json格式打印
步骤
注意:很多网站有并发连接数的限制,所以当请求发送太快的时候会导致返回值为空或报错。
安装依赖 express superagent cheerio eventproxy
$ npm install express superagent cheerio eventproxy --save
新建app.js 抓取所有的url
// 引入依赖
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
eventproxy
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) {});
这一句,监听了三个事件,分别是 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');
});
来源:oschina
链接:https://my.oschina.net/u/3913691/blog/3061198