前端同窗可能向來對爬蟲不是很感冒,以爲爬蟲須要用偏後端的語言,諸如 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爬蟲的核心就已經介紹完畢了,剩下就徹底能夠自由發揮了