//"cheerio",一个nodeJS模块(第三方模块 安装指令 npm install cheerio),类似于jquery,可以将html页面的char转换为document文档对象,然后用类似于jquery的方式进行操作DOM
var http = require('http');
var cheerio = require('cheerio');
var url = "http://www.imooc.com/learn/348";
function filterChapters(html) {
//把html内容封装进$中,
var $ = cheerio.load(html);
//分析出包含所有章节的类名
var chapters = $('.chapter');
var courseData = []; //课程信息
//把each中要定义的变量移动到函数顶部,避免反复声明
var chapter;
var chapterTitle;
var videos;
var chapterData;
var video;
var videoTitle;
var id;
var adress;
chapters.each(function(index, item) {
chapter = $(item);
chapterTitle = chapter.find('strong').text();
videos = chapter.find('li');
chapterData = {
'chapterTitle': chapterTitle,
'videos': []
};
videos.each(function(index, item) {
video = $(item).find('.J-media-item');
videoTitle = video.text();
id = video.attr('href').split('video/')[1];
adress = video.attr('href');
chapterData.videos.push({
'title':videoTitle,
'id':id,
'adress':adress
});
});
courseData.push(chapterData);
});
return courseData;
}
function printCourseInfo(courseData) {
var chapterTitle;
var urlPre = 'URL:http://www.imooc.com';
courseData.forEach(function(item) {
chapterTitle = item.chapterTitle;
console.log(chapterTitle + ':' + '\n');
item.videos.forEach(function(video) {
console.log('ID:【' + video.id + '】' + urlPre + video.adress +' 章节:'+ video.title.trim() + '\n');
});
});
}
http.get(url, function(res) {
var html = '';
res.on('data', function(data) {
html += data;
});
res.on('end', function() {
var courseData = filterChapters(html);
printCourseInfo(courseData);
});
}).on('error', function() {
console.log("获取课程数据出错!");
});
二、Promise重构
var http = require('http')
var cheerio = require('cheerio')
var basicUrl = 'http://www.imooc.com/learn/'
var Promise = require('bluebird')
var baseUrl = 'http://www.imooc.com/learn/637'
//***扩展变量
var coursesIds = [348, 637, 259, 75, 197]; //要爬取的课程ID
var pagesArr = []
//***扩展变量完毕
//***4.单页面扩展至多课程----批量获取页面html
coursesIds.forEach(function(id) {
pagesArr.push(getPageAsync(basicUrl + id))
})
// 填充学习的人数
for(var i=0; i < coursesIds.length; i++){
$.ajax({
type: "GET",
url: "http://www.imooc.com/course/AjaxCourseMembers?ids="+coursesIds[i]
success: function (a) {
if (0 == a.result) {
var c = a.data[0];
$(".js-learn-num")[i].text(c.numbers)
} else {
console.log("获取学习人数错误")
}
}
})
}
//1.获取界面html并返回准备传入解析函数,利用Promise对象进行Async的页面获取
function getPageAsync(url) {
return new Promise(function(resolve, reject) {
http.get(url, function(res) {
console.log('正在爬取' + url + '\n')
var html = ''
res.on('data', function(data) {
html += data
})
res.on('end', function() {
console.log('页面' + url + '爬取完毕')
resolve(html)
})
}).on('error', function(e) {
reject(e)
console.log('爬取页面信息失败')
})
})
}
//2.解析函数,用于将传入的页面HTML代码解析,提取其中所需要的信息,并保存在courseData对象中
function filterChapters(html) {
var $ = cheerio.load(html)
//下面是自定义函数,用于text()函数删除子元素的影响
$.fn.mytext = function() {
return $(this).clone()
.children()
.remove()
.end()
.text()
}
//自定义函数完毕
/*数据信息格式
var courseData={
courseTitle:'',
courseLearners:'',
chapters:[]
}
chapters=[{
chapterTitle:chapterTitle,
videos:[{
title:title,
id:id
}
]
}]
*/
var courseTitle = $($($('.course-infos').find('.hd')).find('h2')).mytext().trim()
var courseLearners = parseInt($($('.statics').children('.static-item')).find('span[class="meta-value js-learn-num"]').mytext()) //注意 因为html文件中没有人数信息,所以获取不到,这里调了好久才发现
var courseData = {
courseTitle: courseTitle,
courseLearners: courseLearners,
chapters: []
} //所有信息存储用的数组
var chapters = $('.chapter')
//遍历所需要的变量
var $thisChapter, $chapterTitle
var $videoTitle, $videoId, $thisVideo
var $videos
//张杰遍历开始
chapters.each(function(item) {
$thisChapter = $(this)
$chapterTitle = $($thisChapter.find('strong')).mytext().replace(/\s/g, '')
//用于保存信息和最终输出的courseData对象
var chapterData = {
chapterTitle: $chapterTitle,
videos: []
}
//完毕
//获取并保存videos数据
$videos = $thisChapter.find('.video').children('li')
$videos.each(function(item) { //开始遍历这一章中的所有视频
$thisVideo = $(this)
$videoTitle = $thisVideo.find('.J-media-item').mytext().replace(/\s/g, '')
$videoId = $thisVideo.find('.J-media-item').attr('href').split('video/')[1]
//合成一个对象,保存至chapterData的videos数组中
chapterData.videos.push({
title: $videoTitle,
id: $videoId
})
//video推入courseData完毕
})
//videos存储完毕
courseData.chapters.push(chapterData)
}) //张杰遍历结束
//返回courseData
return courseData
}
//3.输出函数,按照指定格式输出courseData中保存的信息
function printInfo(courseData) {
console.log('#####################课程:' + courseData.courseTitle + '#######################')
console.log(' ->该课程学习人数:' + courseData.courseLearners + '\n')
courseData.chapters.forEach(function(item) {
console.log(' @@@章节:' + item.chapterTitle + '@@@\n')
//输出张杰下的视频信息
item.videos.forEach(function(item) {
console.log(' >课程:[' + item.id + ']' + item.title)
})
})
console.log('\n')
}
// //函数运行主体
// getPageAsync(baseUrl)
// .then(function(html){
// var courseData=filterChapters(html)//利用解析函数解析所爬取的页面并返回课程信息对象
// printInfo(courseData)//输出最终整理完毕的课程信息对象
// })
//扩展--函数运行主体
Promise
.all(pagesArr)
.then(function(pages) {
pages.forEach(function(page) {
var courseData = filterChapters(page)
printInfo(courseData)
})
})