Node.js第一次小爬虫

此次学习nodejs,进行了一次小爬虫,肯定是要记录下来的。

此次爬虫以慕课网为例,爬取某一课程的章节信息。
代码在视频的基础上进行了一定的改进和优化。

声明全局变量
var http = require('http');
var cheerio = require('cheerio');
var url = 'http://www.imooc.com/learn/348';
get()
http.get(url, function(res) {
    var html = '';
    res.on('data', function(data) {
        html += data;
    });
    res.on('end', function() {
        var courseData = filterChapters(html);
        printData(courseData);
    });

}).on('error', function() {
    console.log("获取课程数据错误");
})
filterChapters方法用于获取章节信息,传入HTML,返回一个数组
function filterChapters(html) {
    var $ = cheerio.load(html);
    var chapters = $('.chapter');

    // [{
    //  chapterTitle:'',
    //  videos:[
    //  title:'',
    //  id:''
    //  ]
    // }]
    var courseData = [];
    var chapter, chapterTitle, chapterData;
    var video, videoTitle, videoId
    chapters.each(function(item) {
        chapter = $(this);
        chapterTitle = chapter.find('strong').contents().filter(function(index) {
            return this.nodeType === 3;
        }).text().trim();
        videos = chapter.find('.video').children('li');
        chapterData = {
            chapterTitle: chapterTitle,
            videos: []
        }
        videos.each(function(index, el) {
            video = $(this).find('.J-media-item');
            videoTitle = video.contents().filter(function(index) {
                return this.nodeType === 3;
            }).text().trim().split('\n');
            nodes = video[0].childNodes;
            for (var i = 0; i < nodes.length - 1; i++) {
                if (nodes[i].nodeType == 3) {
                    videoTitle = nodes[i].nodeValue.trim();
                }
            }
            videoId = video.attr('href').split('video/')[1];
            chapterData.videos.push({  
                title: videoTitle[0].trim(),
                time: videoTitle[1].trim(),
                id: videoId
            })
        })
        courseData.push(chapterData);
    })
    return courseData;
}
printData方法用于打印数据
function printData(courseData) {
    var html = '';
    courseData.forEach(function(item) {
        html += item.chapterTitle + '\n\n';
        item.videos.forEach(function(video) {
            html += '[' + video.id + ']  ' + video.title + '  ' + video.time + '\n';
        })
        html += '\n'
    })
    console.log(html);
}

遇见了一个小问题,就在获取文本内容时使用了innerText,但发现这个方法会将子标签的文本一同获取到,这不是想要的结果,于是通过查资料,自己动手实现了这一操作。

//JS原生实现
nodes=video[0].childNodes;
for(var i=0;i

性能认识
不要在循环里面声明变量,这会导致每次循环都声明该变量,可在循环体外声明变量
不要循环使用console.log(),console也是一个对象。可先声明一个变量,将要输出的字符串加进该变量,最后在用console.log()。

本次爬虫学到了不少东西,初次学习,免不了有些错误和不当之处,望大家能不吝赐教。

你可能感兴趣的:(Node.js第一次小爬虫)