1、HTTP爬虫
1、在node的http模块中有get和request连个接口来完成数据的获取或者提交,对于get和request我们可以去官网先看看这两个方法http://nodejs.cn/api/http.html#http_http_methods,这两个方法我们在后面的博客中还会提到。现在我们来做个爬虫来爬https://www.imooc.com/learn/348。
2、首先我们要去获得该页面的html源码
var http = require('http'); var url='http://www.imooc.com/learn/348'; http.get(url,function(res){ var html=''; res.on('data',function(data){ //将data事件绑定到匿名函数,data事件实际上在重复着发生,这个function实际也在重复的进行 html+=data; //将获得的数据不断添加到html变量中 }) res.on('end',function(){ //在响应结束的事件发生后,绑定到匿名函数中,匿名函数负责打印所有的html代码 console.log(html) //输出一堆html的代码 }) }).on('error',function(){ console.log('获取课程数据出现了错误') })
3、我们获得到网页的html源码其实没有多大用,现在我们搞点有用的数据,我们这里要获取这个网页上的课程信息,把课程列表获取下来。这里我们首先推荐cheerio模块,能够操作装载后的html,简单方便,我们使用 npm install cheerio来下载这个模块,下面我们直接亮出全部代码和两幅html网页源码图,然后我们慢慢讲解,代码按照注释的数字顺序去读
var http = require('http'); var cheerio=require('cheerio'); var url='http://www.imooc.com/learn/348'; function filterChapters(html){ var $=cheerio.load(html) //(2)使用cheerio模块将html代码装载进来 var chapters=$('.chapter') //图1告诉我们,课程的章节都在<div class="chapter course-wrap">..<div>中,我们就找到所有的chapter类,把它们放在变量chapters中,那变量chapters实际上就是个数组 //我们期望的最后拿到的数据结构 // [{ // chapterTitle:'', //章节的标题 // videos:[ // title:'', // id:'', // ] // }] var courseData=[] chapters.each(function(item){ //在之前拿到每一章的条件下进行遍历 var chapter=$(this) //遍历的里面拿到单独的某一章 var chapterTitle=chapter.find('h3').text() //图2告诉我们,每一章的大标题都在h3标签里,使用find找到h3这个标签,将h3下的文本内容使用text()拿出来 var videos=chapter.find('.video').children('li') //videos是个数组,在本章节有几个视频,这个videos数组里就有几个元素 var chapterData={ chapterTitle:chapterTitle, videos:[] } videos.each(function(item){ var video=$(this).find('.J-media-item') //图2告诉我们每个视频标题都包含在<a href='xxx' class='J-media-item'>下 var videoTitle=video.text() //找到每节的视频标题 var id=video.attr('href').split('video/')[1] //在href=/video/6649中只截取6649 chapterData.videos.push({ title:videoTitle, id:id, }) }) courseData.push(chapterData) }) return courseData; } function printCourseInfo(courseDate){ //(3)把获取的信息全部打印出来 courseDate.forEach(function(item){ var chapterTitle=item.chapterTitle //console.log(chapterTitle+'\n') console.log(chapterTitle) item.videos.forEach(function(video){ console.log('['+video.id+']'+video.title+'\n') }) }) } http.get(url,function(res){ //(1)使用get方法从我们指定的url上去获取数据 var html=''; res.on('data',function(data){ //将data事件和匿名函数绑定 html+=data; //每次获取的数据都加到html变量中 }) res.on('end',function(){ //将响应结束事件和匿名函数绑定 var courseDate=filterChapters(html) //最后的变量html就是从url上获取的html源码,交给filterChapters处理 printCourseInfo(courseDate) }) }).on('error',function(){ console.log('获取课程数据出现了错误') })
4、值得注意的是,对于同一个网页在不同时间段的html源代码不一样的,所以假如代码是18年六月写的,没准到下一年就不能用了,因为网页源代码变了,结构变了,所以最后按照上的代码的思路去自己爬爬,下面展示一下上面代码运行的结果