//"cheerio",一个nodeJS模块(第三方模块 安装指令 npm install cheerio),类似于jquery,可以将html页面的char转换为document文档对象,然后用类似于jquery的方式进行操作DOM
});
二、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)
})
})