HTTP小爬虫(慕课网)

一、传统的方法
//"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)
        })


    })

你可能感兴趣的:(精选博客,NodeJS学习目录)