Node.js mm131圖片批量下載爬蟲1.00 iconv協助轉碼

//======================================================
// mm131圖片批量下載爬蟲1.00
// 2017年11月15日
//======================================================

// 內置http模塊
var http=require("http");

// 內置文件處理模塊,用於建立目錄和圖片文件
var fs=require('fs');

// 用於轉碼。非Utf8的網頁如gb2132會有亂碼問題,須要iconv將其轉碼
var iconv = require('iconv-lite');

// cheerio模塊,提供了相似jQuery的功能,用於從HTML code中查找圖片地址和下一頁
var cheerio = require("cheerio");

// 請求參數JSON。http和https都有使用
var options;

// request請求
var req;

// 圖片數組,找到的圖片地址會放到這裏
var pictures=[];

//--------------------------------------
// 爬取網頁,找圖片地址,再爬
// pageUrl sample:http://www.mm131.com/xinggan/2852.html
// pageUrl sample:http://www.mm131.com/xinggan/2853.html
// pageUrl sample:http://www.mm131.com/xinggan/2976.html  
//--------------------------------------
function crawl(pageUrl){
    console.log("Current page="+pageUrl);

    // 獲得hostname和path
    var currUrl=pageUrl.replace("http://","");
    var pos=currUrl.indexOf("/");
    var hostname=currUrl.slice(0,pos);        
    var path=currUrl.slice(pos);    
    //console.log("hostname="+hostname);
    //console.log("path="+path);
    
    // 初始化options  
    options={
        hostname:hostname,
            port:80,
            path:path,// 子路徑
          method:'GET',        
    };

    req=http.request(options,function(resp){
        var html = [];

        resp.on("data", function(data) {
            html.push(data);
        })
        resp.on("end", function() {
            var buffer = Buffer.concat(html);
            var body = iconv.decode(buffer,'gb2312'); // 特意增長的,爲了讓漢字不亂碼,header裏面有<meta http-equiv="Content-Type" content="text/html; charset=gb2312">字樣都須要iconv幫忙轉碼
            //console.log(body);
            
            var $ = cheerio.load(body);        
            var picCount=0;

            // 找圖片放入數組
            $(".content-pic a img").each(function(index,element){
                var picUrl=$(element).attr("src");
                //console.log(picUrl);

                if(picUrl.indexOf('.jpg')!=-1){
                    pictures.push(picUrl); 
                    picCount++;
                } 
            })   
            console.log("找到圖片"+picCount+"張.");                
            
            var nextPageUrl=null;
            // 找下一頁
            $(".content-page a").each(function(index,element){
                var text=$(element).text();
                if(text.indexOf('下一頁')!=-1){
                    nextPageUrl=$(element).attr("href");
                    nextPageUrl="http://www.mm131.com/xinggan/"+nextPageUrl;// 把省略部分加上
                    console.log("找到下一頁.");
                }         
            })

            if(nextPageUrl==null){
                console.log(pageUrl+"已是最後一頁了.\n");
                download(pictures);
            }else{
                //console.log("下一頁是"+nextPageUrl);
                crawl(nextPageUrl);
            }
            
        }).on("error", function() {
            console.log("獲取失敗")
        })
    });

    // 超時處理
    req.setTimeout(7500,function(){
        req.abort();
    });

    // 出錯處理
    req.on('error',function(err){
        console.log('請求發生錯誤'+err);        
    });

    // 請求結束
    req.end();
}

//--------------------------------------
// 下載圖片
//--------------------------------------
function download(pictures){
    var folder='pictures('+getNowFormatDate()+")";
    // 建立目錄
    fs.mkdir('./'+folder,function(err){
        if(err){
            console.log("目錄"+folder+"已經存在");
        }
    });

    var total=0;
    total=pictures.length;
    console.log("總計有"+total+"張圖片將被下載.");
    appendToLogfile(folder,"總計有"+total+"張圖片將被下載.\n");
    for(var i=0;i<pictures.length;i++){
        var picUrl=pictures[i];
        downloadPic(picUrl,folder);
    }
}

//--------------------------------------
// 寫log文件
//--------------------------------------
function appendToLogfile(folder,text){
    fs.appendFile('./'+folder+'/log.txt', text, function (err) {
        if(err){
            console.log("不能書寫log文件");
            console.log(err);
        }
    });
}

//--------------------------------------
// 取得當前時間
//--------------------------------------
function getNowFormatDate() {
    var date = new Date();
    var seperator1 = "-";
    var seperator2 = "_";
    var month = date.getMonth() + 1;
    var strDate = date.getDate();
    if (month >= 1 && month <= 9) {
        month = "0" + month;
    }
    if (strDate >= 0 && strDate <= 9) {
        strDate = "0" + strDate;
    }
    var currentdate =date.getFullYear() + seperator1 + month + seperator1 + strDate
            + " " + date.getHours() + seperator2 + date.getMinutes()
            + seperator2 + date.getSeconds();
    return currentdate;
}

//--------------------------------------
// 下載單張圖片
// picUrl sample:http://img2.mm131.com:55888/pic/2852/1.jpg
//--------------------------------------
function downloadPic(picUrl,folder){
    console.log("圖片:"+picUrl+"下載開始");

    // 獲得hostname,path和port
    var currUrl=picUrl.replace("http://","");
    var pos=currUrl.indexOf("/");
    var hostname=currUrl.slice(0,pos);        
    var path=currUrl.slice(pos);

    // 有端口加端口,沒有端口默認80
    var port=80;
    if(hostname.indexOf(":")!=-1){
        var arr=hostname.split(":");
        hostname=arr[0];
        port=arr[1];
    }    

    //console.log("hostname="+hostname);
    //console.log("path="+path);
    //console.log("port="+port);

    var picName=currUrl.slice(currUrl.lastIndexOf("/"));
    
    // 初始化options  
    options={
        hostname:hostname,
            port:port,
            path:path,// 子路徑
          method:'GET',
              headers:{
                  'Referer':'http://www.mm131.com',      
            }
    };

    req=http.request(options,function(resp){
        var imgData = "";
        resp.setEncoding("binary"); 

        resp.on('data',function(chunk){
            imgData+=chunk;            
        });

        resp.on('end',function(){        

            // 建立文件
            var fileName="./"+folder+picName;
            fs.writeFile(fileName, imgData, "binary", function(err){
                if(err){
                    console.log("[downloadPic]文件"+fileName+"下載失敗.");
                    console.log(err);
                    appendToLogfile(folder,"文件  "+picUrl+"  下載失敗.\n");
                }else{
                    appendToLogfile(folder,"文件  "+picUrl+"  下載成功.\n");
                    console.log("文件"+fileName+"下載成功");
                }
            });    
        });
    });

    // 超時處理
    req.setTimeout(7500,function(){
        req.abort();
    });

    // 出錯處理
    req.on('error',function(err){
        if(err){
            console.log('[downloadPic]文件'+picUrl+"下載失敗,"+'由於'+err);
            appendToLogfile(folder,"文件"+picUrl+"下載失敗.\n");
        }
    });

    // 請求結束
    req.end();
}

//--------------------------------------
// 程序入口 
//--------------------------------------
function getInput(){
        
    process.stdout.write("\033[35m 請輸入第一頁URL:\033[039m");    //紫色
    process.stdin.resume();
    process.stdin.setEncoding('utf8');    

    process.stdin.on('data',function(text){
        process.stdin.end();// 退出輸入狀態        
        crawl(text.trim());// trim()是必須的!        
    });    
}

// 調用getInput函數,程序開始
getInput();

2017年11月15日20:54:16html

相關文章
相關標籤/搜索