您的位置:首页 > Web前端 > Node.js

nodejs 爬取小说

2018-03-11 20:28 141 查看

前言

前段时间看到有个同学用python爬取了小说,于是打算用nodejs爬取一下小说,在这里先总结一下整个过程.(仅供学习,请勿商业)

效果图



爬取思路

爬取首页url,然后把所有要爬取的url放在数组,准备爬取

大概有2300多个url要爬取,不可能一下发出2000多条请求,这样请求失败可能性极大.我使用了async这个包,控制了一下并发,请求控制为5,效果还是挺好的.设置代理,再提高一下并发数的话,效率就可以大大提高了.

使用到的npm包

request 用来发送请求,可以用superagent代替

iconv-lite 用来转码

cheerio 类似Jquery的一个库,方便dom操作

async 控制并发数

具体代码

// request
const request = require('request');
const iconv = require('iconv-lite');
// 类似jquery的一个库
const cheerio = require('cheerio');
// 文件管理模块
const fs = require('fs');
// 控制并发数
const async = require('async');
var URL = 'http://www.biquge.com.tw/3_3711/';
var NUMBER = 0;
var start = new Date();
console.log("开始爬取首页......");
var Options = {
method: 'GET',
encoding: null,
url:URL,
timeout:100000
};
request(Options,function(err,res,body){
if(err){
console.log('首页爬取失败');
console.log(err);
return ;
}
console.log("首页爬取成功,费时" + (new Date() - start) / 1000 + '秒');
// 处理爬取的信息
body = iconv.decode(body,'gbk');
var $ = cheerio.load(body);
var MAXLIMIT = 5;
var TITLE = $('#info>h1').text() + '.txt';
var urls = $('#list>dl>dd>a');
var URLS = [];

urls.each( function(index,ele){
var a = $(this);
var url = URL.substring(0,25) + a.attr('href');
var data = {
'index':index,
'url':url,
'title':a.text()
};
URLS.push(data);
});

async.mapLimit(URLS,MAXLIMIT,function(item,callback){
getData(item,callback)
},function(err,result){

var end  = ( new Date() - start ) /1000;

console.log(`爬取所有信息费时${end}秒`);

result.sort(function(a,b){
return a.index - b.index;
});

result = result.map(function(item){

return item.title + '\n\r' + item.content;

}).join('\n\r');

write(TITLE,result);

var end = (new Date() - start ) / 1000;
console.log("共耗时"+end+"秒");
})

});

var getData = function(item,callback){
var start = new Date();
Options.url = item.url;
request(Options,function(err,res,body){
var end = (new Date() - start) / 1000;
var str;
if(err){
var str = `获取${item.url}失败,共耗时${end}秒\n\r`;
callback(null,{
'index':-1,
'title':'异常',
'content':'异常'
});
message(11,str);
}else{
body = iconv.decode(body,'gbk');
var $ = cheerio.load(body);
var content = $('#content').text();
var str = `获取${item.url}成功,共耗时${end}秒\n\r`;
var data = {
"index":item.index,
"title":item.title,
"content":content
};
callback(null,data);
message(10,str);
NUMBER++;
console.log(`成功获取${NUMBER}个`);
}
})
};

var write = function(bookname,data){

var start = new Date();
console.log("开始写入文件");
fs.writeFileSync(bookname,data,'utf-8');
var end = ( new Date() - start ) / 1000;
console.log(`写入文件成功,耗时${end}秒`);
}

// 每个请求的信息,success or false
var message = function(type,data){
var name
a8a7
= 'success.txt';
var options = {
'flag':'a+',
'encoding':'utf-8'
}
//success
if(type == 11){
name = 'error.txt';
}
fs.writeFile(name,data,options,function(err){
if(err){
console.log(err);
}
})
}


总结

其实也没什么好说的,就是各种npm的综合使用,值得注意的就是程序里的一下细节处理,爬取到的内容是先保存的内存中好,还是储存在外部文件中?爬取到内容的应该如何排序?等问题.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  并发 nodejs