前端同窗可能向来对爬虫不是很感冒,以为爬虫须要用偏后端的语言,诸如 php , python 等。固然这是在 nodejs 前了,nodejs 的出现,使得 Javascript 也能够用来写爬虫了。因为 nodejs 强大的异步特性,让咱们能够轻松以异步高并发去爬取网站,固然这里的轻松指的是 cpu 的开销。php
第一个就是他的驱动语言是JavaScript。JavaScript在nodejs诞生以前是运行在浏览器上的脚本语言,其优点就是对网页上的dom元素进行操做,在网页操做上这是别的语言没法比拟的。html
第二就是nodejs是单线程异步的。听起来很奇怪,单线程怎么可以异步呢?想一下学操做系统的时候,单核cpu为何可以进行多任务处理?道理也是相似,在操做系统中进程对CPU的占有进行时间切片,每个进程占有的时间很短,可是全部进程循环不少次,所以看起就像是多个任务在同时处理。js也是同样,js里有事件池,CPU会在事件池循环处理已经响应的事件,未处理完的事件不会放到事件池里,所以不会阻塞后续的操做。在爬虫上这样的优点就是在并发爬取页面上,一个页面未返回不会阻塞后面的页面继续加载,要作到这个不用像python那样须要多线程。前端
首先是异步并发上。处理的好很方便,处理的很差就会很麻烦。例如要爬取10个页面,用node不作异步处理话,那返回的结果可不必定是按一、二、三、4……这个顺序,极可能是随机。解决的办法就是增长一个页面的序列戳,让爬取的数据生成csv文件,而后从新排序。node
第二个是数据处理上的劣势,这点是不如python的,若是只是单纯的爬数据,用node固然很好,可是若是用爬来的数据继续作统计分析,作个回归分析聚类啥的话,那就不能用node一步到底了。python
在对应的项目文件夹下执行npm init来初始化一个package.json文件jquery
request听起来很熟悉吧,跟python里request功能同样。它的功能就是创建起对目标网页的连接,并返回相应的数据,这个不难理解。程序员
cheerio的功能是用来操做dom元素的,他能够把request返回来的数据转换成可供dom操做的数据,更重要的cheerio的api跟jquery同样,用$来选取对应的dom结点,是不很方便?对一个前端程序员来讲,这比python的什么xpath和beautisoup方便了不知道多少啊哈哈npm
安装命令也很简单:json
分别是npm install request --save 和 npm install cheerio后端
接下来就用request , fs和cherrio写一个爬虫吧!
首先引入依赖模块
var http=require("http"); //网络请求 var fs=require("fs"); //操做文件,读写文件 var cheerio=require("cheerio"); //扩展模块 注:cheerio 模块是第三方模块,须要进行安装: npm install cheerio --save
百度新闻页面连接是:http://news.baidu.com/
执行下面代码:
var http=require("http"); var fs=require("fs"); const wz="http://news.baidu.com/"; //网址 var strHtml=""; var results=[]; http.get(wz,function(res){ res.on("data",function(chunk){ strHtml+=chunk; }) res.on("end",function(){ console.log(strHtml); }); })
运行一下结果就是这样的
是否是很激动哈哈,html返回回来了。这样仍是不够的,接下就是要处理下返回的数据,并提炼出咱们想要得到的信息,这就轮到cheerio登场了
将request返回的结果传入cheerio中,并得到想要获取的信息,看代码是否是想在写脚本的感受?
接下来咱们在获取一下这一段
执行如下代码:
var http=require("http"); var fs=require("fs"); var cheerio=require("cheerio"); const wz="http://news.baidu.com/"; var strHtml=""; var results=[]; http.get(wz,function(res){ res.on("data",function(chunk){ strHtml+=chunk; }) res.on("end",function(){ //console.log(strHtml); var $=cheerio.load(strHtml); $("#channel-all li").each((iten,i)=>{ console.log($(i).text()); }) }); })
运行一下结果以下:
这样一个简单的爬虫就完成啦,是否是很简单啊。
如下是咱们将要爬取的图片:
首先咱们也须要同上面同样引入一些须要的核心模块
var http = require("http"); var https = require("https"); var fs = require("fs"); var cheerio = require("cheerio");
注:cheerio 模块是第三方模块,须要进行安装:
npm install cheerio --save
//保存网络图片 function saveImage(imageUrl){ http.get(imageUrl, function (res) { res.setEncoding('binary'); //二进制(binary) var imageData =''; res.on('data',function(data){ //图片加载到内存变量 imageData += data; }).on('end',function(){ //加载完毕保存图片 if(!fs.existsSync("./images")){ fs.mkdirSync("./images"); } fs.writeFile('images/'+Math.random()+'.png',imageData,'binary',function (err) { //以二进制格式保存 if(err) throw err; console.log('保存成功'); }); }); }); }
这种方式仍是比较简单的,容易理解,直接使用http的get方法进行请求url,将获得的内容给cheerio解析,用jquery的方式解析出咱们要东西便可。
要点:
获得的结果中文乱码如何解决呢,用iconv-lite模块将获得的内容进行转码便可。
http.get(options,function(result){ var body = []; result.on('data',function(chunk){ body.push(chunk); }); result.on('end', function () { var html = iconv.decode(Buffer.concat(body), 'gb2312'); //注意这里body是数组 var $ = cheerio.load(html); ... }); });
这种方式在获取内容的方式上与上有些不一样,能够直接获取到Buffer类型的数据。而后将获得的内容给cheerio解析,用jquery的方式解析出咱们要东西便可。
要点:
结果中文乱码如何解决,用iconv-lite模块将获得的内容进行转码便可。
request(options,function(err,res,body){ if(err)console.log(err); if(!err&&res.statusCode==200){ var html = iconv.decode(body, 'gb2312'); //这里body是直接拿到的是Buffer类型的数据,能够直接解码。 var $ = cheerio.load(html); ... } });
这种方式是比前面两个有较大差异,用了superagent的get方法发起请求,解码的时候用到了superagent-charse,用法仍是很简单的,以后再将获取到的内容给cheerio解析,用jquery的方式解析出咱们要东西便可。
要点:
结果中文乱码解决用superagent-charset模块进行转码,方式较之上面有点差异。
首先看它的加载方式:
var charset = require("superagent-charset"); var superagent = charset(require("superagent")); //将superagent模块传递给superagent-charset
解码方式:
superagent.get(url) .charset('gb2312') //用charset方法达到解码效果。 .end(function(err,result){ if(err) console.log(err); var $ = cheerio.load(result.text); ... });
至此呢,Nodejs爬虫的核心就已经介绍完毕了,剩下就彻底能够自由发挥了