NodeJS爬蟲入門

来源:http://www.cnblogs.com/mingjiatang/archive/2017/12/13/8034953.html
-Advertisement-
Play Games

1. 寫在前面 往常都是利用 Python/.NET 語言實現爬蟲,然現在作為一名前端開發人員,自然需要熟練 NodeJS。下麵利用 NodeJS 語言實現一個糗事百科的爬蟲。另外,本文使用的部分代碼是 es6 語法。 實現該爬蟲所需要的依賴庫如下。 1. request: 利用 get 或者 po ...


1. 寫在前面

往常都是利用 Python/.NET 語言實現爬蟲,然現在作為一名前端開發人員,自然需要熟練 NodeJS。下麵利用 NodeJS 語言實現一個糗事百科的爬蟲。另外,本文使用的部分代碼是 es6 語法。

實現該爬蟲所需要的依賴庫如下。

  1. request: 利用 get 或者 post 等方法獲取網頁的源碼。
  2. 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 源碼,往往得不到我們需要的信息。一般情況下,需要考慮到請求頭和網頁編碼。

  1. 網頁的請求頭
  2. 網頁的編碼

下麵介紹在請求的時候如何添加網頁請求頭以及設置正確的編碼。

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 對象。

上面介紹的功能足矣滿足後面的所需了,更多功能請參看官網的文檔 request

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);

上面的代碼非常簡單,就不再用文字進行贅述了。下麵總結一點自己認為比較重要的幾點。

  1. 使用 find() 方法獲取的節點集合 A,若再次以 A 集合中的元素為根節點定位它的子節點以及獲取子元素的內容與屬性,需對 A 集合中的子元素進行 $(A[i]) 包裝,如上面的$(ele) 一樣。
  2. 在上面代碼中使用 $(ele) ,其實還可以使用 $(this) 但是由於我使用的是 es6 的箭頭函數,因此改變了 each 方法中回調函數的 this 指針,因此,我使用 $(ele);
  3. cheerio 庫也支持鏈式調用,如上面的 $('.post_item').find('a.titlelnk') ,需要註意的是,cheerio 對象 A 調用方法 find(),如果 A 是一個集合,那麼 A 集合中的每一個子元素都調用 find() 方法,並放回一個結果結合。如果 A 調用 text() ,那麼 A 集合中的每一個子元素都調用 text() 並返回一個字元串,該字元串是所有子元素內容的合併(直接合併,沒有分隔符)。

最後在總結一些我比較常用的方法。

  1. first()
  2. last()
  3. children([selector]): 該方法和 find 類似,只不過該方法只搜索子節點,而 find 搜索整個後代節點。

關於更多 cheerio 庫的用法,請參考文檔 cheerio

4. 糗事百科爬蟲

通過上面對 requestcheerio 類庫的介紹,下麵利用這兩個類庫對糗事百科的頁面進行爬取。

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('div');
    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 方法的參數,實現抓取不同頁面的信息。

在上面已有代碼的基礎上,使用 koavue2.0 搭建一個瀏覽文本的頁面,效果如下:

源碼已上傳到 github 上。下載地址:https://github.com/StartAction/SpliderQB ;

項目運行依賴 node v7.6.0 以上, 首先從 Github 上面克隆整個項目。

git clone https://github.com/StartAction/SpliderQB.git

克隆之後,進入項目目錄,運行下麵命令即可。

node app.js

5. 總結

通過實現一個完整的爬蟲功能,加深自己對 Node 的理解,且實現的部分語言都是使用 es6 的語法,讓自己加快對 es6 語法的學習進度。另外,在這次實現中,遇到了 Node 的非同步控制的知識,本文是採用的是 asyncawait 關鍵字,也是我最喜歡的一種,然而在 Node 中,實現非同步控制有好幾種方式。關於具體的方式以及原理,有時間再進行總結。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 除法不可用手工演算法來計算,其基本思想是反覆做減法,看從被除數裡面最多能減去多少個除數,商就是多少。 除法函數: 如果前者絕對值小於後者直接返回零 做減法時,不需要一個一個減,可以以除數*10^n為基數來減 如果喜歡我的文章,可以掃描二維碼關註我的微信公眾號 爭取每天都分享一點我自己的開發和練習體驗~ ...
  • 用到一些封裝好的運動函數,主要是定時器 效果為圖片和圖片的描述定時自動更換 commom.js tween.js ...
  • mvc/mvvm "阮大神博客" mvc 分為三層,其實M層是數據模型層,它是真正的後端數據在前端js中的一個映射模型,他們的關係是:數據模型層和視圖層有映射關係,model改變,view展示也會更改,當view產生用戶操作或會反饋給controller,controller更改model,這個時候 ...
  • 1.首先先要下載artTemplate.js,這個可以在官網下載也可以在GitHob進行下載。 2.現在是編寫一個存放html標簽的編寫模板,使用<script type="text/html" id="site_template"></script>裝載,裡面的id是你到時候將確認將數據傳給誰的綁 ...
  • WebpackOptionsDefaulter模塊 通過參數檢測後,會根據單/多配置進行處理,本文基於單配置,所以會進行到如下代碼: 模塊的作用是進行預設值的設置,流程圖如下: 進入該模塊: 可以看到,這個模塊的內容是用ES6的新語法寫的,很好理解,因為這個模塊是只是針對webpack的預設設置,所 ...
  • 最近學習vue.js,下麵是筆記: 重點在3. 可能出現的問題: 1,首先我這邊歷經了慘痛的教訓後,建議各位vue學友,一定要使用Administrator,系統管理員身份登錄,不要使用二級管理員,很容易在安裝腳手架或者其他工具時,出現許可權問題,,登錄Administrator操作電腦後很多亂七八糟 ...
  • 前言 通常,jQuery的函數ajax進行Ajax調用。函數ajax只能做一個Ajax調用。當Ajax調用成功時,執行回調函數。可選地,當Ajax調用返回錯誤時,調用另一個回調函數。但是,該功能不能根據這些請求的結果進行多個Ajax請求和註冊回調函數。一種情況是,網頁使多個Ajax請求在禁用用戶交互 ...
  • 今天看到一個關於foo的一個面試題,趕腳特別有意思 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...