node.js爬虫
前端同学可能向来对爬虫不是很感冒,觉得爬虫需要用偏后端的语言,诸如 php , python 等。当然这是在 nodejs 前了,nodejs 的出现,使得 Javascript 也可以用来写爬虫了。由于 nodejs 强大的异步特性,让我们可以轻松以异步高并发去爬取网站,当然这里的轻松指的是 cpu 的开销。
要读懂本文,其实只需要有
- 能看懂 Javascript 及 JQuery
- 简单的nodejs基础
- http 网络抓包 和 URL 基础
Nodejs做爬虫的优劣
首先说一下node做爬虫的优势
第一个就是他的驱动语言是JavaScript。JavaScript在nodejs诞生之前是运行在浏览器上的脚本语言,其优势就是对网页上的dom元素进行操作,在网页操作上这是别的语言无法比拟的。
第二就是nodejs是单线程异步的。听起来很奇怪,单线程怎么能够异步呢?想一下学操作系统的时候,单核cpu为什么能够进行多任务处理?道理也是类似,在操作系统中进程对CPU的占有进行时间切片,每一个进程占有的时间很短,但是所有进程循环很多次,因此看起就像是多个任务在同时处理。js也是一样,js里有事件池,CPU会在事件池循环处理已经响应的事件,未处理完的事件不会放到事件池里,因此不会阻塞后续的操作。在爬虫上这样的优势就是在并发爬取页面上,一个页面未返回不会阻塞后面的页面继续加载,要做到这个不用像python那样需要多线程。
其次是node的劣势
首先是异步并发上。处理的好很方便,处理的不好就会很麻烦。例如要爬取10个页面,用node不做异步处理话,那返回的结果可不一定是按1、2、3、4……这个顺序,很可能是随机。解决的办法就是增加一个页面的序列戳,让爬取的数据生成csv文件,然后重新排序。
第二个是数据处理上的劣势,这点是不如python的,如果只是单纯的爬数据,用node当然很好,但是如果用爬来的数据继续做统计分析,做个回归分析聚类啥的话,那就不能用node一步到底了。
如何用nodejs做爬虫
下面就要说一下如何用nodejs做爬虫了
- 1、初始化项目文件
在对应的项目文件夹下执行npm init来初始化一个package.json文件
- 2、安装request和cheerio依赖包
request听起来很熟悉吧,跟python里request功能一样。它的功能就是建立起对目标网页的链接,并返回相应的数据,这个不难理解。
cheerio的功能是用来操作dom元素的,他可以把request返回来的数据转换成可供dom操作的数据,更重要的cheerio的api跟jquery一样,用$来选取对应的dom结点,是不很方便?对一个前端程序员来说,这比python的什么xpath和beautisoup方便了不知道多少啊哈哈
安装命令也很简单:
分别是npm install request --save 和 npm install cheerio
- 3、引入依赖包并使用
接下来就用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());
})
});
})
运行一下结果如下:
这样一个简单的爬虫就完成啦,是不是很简单啊。
然后再简单的介绍一下node.js爬取图片
以下是我们将要爬取的图片:
首先我们也需要同上面一样引入一些需要的核心模块
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('保存成功');
});
});
});
}
nodejs 爬虫总结
① http.get+cheerio+iconv-lite
这种方式还是比较简单的,容易理解,直接使用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);
...
});
});
② request+cheerio+iconv-lite
这种方式在获取内容的方式上与上有些不同,可以直接获取到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+cheerio+superagent-charset
这种方式是比前面两个有较大差别,用了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爬虫的核心就已经介绍完毕了,剩下就完全可以自由发挥了
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。