上一篇是对单一页面的数据,所以只能爬到单一的数据,因为不同的 ID 请求出不同的数据,所以把小爬虫完善一下
该例子是拿幕课网中的某个页面来进行测试
这个时候就用到一个 Promise 异步回调模块(作用是把页面一个接一个的请求),node 版本比较新的就直接 require 进来就可以了,而旧版本的可以下载 bluebird 模块
npm install bluebird
然后require 进来就可以了 var Promise = require('bluebird');
先把要引入的东西引进来
var http = require('http');
var Promise = require('bluebird');
var cheerio = require('cheerio');
var baseUrl = 'http://www.imooc.com/learn/'; // http://www.imooc.com/learn/348
var videosIds = [348,637];
然后用 Promise 异步回调方法把 http.get 请求的包起来,思路是改变 ID 然后一个接一个的请求,Promise 里有一个 all 方法,该方法传进去的是一个数组,每一组就是一个方法,跑完所有的方法会返回一个数组,每组就是每次请求得到的数据
function getPageAsync(url){
return new Promise(function(resolve , reject){
console.log('正在爬取' + url);
http.get( url , function(res){
var html = '';
res.on('data', function(data){ //监听 data 事件 , 这个时候爬的是整个的html代码;
html += data;
})
res.on('end', function(res){
//console.log(html); //http跑完后打印出来 ,
resolve(html)
})
}).on('error', function(e){
reject(e);
console.log('获取失败');
})
})
}
//把所有的请求的集中来一起
var fetchCourseArray = [];
videosIds.forEach(function(id){
fetchCourseArray.push(getPageAsync(baseUrl + id));
})
Promise
.all(fetchCourseArray) // all 参数是一个方法的数组, 先把一堆 getPageAsync 请求给做完
.then(function(pages){ //用了 all后 pages 是一个数组,每组是每次请求后得到的东西
var courseData = [];
//console.log(pages)
pages.forEach(function(html){
var course = filterChapters(html);
courseData.push(course);
})
printCourseInfo(courseData)
})
filterChapters 方法是把 html数据解析出有用的东西
function filterChapters(html){
var $ = cheerio.load(html); //拿到html 内容,然后就可以用 $('.xx') 来获取元素一样操作
var chapter = $(".chapter");
/*
把有用的数据筛选成这个的结构
{
title : '',
num : '',
list : [{
chapterTitle : '', //标题
videos : [
id : '',
title : '',
]
}],
}
*/
var title = $('.course-infos .clearfix h2').text().trim();
var courseData = {
title : title,
list : [],
}
chapter.each(function(item){
var chapter = $(this);
var videos = chapter.find('.video').children('li');
var chapterTitle = chapter.find('strong').text().trim();
var list = {
chapterTitle : chapterTitle,
videos : [],
}
videos.each(function(item){
var video = $(this).find('.J-media-item');
var videoTitle = video.text();
var id = videos.attr('data-media-id');
list.videos.push({
id : id,
title : videoTitle,
})
})
courseData.list.push(list);
})
return courseData;
}
printCourseInfo 方法是打得到的数据打印出来
function printCourseInfo(courseData){
courseData.forEach(function(data){
var pageTitle = data.title;
console.log(pageTitle + '\n'); //页面标题
data.list.forEach(function(item){
var title = item.chapterTitle;
var videos = item.videos;
console.log(title + '\n'); //第N章节标题
videos.forEach(function(video){
console.log('【'+video.id+'】' + video.title + '\n'); //内容
})
})
})
}