寫個爬蟲唄

黃小帥發表於2019-02-25

之前寫了個小爬蟲,用來爬噹噹的圖書資訊用的,挺好玩,分享一下吧。整個爬蟲非常簡單,主要是使用request庫+cheerio解析,實現非常粗糙,今天正好理一下思路。

首先,準備工作,就是各種庫的安裝以及其他前置工作的準備,比如頁面分析。

整個流程實際上比較簡單,適合像我這樣的菜鳥觀看。

準備工作

npm install request
npm install cheerio
npm install iconv-lite複製程式碼

request是用來請求頁面的庫,也是本次爬蟲最核心的庫;cheerio是用於解析的庫,將頁面轉化成DOM來簡化資料的解析;iconv-lite是解碼庫,因為噹噹網用的不是utf8編碼,這點倒是讓我吃了不少苦頭。

分析清單

下載完需要的庫就可以開始擼了,不過擼之前需要先分析頁面結構,我列一下分析清單:

  1. 頁面結構:分析資料在哪些結構中
  2. 資料形式:圖片,文字還是數字
  3. 爬取深度:抓取的資料在當前頁面還是需要進入連結(比如商品列表與商品詳情,我們需要的資料在詳情頁,但我們只能通過列表頁去爬,這時候深度就是2)
  4. 儲存位置:資料儲存在哪:檔案or資料庫
  5. 編碼格式:編碼不對資料就全是亂碼了,這樣的資料要了也沒用

分析完需要分析的東西就可以接著往下了

初步使用

request({
    encoding:null,
    url:`http://book.dangdang.com/list/newRelease_C01.54.htm`
},function(err,response,body){
    if(err){console.log(err)}
    else{
        //處理資料
        console.log(body)
    }
})複製程式碼

這裡解釋一下,encoding:null是取消編碼,因為預設會按照utf8編碼,但頁面本身是gb2312的,所以解析了也沒用。不寫會出問題,因為以gb2312解碼的時候資料都被utf8編碼過,簡直是災難。

response是伺服器端的響應,比如各種頭資訊啊之類的,這裡用不到它。body是頁面主體,也就是整個html,是我們需要處理的主角。

但之前也提到了,頁面編碼是gb2312,因此在解析資料之前先要解碼。

var decodeBuffer=iconv.decode(body,"gb2312");//將body以gb2312解析轉化成buffer(unicode)
var html=decodeBuffer.toString();
var $=cheerio.load(html);複製程式碼

這時候html是原gb2312解碼後又被編碼成utf8的字串,如果列印出來就能發現,裡邊的中文不再是亂碼了。這時候就輪到cheerio登場了:cheerio提供的api和JQuery基本相同,在這裡可以直接當成JQuery,因此為了更加靠近JQuery,我們將解析後的資料儲存到$這個變數中。

var $=cheerio.load(html);
$(".tushu").each(function(index,ele){
    var bookName=$(ele).find(".name").text();
    console.log(bookName);
})複製程式碼

這時候書名就被列印出來了,是不是很方便。圖片我們就用src吧,當然,如果想把圖片儲存下來也是可以的,用上fs模組就行了

var fs = require("fs");
var path=require("path");
$(".tushu").each(function(index,ele){
    var src=$(ele).find(".cover img").attr("src");
    var srcParse=path.parse(src);
    var srcStore="img/"+srcParse.base;
    request(src).pipe(fs.createWriteStream(srcStore));
})複製程式碼

完整程式碼

至此,整個爬蟲差不多了,因為噹噹把下一頁的連結寫在了a標籤裡,因此同樣可以使用選擇器這種方式去獲取href,以此得知下一頁的路徑。因此封裝一下:

var request=require("request");
var cheerio=require("cheerio");
var iconv=require("iconv-lite");
var path=require("path");
var fs=require("fs");

var main="http://book.dangdang.com";

function spider(url){
    request({
        encoding:null,
        url:url
    },function (err, res, body) {
        var decodeBuffer=iconv.decode(body,"gb2312");
        var result=decodeBuffer.toString();
        var $=cheerio.load(result);
        $(`.tushu`).each(function(index,ele){
            var src=$(ele).find(".cover img").attr("src");
            var srcpath=path.parse(src);
            var srcStore="img/"+srcpath.base;
            request(src).pipe(fs.createWriteStream(srcStore));
        });
        var next=$(`.fanye_bottom > span:nth-child(1) > a:last-child`).attr("href");
        var nextUrl=main+next;
        spider(nextUrl);
    })
}複製程式碼

這時候再呼叫一下spider函式,就可以一頁一頁往下了。同時我也把詳細文章寫在了自己部落格上,防止下次寫的時候忘了怎麼用,可以點選訪問

小結

當然,這個爬蟲很簡單,基本上糊弄一下沒有任何限制的網站還行。之後要寫一個同城租房的畢設專案,準備爬58租房資訊。58對ip作了限制,因此訪問量太大會出驗證碼或者封ip,所以需要加上代理等進一步偽裝一下。代理的確非常頭疼,因為可用率非常低,還記得當初隨便找了一個網站,爬了1w多條ip,結果前幾個還能用,後面的測試一下基本不可用,最後在篩選的時候就篩選出7-8條,真的心累。後來找到了快代理,可用率還不錯,基本能達到12%左右,可以說是非常高的可用率了,畢竟免費。當然有更好的免費代理可以和我說說呀。

第一次寫文章,有什麼不對的地方歡迎看官指正。

相關文章