美文网首页
Node.js + Promise 实现爬虫

Node.js + Promise 实现爬虫

作者: 木木口丁 | 来源:发表于2017-07-29 15:10 被阅读0次

    写在前面:

    前天,(是前天吧,,?)写了一个基于http模块和cheerio模块实现的小爬虫,爬取了慕课网的一些课程信息,现在用另一种方法实现。

    • 安装bluebird模块,以提供Promise异步操作
      npm install bluebird
    • 安装cheerio模块用于操作DOM
      npm install cheerio
    • 爬取不到课程信息中的正在学习人数,一直是NaN很蛋疼。。可能网站用了什么反爬手段。。
    • Node.js 没有DOM结构!

    Code:

    // E:\Node\crawler\promiseCrawler.js
    var http = require('http');
    var Promise = require('bluebird');
    var cheerio = require('cheerio');
    var baseUrl = 'http://www.imooc.com/learn/';
    var url = 'http://www.imooc.com/learn/348';
    var videoIds = [348, 637, 259, 728, 197, 134, 75];
    
    function filterChapters(html) {
        var $ = cheerio.load(html);
        var chapters = $('.chapter');
        var title = $('#main .course-infos .w .hd h2').text().trim();
        var number = parseInt($('.js-learn-num').text().trim(), 10);
    
        // courseData = {
        //     title : title,    // 大标题
        //     number : number,    // 学习人数
        //     videos : []
        // }
    
        var courseData = {
            title: title,
            number: number,
            videos: []
        };
        chapters.each(function (item) {
            var chapter = $(this);
            var chapterTitle = chapter.find('strong').text().trim();
            var videos = chapter.find('.video').children('li');
            var chapterData = {
                chapterTitle: chapterTitle,
                videos: []    // 小节视频
            }
    
            videos.each(function (item) {
                var video = $(this).find('.J-media-item');
                var videoTitle = video.text().trim();
                var id = video.attr('href').split('video/')[1];
    
                chapterData.videos.push({
                    title: videoTitle,
                    id: id
                })
            })
            courseData.videos.push(chapterData);
        })
        return courseData;
    }
    
    function printCourseInfo(coursesData) {
        coursesData.forEach(function (courseData) {
            console.log(courseData.number + '人学过' + courseData.title + '\n');
        })
    
        coursesData.forEach(function (courseData) {
            console.log('### ' + courseData.title + '\n');
    
            courseData.videos.forEach(function (item) {
    
                var chapterTitle = item.chapterTitle;
    
                console.log(chapterTitle + '\n');
                item.videos.forEach(function (video) {
                    console.log('[' + video.id + ']' + video.title + '\n');
                })
            })
        })
    
    }
    
    function getPageAsync(url) {
        return new Promise(function (resolve, reject) {
            console.log('正在爬取 ' + url);
    
            http.get(url, function (res) {
                var html = '';
    
                res.on('data', function (data) {
                    html += data;
                })
    
                res.on('end', function () {
                    // console.log(html);
                    resolve(html);
                    //var courseData = filterChapters(html);
                    //printCourseInfo(courseData);
                })
            }).on('error', function (e) {
                reject(e)
                console.log("获取课程数据出错!");
            })
        })
    }
    
    var fetchCourseArray = [];
    videoIds.forEach(function (id) {
        fetchCourseArray.push(getPageAsync(baseUrl + id));
    })
    
    // .all()提供并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调.
    Promise.all(fetchCourseArray)
        .then(function (pages) {
            var coursesData = [];
            pages.forEach(function (html) {
                var courses = filterChapters(html);
                coursesData.push(courses);
            });
            coursesData.sort(function (a, b) {    // 从大到小排序
                return a.number < b.number;
            })
    
            printCourseInfo(coursesData);
        })
    

    结果如图:

    爬取结果

    相关文章

      网友评论

          本文标题:Node.js + Promise 实现爬虫

          本文链接:https://www.haomeiwen.com/subject/oyzqlxtx.html