node.js 爬虫入门总结
node.js爬蟲
前端同學(xué)可能向來對(duì)爬蟲不是很感冒,覺得爬蟲需要用偏后端的語(yǔ)言,諸如 php , python 等。當(dāng)然這是在 nodejs 前了,nodejs 的出現(xiàn),使得 Javascript 也可以用來寫爬蟲了。由于 nodejs 強(qiáng)大的異步特性,讓我們可以輕松以異步高并發(fā)去爬取網(wǎng)站,當(dāng)然這里的輕松指的是 cpu 的開銷。
要讀懂本文,其實(shí)只需要有
- 能看懂 Javascript 及 JQuery
- 簡(jiǎn)單的nodejs基礎(chǔ)
- http 網(wǎng)絡(luò)抓包 和 URL 基礎(chǔ)
Nodejs做爬蟲的優(yōu)劣
首先說一下node做爬蟲的優(yōu)勢(shì)
第一個(gè)就是他的驅(qū)動(dòng)語(yǔ)言是JavaScript。JavaScript在nodejs誕生之前是運(yùn)行在瀏覽器上的腳本語(yǔ)言,其優(yōu)勢(shì)就是對(duì)網(wǎng)頁(yè)上的dom元素進(jìn)行操作,在網(wǎng)頁(yè)操作上這是別的語(yǔ)言無法比擬的。
第二就是nodejs是單線程異步的。聽起來很奇怪,單線程怎么能夠異步呢?想一下學(xué)操作系統(tǒng)的時(shí)候,單核cpu為什么能夠進(jìn)行多任務(wù)處理?道理也是類似,在操作系統(tǒng)中進(jìn)程對(duì)CPU的占有進(jìn)行時(shí)間切片,每一個(gè)進(jìn)程占有的時(shí)間很短,但是所有進(jìn)程循環(huán)很多次,因此看起就像是多個(gè)任務(wù)在同時(shí)處理。js也是一樣,js里有事件池,CPU會(huì)在事件池循環(huán)處理已經(jīng)響應(yīng)的事件,未處理完的事件不會(huì)放到事件池里,因此不會(huì)阻塞后續(xù)的操作。在爬蟲上這樣的優(yōu)勢(shì)就是在并發(fā)爬取頁(yè)面上,一個(gè)頁(yè)面未返回不會(huì)阻塞后面的頁(yè)面繼續(xù)加載,要做到這個(gè)不用像python那樣需要多線程。
其次是node的劣勢(shì)
首先是異步并發(fā)上。處理的好很方便,處理的不好就會(huì)很麻煩。例如要爬取10個(gè)頁(yè)面,用node不做異步處理話,那返回的結(jié)果可不一定是按1、2、3、4……這個(gè)順序,很可能是隨機(jī)。解決的辦法就是增加一個(gè)頁(yè)面的序列戳,讓爬取的數(shù)據(jù)生成csv文件,然后重新排序。
第二個(gè)是數(shù)據(jù)處理上的劣勢(shì),這點(diǎn)是不如python的,如果只是單純的爬數(shù)據(jù),用node當(dāng)然很好,但是如果用爬來的數(shù)據(jù)繼續(xù)做統(tǒng)計(jì)分析,做個(gè)回歸分析聚類啥的話,那就不能用node一步到底了。
如何用nodejs做爬蟲
下面就要說一下如何用nodejs做爬蟲了
- 1、初始化項(xiàng)目文件
在對(duì)應(yīng)的項(xiàng)目文件夾下執(zhí)行npm init來初始化一個(gè)package.json文件
- 2、安裝request和cheerio依賴包
request聽起來很熟悉吧,跟python里request功能一樣。它的功能就是建立起對(duì)目標(biāo)網(wǎng)頁(yè)的鏈接,并返回相應(yīng)的數(shù)據(jù),這個(gè)不難理解。
cheerio的功能是用來操作dom元素的,他可以把request返回來的數(shù)據(jù)轉(zhuǎn)換成可供dom操作的數(shù)據(jù),更重要的cheerio的api跟jquery一樣,用$來選取對(duì)應(yīng)的dom結(jié)點(diǎn),是不很方便?對(duì)一個(gè)前端程序員來說,這比python的什么xpath和beautisoup方便了不知道多少啊哈哈
安裝命令也很簡(jiǎn)單:
分別是npm install request --save 和 npm install cheerio
- 3、引入依賴包并使用
接下來就用request , fs和cherrio寫一個(gè)爬蟲吧!
首先引入依賴模塊
var http=require("http"); //網(wǎng)絡(luò)請(qǐng)求var fs=require("fs"); //操作文件,讀寫文件var cheerio=require("cheerio"); //擴(kuò)展模塊注:cheerio 模塊是第三方模塊,需要進(jìn)行安裝:npm install cheerio --save接下來就以我之前爬取的的百度新聞頁(yè)為例吧,為什么要選這個(gè)呢,因?yàn)檫@個(gè)是最基礎(chǔ)最簡(jiǎn)單的。
百度新聞頁(yè)面鏈接是:http://news.baidu.com/
執(zhí)行下面代碼:
var http=require("http"); var fs=require("fs");const wz="http://news.baidu.com/"; //網(wǎng)址var strHtml=""; var results=[]; http.get(wz,function(res){res.on("data",function(chunk){strHtml+=chunk;})res.on("end",function(){console.log(strHtml);}); })運(yùn)行一下結(jié)果就是這樣的
是不是很激動(dòng)哈哈,html返回回來了。這樣還是不夠的,接下就是要處理下返回的數(shù)據(jù),并提煉出我們想要獲得的信息,這就輪到cheerio登場(chǎng)了
將request返回的結(jié)果傳入cheerio中,并獲得想要獲取的信息,看代碼是不是想在寫腳本的感覺?
接下來我們?cè)讷@取一下這一段
執(zhí)行以下代碼:
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());})}); })運(yùn)行一下結(jié)果如下:
這樣一個(gè)簡(jiǎn)單的爬蟲就完成啦,是不是很簡(jiǎn)單啊。
然后再簡(jiǎn)單的介紹一下node.js爬取圖片
以下是我們將要爬取的圖片:
首先我們也需要同上面一樣引入一些需要的核心模塊
var http = require("http");var https = require("https");var fs = require("fs");var cheerio = require("cheerio");注:cheerio 模塊是第三方模塊,需要進(jìn)行安裝:
npm install cheerio --save
//保存網(wǎng)絡(luò)圖片 function saveImage(imageUrl){http.get(imageUrl, function (res) {res.setEncoding('binary'); //二進(jìn)制(binary)var imageData ='';res.on('data',function(data){ //圖片加載到內(nèi)存變量imageData += data;}).on('end',function(){ //加載完畢保存圖片if(!fs.existsSync("./images")){fs.mkdirSync("./images");}fs.writeFile('images/'+Math.random()+'.png',imageData,'binary',function (err) { //以二進(jìn)制格式保存if(err) throw err;console.log('保存成功');});});}); }
nodejs 爬蟲總結(jié)
① http.get+cheerio+iconv-lite
這種方式還是比較簡(jiǎn)單的,容易理解,直接使用http的get方法進(jìn)行請(qǐng)求url,將得到的內(nèi)容給cheerio解析,用jquery的方式解析出我們要東西即可。
要點(diǎn):
得到的結(jié)果中文亂碼如何解決呢,用iconv-lite模塊將得到的內(nèi)容進(jìn)行轉(zhuǎn)碼即可。
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是數(shù)組var $ = cheerio.load(html);...}); });② request+cheerio+iconv-lite
這種方式在獲取內(nèi)容的方式上與上有些不同,可以直接獲取到Buffer類型的數(shù)據(jù)。然后將得到的內(nèi)容給cheerio解析,用jquery的方式解析出我們要東西即可。
要點(diǎn):
結(jié)果中文亂碼如何解決,用iconv-lite模塊將得到的內(nèi)容進(jìn)行轉(zhuǎn)碼即可。
request(options,function(err,res,body){if(err)console.log(err);if(!err&&res.statusCode==200){var html = iconv.decode(body, 'gb2312'); //這里body是直接拿到的是Buffer類型的數(shù)據(jù),可以直接解碼。var $ = cheerio.load(html);...} });③ superagent+cheerio+superagent-charset
這種方式是比前面兩個(gè)有較大差別,用了superagent的get方法發(fā)起請(qǐng)求,解碼的時(shí)候用到了superagent-charse,用法還是很簡(jiǎn)單的,之后再將獲取到的內(nèi)容給cheerio解析,用jquery的方式解析出我們要東西即可。
要點(diǎn):
結(jié)果中文亂碼解決用superagent-charset模塊進(jìn)行轉(zhuǎn)碼,方式較之上面有點(diǎn)差別。
首先看它的加載方式:
var charset = require("superagent-charset");var superagent = charset(require("superagent")); //將superagent模塊傳遞給superagent-charset解碼方式:
superagent.get(url).charset('gb2312') //用charset方法達(dá)到解碼效果。.end(function(err,result){if(err) console.log(err);var $ = cheerio.load(result.text);...});至此呢,Nodejs爬蟲的核心就已經(jīng)介紹完畢了,剩下就完全可以自由發(fā)揮了
總結(jié)
以上是生活随笔為你收集整理的node.js 爬虫入门总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【java】反射+poi 导出exce
- 下一篇: 链接器和加载器 好书