在百度上面有许多关于使用nodejs进行网页数据爬取的例子,但是大多数都只是爬取的单页面数据。但是设想如果我们爬取到的是一个页面的url,然后我们要再次访问url进行下一个页面的爬取。这样有许多人就可能会想到执行两次,但是事实上我们只需要一次请求就可以完成。但是因为nodejs的异步机制,这就让我们必须要使用到async的walterfall和whilst,下面就以抓取BT吧最新电影数据为例:
var express = require("express");
//网络请求模块
var request = require("request");
//将html代码转为jquery可以解析的模块
var cheerio = require("cheerio");
//转换编码模块
var iconv = require("iconv-lite");
//异步模块---walterfall和whilst
var async = require("async");
var app = express();
//设置跨域访问
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
res.header("Content-Type", "application/json;charset=utf-8");
next();
});
//BT吧最新电影
app.get('/BTMovies/newMovies',function(req,res){
/*
进行地址和详细信息的抓取,因为nodejs异步的原因会导致在还没有抓取到地址的时候就进行了详细信息的获取,所以这种方式不采用
*/
// request('http://www.btba.com.cn/',function(error,response,body){
// if(!error && response.statusCode == 200){
// $ = cheerio.load(body);
// var array = [];
// $('.year li a').each(function(i,item){
// var object = {
// title:'',
// url :'',
// img :''
// }
// object.title = $(this).attr('title');
// object.url = $(this).attr('href');
// request(object.url,function(error,response,body){
// if(!error && response.statusCode == 200){
// $ = cheerio.load(body);
// object.img = $('.l img').attr('src');
// }
// })
// array.push(object);
// })
// res.json({
// newMovies:array
// })
// }
// })
/*
先采用walterfall进行最新电影的详细地址获取
然后再根据获取到的地址采用whilst进行循环抓取详细信息
*/
async.waterfall([
function(callback){
request('http://www.btba.com.cn/',function(error,response,body){
if(!error && response.statusCode == 200){
$ = cheerio.load(body,{decodeEntities: false});
var array = [];
$('.year li a').each(function(i,item){
var object = {
title:'',
url :'',
img :'',
download:[],
}
object.title = $(this).attr('title');
object.url = $(this).attr('href');
array.push(object);
})
callback(null, array);
}
})
}
], function (err, result) {
var length = result.length;
var i = 0;
async.whilst(
function() { return i < length; },
function(callback) {
i++;
request(result[i-1].url,function(error,response,body){
if(!error && response.statusCode == 200){
$ = cheerio.load(body,{decodeEntities: false});
var img = $('.l img').attr('src');
var download_array = [];
$('.btinfo h3').each(function(i,item){
var download_info = {url:'',size:'',info:''};
download_info.url = $(this).find('a').attr('href');
download_info.size = $(this).find('b').html();
download_info.info = $(this).find('i').html();
download_array.push(download_info);
})
result[i-1].img = img;
result[i-1].download = download_array.slice();
callback(null, result);
}
})
},
function (err, content) {
res.json({
data:content
})
}
);
});
})
var server = app.listen(4444, function() {
console.log('监听端口 4444');
});