在百度上面有許多關於使用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');
});