刚开始学js, 在 https://github.com/alsotang/node-lessons/tree/master/lesson3 教程的基础上, 将所抓取的标题对应的也一并文章进行抓取。 由于异步事件模型的原因,如果利用for循环的话
, 对文章进行抓取时,直接for循环执行get事件,但由于异步造成访问间隔太短会报出503的错误,暂时不了解有什么通用的手段避免, 因此利用events库的信号来模拟实现同步抓取, 源码如下。
var superagent = require('superagent');
var cheerio = require('cheerio');
var events = require('events');
var app = require('express')();
var emitter = new events.EventEmitter();
var srcHost = 'https://cnodejs.org';
var items = [];
var titleAry = [];
var indexPage = null;
var curIndex = 0;
emitter.on('childEvnts', function(data){
var $element = indexPage(titleAry[curIndex]);
var $ = cheerio.load(data.text);
var curContext = $("#main .markdown-text");
items.push({
title : $element.attr('title'),
href : $element.attr('href'),
context : $(curContext[0]).text()
});
console.log(curIndex, items.length);
if (items.length === titleAry.length)
emitter.emit("End");
else {
curIndex++;
console.log(indexPage(titleAry[curIndex]).attr('href'));
ownGet(srcHost + indexPage(titleAry[curIndex]).attr('href'));
}
});
function ownGet (url) {
superagent.get(url)
.end(function(err, articleData) {
if (err){
console.log(err.message);
return;
}
emitter.emit('childEvnts', articleData);
});
}
app.get('/', function (req, res, next) {
if (items.length !== 0){
res.send(items);
return;
}
superagent.get(srcHost)
.end(function(err, data){
if (err) {
return;
}
var $ = cheerio.load(data.text);
indexPage = $;
titleAry = $("#topic_list .topic_title");
var $element = $(titleAry[0]);
ownGet(srcHost + $element.attr('href'));
});
(function(res){
emitter.on('End', function(){
res.send(items);
});
})(res);
});
app.listen(3000, function () {
console.log("start listen port 3000");
});