前言 早就聽過爬蟲,這幾天開始學習nodejs,寫了個爬蟲 demo ,爬取 博客園首頁的文章標題、用戶名、閱讀數、推薦數和用戶頭像,現做個小總結。 使用到這幾個點: 1、node的核心模塊-- 文件系統 2、用於http請求的第三方模塊 -- superagent 3、用於解析DOM的第三方模塊 ...
前言
早就聽過爬蟲,這幾天開始學習nodejs,寫了個爬蟲 demo ,爬取 博客園首頁的文章標題、用戶名、閱讀數、推薦數和用戶頭像,現做個小總結。
使用到這幾個點:
1、node的核心模塊-- 文件系統
2、用於http請求的第三方模塊 -- superagent
3、用於解析DOM的第三方模塊 -- cheerio
幾個模塊詳細的講解及API請到各個鏈接查閱,demo中只有簡單的用法。
準備工作
使用npm管理依賴,依賴信息會存放在package.json中
//安裝用到的第三方模塊
cnpm install --save superagent cheerio
引入所需要用到的功能模塊
//引入第三方模塊,superagent用於http請求,cheerio用於解析DOM const request = require('superagent'); const cheerio = require('cheerio'); const fs = require('fs');
請求 + 解析頁面
想要爬到博客園首頁的內容,首先要請求首頁地址,拿到返回的html,這裡使用superagent進行http請求,基本的使用方法如下:
request.get(url) .end(error,res){ //do something }
向指定的url發起get請求,請求錯誤時,會有error返回(沒有錯誤時,error為null或undefined),res為返回的數據。
拿到html內容後,要拿到我們想要的數據,這個時候就需要用cheerio解析DOM了,cheerio要先load目標html,然後再進行解析,API和jquery的API非常類似,熟悉jquery上手非常快。直接看代碼實例
//目標鏈接 博客園首頁 let targetUrl = 'https://www.cnblogs.com/'; //用來暫時保存解析到的內容和圖片地址數據 let content = ''; let imgs = []; //發起請求 request.get(targetUrl) .end( (error,res) => { if(error){ //請求出錯,列印錯誤,返回 console.log(error) return; } // cheerio需要先load html let $ = cheerio.load(res.text); //抓取需要的數據,each為cheerio提供的方法用來遍歷 $('#post_list .post_item').each( (index,element) => { //分析所需要的數據的DOM結構 //通過選擇器定位到目標元素,再獲取到數據 let temp = { '標題' : $(element).find('h3 a').text(), '作者' : $(element).find('.post_item_foot > a').text(), '閱讀數' : +$(element).find('.article_view a').text().slice(3,-2), '推薦數' : +$(element).find('.diggnum').text() } //拼接數據 content += JSON.stringify(temp) + '\n'; //同樣的方式獲取圖片地址 if($(element).find('img.pfs').length > 0){ imgs.push($(element).find('img.pfs').attr('src')); } }); //存放數據 mkdir('./content',saveContent); mkdir('./imgs',downloadImg); })
存儲數據
上面解析DOM之後,已經拼接了所需要的信息內容,也拿到了圖片的URL,現在就進行存儲,把內容存放到指定目錄的txt文件中,而且下載圖片到指定目錄
先創建目錄,使用nodejs核心的文件系統
//創建目錄 function mkdir(_path,callback){ if(fs.existsSync(_path)){ console.log(`${_path}目錄已存在`) }else{ fs.mkdir(_path,(error)=>{ if(error){ return console.log(`創建${_path}目錄失敗`); } console.log(`創建${_path}目錄成功`) }) } callback(); //沒有生成指定目錄不會執行 }
有了指定目錄之後,可以寫入數據了,txt文件的內容已經有了,直接寫入就可以了使用writeFile()
//將文字內容存入txt文件中 function saveContent() { fs.writeFile('./content/content.txt',content.toString()); }
取到了圖片的鏈接,所以需要再使用superagent下載圖片,存在本地。superagent可以直接返回一個響應流,再配合nodejs的管道,直接把圖片內容寫到本地
//下載爬到的圖片 function downloadImg() { imgs.forEach((imgUrl,index) => { //獲取圖片名 let imgName = imgUrl.split('/').pop(); //下載圖片存放到指定目錄 let stream = fs.createWriteStream(`./imgs/${imgName}`); let req = request.get('https:' + imgUrl); //響應流 req.pipe(stream); console.log(`開始下載圖片 https:${imgUrl} --> ./imgs/${imgName}`); } ) }
效果
執行下demo,看下效果,數據已經正常爬下來了
非常簡單的一個demo,可能也沒有那麼嚴謹,不過總是走出了node的第一小步。