這篇文章主要跟大家講解了一下用NodeJS學習爬蟲,並透過爬糗事百科來講解用法和效果,一起學習下吧。
1.前言分析
平常都是利用Python/.NET 語言實作爬蟲,原本現在作為前端開發人員,自然需熟練NodeJS。下面利用 NodeJS 語言實作一個糗事百科的爬蟲。另外,本文使用的部分程式碼是 es6 語法。
實作該爬蟲所需的依賴函式庫如下。
request: 利用 get 或 post 等方法取得網頁的原始碼。 cheerio: 網頁原始碼解析,取得所需資料。
本文首先對爬蟲所需依賴函式庫及其使用進行介紹,然後利用這些依賴函式庫,實作一個針對糗事百科的網路爬蟲。
2. request 函式庫
request 是一個輕量級的 http 函式庫,功能十分強大且使用簡單。可以使用它實作 Http 的請求,並且支援 HTTP 認證, 自定請求頭等。以下對 request 庫中一部分功能進行介紹。
安裝 request 模組如下:
npm install request
在安裝好 request 後,即可進行使用,下面利用 request 請求一下百度的網頁。
const req = require('request'); req('http://www.baidu.com', (error, response, body) => { if (!error && response.statusCode == 200) { console.log(body) } })
在沒有設定 options 參數時,request 方法預設是 get 請求。而我喜歡利用 request 物件的具體方法,使用如下:
req.get({ url: 'http://www.baidu.com' },(err, res, body) => { if (!err && res.statusCode == 200) { console.log(body) } });
然而很多時候,直接去請求一個網址所獲取的 html 源碼,往往得不到我們需要的資訊。一般情況下,需要考慮到請求頭和網頁編碼。
網頁的請求頭網頁的編碼
下面介紹在請求的時候如何添加網頁請求頭以及設定正確的編碼。
req.get({ url : url, headers: { "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36", "Host" : "www.zhihu.com", "Upgrade-Insecure-Requests" : "1" }, encoding : 'utf-8' }, (err, res, body)=>{ if(!err) console.log(body); })
設定 options 參數, 新增 headers
屬性即可實現請求頭的設定;新增 encoding
屬性即可設定網頁的編碼。需要注意的是,若 encoding:null
,那麼 get 請求所取得的內容則是 Buffer
對象,即 body 是一個 Buffer 物件。
上面介紹的功能足矣滿足後面的所需了
#3. cheerio 庫
cheerio 是一款伺服器端的Jquery,以輕、快、簡單易學等特色被開發者喜愛。有 Jquery 的基礎後再來學習 cheerio 函式庫非常輕鬆。它能夠快速定位到網頁中的元素,其規則和 Jquery 定位元素的方法是一樣的;它也能以一種非常方便的形式修改 html 中的元素內容,以及獲取它們的資料。以下主要針對 cheerio 快速定位網頁中的元素,以及取得它們的內容進行介紹。
先安裝 cheerio 函式庫
npm install cheerio
下面先給一段程式碼,再對程式碼進行解釋 cheerio 函式庫的用法。對部落格園首頁進行分析,然後提取每一頁中文章的標題。
首先對部落格園區首頁進行分析。如下圖:
對html 原始碼進行分析後,首先透過.post_item
取得所有標題,接著對每一個.post_item
進行分析,使用a.titlelnk
即可符合每個標題的a 標籤。下面透過程式碼進行實作。
const req = require('request'); const cheerio = require('cheerio'); req.get({ url: 'https://www.cnblogs.com/' }, (err, res, body) => { if (!err && res.statusCode == 200) { let cnblogHtmlStr = body; let $ = cheerio.load(cnblogHtmlStr); $('.post_item').each((index, ele) => { let title = $(ele).find('a.titlelnk'); let titleText = title.text(); let titletUrl = title.attr('href'); console.log(titleText, titletUrl); }); } });
當然,cheerio 函式庫也支援鍊式調用,上面的程式碼也可改寫成:
let cnblogHtmlStr = body; let $ = cheerio.load(cnblogHtmlStr); let titles = $('.post_item').find('a.titlelnk'); titles.each((index, ele) => { let titleText = $(ele).text(); let titletUrl = $(ele).attr('href'); console.log(titleText, titletUrl);
上面的程式碼非常簡單,就不再用文字進行贅述了。以下總結一點自己認為比較重要的幾點。
使用find()
方法取得的節點集合A,若再次以A 集合中的元素為根節點定位它的子節點以及取得子元素的內容與屬性,需對A 集合中的子元素進行$(A[i])
包裝,如上面的$(ele)
一樣。在上面程式碼中使用$(ele)
,其實還可以使用$(this)
但是由於我使用的是es6 的箭頭函數,因此改變了each
方法中回調函數的this 指針,因此,我使用$(ele)
; cheerio 庫也支援鍊式調用,如上面的$('.post_item').find('a .titlelnk')
,需要注意的是,cheerio 物件A 呼叫方法find()
,如果A 是集合,那麼A 集合中的每一個子元素都會呼叫find( )
方法,並放回一個結果結合。如果A 呼叫text()
,那麼A 集合中的每一個子元素都會呼叫text()
並傳回一個字串,該字串是所有子元素內容的合併(直接合併,沒有分隔符號)。
最後在總結一些我比較常用的方法。
first() last() children([selector]): 這個方法和 find 類似,只不過此方法只搜尋子節點,而 find 搜尋整個後代節點。
4. 糗事百科爬蟲
#通过上面对 request
和 cheerio
类库的介绍,下面利用这两个类库对糗事百科的页面进行爬取。
1、在项目目录中,新建 httpHelper.js
文件,通过 url 获取糗事百科的网页源码,代码如下:
//爬虫 const req = require('request'); function getHtml(url){ return new Promise((resolve, reject) => { req.get({ url : url, headers: { "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36", "Referer" : "https://www.qiushibaike.com/" }, encoding : 'utf-8' }, (err, res, body)=>{ if(err) reject(err); else resolve(body); }) }); } exports.getHtml = getHtml;
2、在项目目录中,新建一个 Splider.js
文件,分析糗事百科的网页代码,提取自己需要的信息,并且建立一个逻辑通过更改 url 的 id 来爬取不同页面的数据。
const cheerio = require('cheerio'); const httpHelper = require('./httpHelper'); function getQBJok(htmlStr){ let $ = cheerio.load(htmlStr); let jokList = $('#content-left').children('p'); let rst = []; jokList.each((i, item)=>{ let node = $(item); let titleNode = node.find('h2'); let title = titleNode ? titleNode.text().trim() : '匿名用户'; let content = node.find('.content span').text().trim(); let likeNumber = node.find('i[class=number]').text().trim(); rst.push({ title : title, content : content, likeNumber : likeNumber }); }); return rst; } async function splider(index = 1){ let url = `https://www.qiushibaike.com/8hr/page/${index}/`; let htmlStr = await httpHelper.getHtml(url); let rst = getQBJok(htmlStr); return rst; } splider(1);
在获取糗事百科网页信息的时候,首先在浏览器中对源码进行分析,定位到自己所需要标签,然后提取标签的文本或者属性值,这样就完成了网页的解析。
Splider.js
文件入口是 splider
方法,首先根据传入该方法的 index 索引,构造糗事百科的 url,接着获取该 url 的网页源码,最后将获取的源码传入 getQBJok
方法,进行解析,本文只解析每条文本笑话的作者、内容以及喜欢个数。
直接运行 Splider.js
文件,即可爬取第一页的笑话信息。然后可以更改 splider
方法的参数,实现抓取不同页面的信息。
在上面已有代码的基础上,使用 koa
和 vue2.0
搭建一个浏览文本的页面,效果如下:
源码已上传到 github 上。下载地址:https://github.com/StartAction/SpliderQB ;
项目运行依赖 node v7.6.0
以上, 首先从 Github 上面克隆整个项目。
git clone https://github.com/StartAction/SpliderQB.git
克隆之后,进入项目目录,运行下面命令即可。
node app.js
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
以上是使用NodeJS編寫爬蟲範例的詳細內容。更多資訊請關注PHP中文網其他相關文章!