zoukankan      html  css  js  c++  java
  • Node.js m03122图片批量下载爬虫1.00

    //======================================================
    // m03122图片批量下载爬虫1.00
    // 2017年11月18日
    //======================================================
    
    // 内置http模块
    var http=require("http");
    
    // 内置文件处理模块,用于创建目录和图片文件
    var fs=require('fs');
    
    // cheerio模块,提供了类似jQuery的功能,用于从HTML code中查找图片地址和下一页
    var cheerio = require("cheerio");
    
    // 请求参数JSON。http和https都有使用
    var options;
    
    // request请求
    var req;
    
    // 图片数组,找到的图片地址会放到这里
    var pictures=[];
    
    // 存放图片的目录
    var folder="";
    
    //--------------------------------------
    // 爬取网页,找图片地址,再爬
    // pageUrl sample:http://m.03122.com/xinggan/14428/
    // pageUrl sample:
    //--------------------------------------
    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=buffer.toString();
                //console.log(body);
                
                var $ = cheerio.load(body);        
                var picCount=0;
    
                // 找图片放入数组
                $(".post-content a mip-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;
                // 找下一页
                $(".infoPages a").each(function(index,element){
                    var text=$(element).text();
                    if(text.indexOf('下一页')!=-1){
                        nextPageUrl=$(element).attr("href");                    
                        //console.log("找到下一页="+nextPageUrl);
                    }         
                })
    
                // 用正则表达式分析判别是否最后一页
                var curr=0;
                var total=0;
                $(".infoPages span").each(function(index,element){
                    var htm=$(element).html();// <em>2</em>/47
    
                    var reg=/<em>(d+)<[/]em>[/](d+)/g;
                    var res;
                    while((res = reg.exec(htm)) != null){
                        curr=parseInt(res[1]);
                        //console.log("curr="+curr);
                        total=parseInt(res[2]);
                        //console.log("total="+total);
                    }                       
                })
    
                if(nextPageUrl==null || curr>=total){
                    console.log(pageUrl+"已经是最后一页了.
    ");
                    saveFile(pageUrl,pictures);// 保存
                    download(pictures);
                }else{
                    console.log("继续下一页");
                    crawl(nextPageUrl);
                }
                
            }).on("error", function() {
                saveFile(pageUrl,pictures);// 保存
                console.log("crawl函数失败,请进入断点续传模式继续进行");
            })
        });
    
        // 超时处理
        req.setTimeout(7500,function(){
            req.abort();
        });
    
        // 出错处理
        req.on('error',function(err){
            console.log('请求发生错误'+err);  
            saveFile(pageUrl,pictures);// 保存
            console.log("crawl函数失败,请进入断点续传模式继续进行");
        });
    
        // 请求结束
        req.end();
    }
    
    //--------------------------------------
    // 下载图片
    //--------------------------------------
    function download(pictures){
    
        var total=0;
        total=pictures.length;
        console.log("总计有"+total+"张图片将被下载.");
        appendToLogfile(folder,"总计有"+total+"张图片将被下载.
    ");
        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://img.cdjqjy.com/pic/scimg/2017/02-22/1487731179884350759.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;
    
        //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',
        };
    
        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+"  下载失败.
    ");
                    }else{
                        appendToLogfile(folder,"文件  "+picUrl+"  下载成功.
    ");
                        console.log("文件"+fileName+"下载成功");
                    }
                });    
            });
        });
    
        // 超时处理
        req.setTimeout(7500,function(){
            req.abort();
        });
    
        // 出错处理
        req.on('error',function(err){
            if(err){
                console.log('[downloadPic]文件   '+picUrl+"  下载失败,"+'因为'+err);
                appendToLogfile(folder,"文件"+picUrl+"下载失败.
    ");
            }
        });
    
        // 请求结束
        req.end();
    }
    
    //--------------------------------------
    // 程序入口 
    //--------------------------------------
    function getInput(){
        process.stdin.resume();    
        process.stdout.write("33[33m 新建模式输入第一页URL,断点续传模式输入0,请输入: 33[39m");// 草黄色
        process.stdin.setEncoding('utf8');
        
        process.stdin.on('data',function(text){
            var input=text.trim();
            process.stdin.end();// 退出输入状态    
    
            if(text.trim()=='0'){
                process.stdout.write("33[36m 进入断点续传模式. 33[39m");    // 蓝绿色
    
                // Read File
                fs.readFile('./save.dat','utf8',function(err,data){
                    if(err){
                        console.log('读取文件save.dat失败,因为'+err);
                    }else{
                        //console.log(data);
                        var obj=JSON.parse(data);
    
                        pictures=obj.pictures;
                        console.log('提取图片'+pictures.length+'张');
    
                        folder=obj.folder;
    
                        // 创建目录
                        fs.mkdir('./'+folder,function(err){
                            if(err){
                                console.log("目录"+folder+"已经存在");
                            }
                        });
    
                        crawl(obj.url);        
                    }
                });
                
                // Resume crawl
            }else{
                process.stdout.write("33[35m 进入新建模式. 33[039m");    //紫色
    
                folder='pictures('+getNowFormatDate()+")";
                // 创建目录
                fs.mkdir('./'+folder,function(err){
                    if(err){
                        console.log("目录"+folder+"已经存在");
                    }
                });
    
                crawl(input);            
            }
        });    
    }
    
    //--------------------------------------
    // 将爬行中信息存入数据文件
    //--------------------------------------
    function saveFile(url,pictures){
        var obj=new Object;
        obj.url=url;
        obj.pictures=pictures;
        obj.folder=folder;
        var text=JSON.stringify(obj);
    
        fs.writeFile('./save.dat',text,function(err){
            if(err){
                console.log('写入文件save.dat失败,因为'+err);
            }
        });
    }
    
    // 调用getInput函数,程序开始
    getInput();

    2017年11月18日15:11:16

  • 相关阅读:
    pat 甲级 1065. A+B and C (64bit) (20)
    pat 甲级 1064. Complete Binary Search Tree (30)
    pat 甲级 1010. Radix (25)
    pat 甲级 1009. Product of Polynomials (25)
    pat 甲级 1056. Mice and Rice (25)
    pat 甲级 1078. Hashing (25)
    pat 甲级 1080. Graduate Admission (30)
    pat 甲级 团体天梯 L3-004. 肿瘤诊断
    pat 甲级 1099. Build A Binary Search Tree (30)
    Codeforce 672B. Different is Good
  • 原文地址:https://www.cnblogs.com/heyang78/p/7856762.html
Copyright © 2011-2022 走看看