1. 程式人生 > >node.js學習筆記(3)——使用cheerio處理爬取的網頁內容

node.js學習筆記(3)——使用cheerio處理爬取的網頁內容

一、簡介

node.js本身自帶爬取網站網頁內容的功能。

var http = require('http');

router.get('/test', function(req, res){
  var url = 'http://www.baidu.com';
  http.get(url, function(response){
    var html = '';
    response.on('data', function(data){
      html += data;
    });
    response.on('end', function(){
      res.render('test', {
        'html':html
      });
    })
  })
})

比如如上程式碼就實現了爬取baidu.com網頁程式碼內容,使用res.render直接將資料渲染到ejs模板中後的內容如下:

基本和原始碼一樣,非常難以手工處理。這就是為什麼我們需要cheerio模組來對爬取到的內容進行處理

二、cheerio

使用方式比較簡單:

1. 使用npm install安裝cheerio模組並新增到依賴中

2. 在js檔案中通過var cheerio = require('cheerio'); 獲取模組引用

3. var $ = cheerio.load(html,{decodeEntities:false});

(1)可以建立一個和jQuery選擇器用法差不多的選擇器 $.

(2)load函式的第一個引數html就是之前http.get方法中所獲得的資料;第二個引數可選,主要是用來設定格式,比如decodeEntities:false設定了不會出現中文亂碼。

三、簡單實戰

案例:爬取北京新發地市場的菜價內容。

1. 翻一下原始碼,檢視所需要的內容的類或者名字

2. 編寫程式碼

router.get('/test', function(req, res){
  var url = 'http://www.xinfadi.com.cn/';
  http.get(url, function(response){
    var html = '';
    response.on('data', function(data){
      html += data;
    });
    response.on('end', function(){
      
      var $ = cheerio.load(html,{decodeEntities:false});
      var content = $('.conLi').text();
      res.render('test', {
        'html':content
      });
    })
  })
})

然後就會出現如下的內容:

3. cheerio的用法完全可以和寫css樣式一樣,通過多個類、名等方式選擇。

比如可以這樣寫:var content = $('#tab1_div_0 .conLi em').text();

然後就會出現更為細緻的效果

4. 一點嘗試 

看到cheerio提供了toArray方法,對於li, em這樣的元素,可以轉換為陣列。嘗試一下後結果

陣列是物件型別的,而且由於物件中包含了對自身的引用,使用JSON.stringify方法不能夠將物件以字串形式輸出。必須引入util模組,用util.inspect()方法對物件進行轉換。隨便轉換一下後發現內容是這樣的:

知道了結構之後按照結構去找資料,最後效果如下:(如果想去掉引號的話使用replace方法加正則表示式即可)

前端表格ejs程式碼:(使用了前端框架bootstrap)

<div class="container">
      <table class="table table-bordered">
        <thead>
          <tr>
            <th colspan="<%= list.length %>" class="table-title">蔬菜表</th>
          </tr>
        </thead>
        <tbody>
          <tr class="success">
            <% for(var i=0; i<cols; i++) { %>
            <td><%= list[i].toString() %></td>
            <% } %>
          </tr>
          <% var counter = 0; %>
          <% while(counter < content.length) { %>
            <tr>
              <% for(var i=0; i<list.length; i++) { %>
                <td><%= content[i+counter] %></td>
              <% } %>
              <% counter = counter + list.length %>
            </tr>
          <% } %>
        </tbody>
      </table>
    </div>

後端程式碼:(部分)

response.on('end', function(){
      
      var $ = cheerio.load(html,{decodeEntities:false});
      var list = $('.tabLi em').toArray();
      var content = $('#tab1_div_0 .conLi em').toArray();
      var list2 = new Array();
      for(var i=0; i<list.length; i++){
        list2[i] = util.inspect(list[i].children[0].data);
      }
      var content2 = new Array();
      for(var i=0; i<content.length; i++){
        content2[i] = util.inspect(content[i].children[0].data);
      }
      res.render('test', {
        'list':list2,
        'cols':list.length,
        'content':content2,
      });
    })

四、總結

爬取網站內容的精髓(不考慮面對反爬取機制的處理)的在於分析,分析它的結構並貼身打造、對症下藥。

五、附贈:url中出現中文的問題

在新發地網站進行商品的檢索時,發現url中有中文

使用 encodeURI(name) 方法可以實現將中文字串編碼。