用nodeJs寫個簡易的爬蟲

 最近都在學nodeJs,剛好看到http模塊,於是就心血來潮,想寫個簡單的爬蟲。

 

  簡單的爬蟲實現原理很簡單:發送http請求至目標地址獲取HTML頁面數據,然後從獲取來的頁面數據中提取需要的數據保存。

 

  用nodeJs寫爬蟲,主要就是用到http.get發送請求至目標地址,然後在res.on("data")中監聽數據傳輸並且保存數據,最後在res.on("end")數據傳送完畢後對數據進行處理,保存。

 

  先來說步驟吧。

 

    我用瞭express框架,先進入項目目錄,在命令行敲入express -e myCreeper 生成express的目錄。然後進入myCreeper的目錄下再敲入命令npm install。然後項目就搭建好瞭。

 

    

 

  搭建好項目後,就可以開始寫瞭,爬蟲的主要功能代碼就是下面這兩段:

 

【前端代碼】

 

復制代碼

<body>

      <h1>我的博客</h1>

       <p class="showMess"></p>

    <script src="/javascripts/zepto.min.js"></script>

    <script>

         $.ajax({

            data:{page:1},

            dataType:"json",

            type:"get",

            url:"/creeper",

            success:function(data){

                console.log(data)

                var html = "";

                for(var i=0;i<data.blogs.length;i++){

                    var blog = data.blogs[i];

                    html += "<p><a href='"+blog.src+"' target='_blank'>"+blog.title+"</a><br>"

                        +"<p class='break'>"+blog.content+"</p><p class='moreMess' style='text-align:right'>"+

                        blog.time+"&nbsp;&nbsp;"+blog.read+"&nbsp;&nbsp;"+blog.say+"</p></p>"

                }

 

                $(".showMess").html(html);

            },

            error:function(){

                alert("錯誤")

            }

        })

    </script>

  </body>

復制代碼

 

 

【後臺代碼】

 

復制代碼

var http = require("http"),

    cheerio = require("cheerio");

 

exports.getBlog = function(req , res){

    var page = req.param("page")||1;

    var _res = res;

    http.get('https://www.cnblogs.com/axes/default.html?page='+page, function(res){

        var chunks = [],

            size = 0;

        res.on("data" , function(chunk){

            chunks.push(chunk);

            size += chunk.length;

        });

 

        res.on("end" , function(){

            //拼接buffer

            var data = Buffer.concat(chunks , size);

            

            var html = data.toString();

            var $ = cheerio.load(html);

            var blogs = [];

            for(var i=0;i<$('.postTitle2').length;i++){

                var blog = {};

                blog.title = $('.postTitle2').eq(i).html();

                blog.src = $('.postTitle2').eq(i).attr("href");

                blog.content = $(".c_b_p_desc").eq(i).html();

 

                var mess = $(".postDesc").eq(i).html().split("<a")[0].split(" ");

 

                blog.time = mess[2]+" "+mess[3];

                blog.read = mess[5];

                blog.say = mess[6];

 

                blogs.push(blog);

            }

            _res.json({

                blogs:blogs

            })

        })

    }).on('error' , function(e){

        console.log("error:"+e.message)

    });

};

復制代碼

  我是直接爬自己博客裡的數據瞭,所以目標地址就是自己的博客地址。首先通過前端ajax發送page數據給後臺,然後後臺接收到page值後,通過http.get發送請求。然後用res.on("data")開始監聽數據傳輸,當有數據傳來的時候,就把數據保存到chunks數組裡面。同時用res.on("end")在數據傳輸結束時對數據進行處理。

 

  上面傳輸數據那裡得註意一下。buffer的拼接容易出問題。我剛開始寫的時候,習慣性是寫成

 

 var data = "";

        res.on("data" , function(chunk){

            data+=chunk

        });

  這樣寫,如果爬出來的中文數據量比較小,顯示還是正常的,但是當數據量比較大的時候,就會出現亂碼瞭。因為獲取的chunk是一個buffer,data+=buffer就相當於把所有的數據buffer通過buffer.toString()拼接起來瞭。如果某一塊buffer是不完整的。當它用toString轉成字符串的時候,就會出現截斷現象,也就是某些中文字符沒瞭。

 

  所以解決辦法就是先用一個數組把所有buffer保存起來,同時記錄buffer的總長度,在數據傳輸完畢的時候,再通過Buffer.concat方法把所有buffer拼接好,再用toString轉成字符串。這時獲取的data數據就是正確的瞭。順便貼出一下Buffer.concat的參數說明:  

 

  

 

 

 

  當把數據轉成字符串的時候,我們要取數據,如何取呢?這裡直接用一個很強大的第三方庫:cheerio,這個模塊采用瞭跟jQuery類似的選擇器。基本上平時jquery怎麼用,就可以怎麼用cheerio。cheerio的項目地址:https://github.com/MatthewMueller/cheerio

 

  安裝方法就直接:npm install cheerio就行瞭。引入cheerio後直接通過load函數處理data數據,再接下來就是很簡單的事瞭。就像前端控制dom一樣輕松的控制dom獲取數據吧。把所有數據獲取到後就直接發送至前端頁面。然後顯示出來。

發佈留言