这个爬虫在Referer设置上和其它爬虫相比有特殊性。代码:

//======================================================
// mimimn图片批量下载Node.js爬虫1.00
// 2017年11月15日
//======================================================

// 内置http模块
var https=require("https");

// 内置文件处理模块,用于创建目录和图片文件
var fs=require('fs');

// cheerio模块,提供了类似jQuery的功能,用于从HTML code中查找图片地址和下一页
var cheerio = require("cheerio");

// 请求参数JSON。http和https都有使用
var options;

// request请求
var req;

// 图片数组,找到的图片地址会放到这里
var pictures=[];

//--------------------------------------
// 爬取网页,找图片地址,再爬
// pageUrl sample:https://www.mimimn.com/files/38/3832.html
// pageUrl sample:https://www.mimimn.com/files/37/3775.html
//--------------------------------------
function crawl(pageUrl){
    console.log("Current page="+pageUrl);

    // 得到hostname和path
    var currUrl=pageUrl.replace("https://","");
    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:443,
            path:path,// 子路径
          method:'GET',
    };

    req=https.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;

            // 找图片放入数组
            $(".text-center 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 htmls=[];
            var currIndex=-1;
            $(".pagination ul li").each(function(index,element){
                var text=$(element).html();
                //console.log(text);
                htmls.push(text);

                var cls=$(element).attr("class");
                if(cls=='active'){
                    currIndex=index;
                }
            })

            //console.log("htmls.length="+htmls.length);
            //console.log("currIndex="+currIndex);

            if((htmls.length-1)==currIndex){
                console.log(pageUrl+"已经是最后一页了.");
                download(pictures);
            }else{
                var text=htmls[currIndex+1];
                var start=text.indexOf("\"");
                var end=text.lastIndexOf("\"");
                var nextPageUrl=text.slice(start+1,end);
                //console.log("下一页是"+nextPageUrl);
                crawl(nextPageUrl);
            }

        }).on("error", function() {
            console.log("获取失败")
        })
    });

    // 超时处理
    req.setTimeout(5000,function(){
        req.abort();
    });

    // 出错处理
    req.on('error',function(err){
        if(err.code=="ECONNRESET"){
            console.log('socket端口连接超时。');
        }else{
            console.log('请求发生错误,err.code:'+err.code);
        }
    });

    // 请求结束
    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:https://mi.uz0.net/20171029/1509249915gi25.jpg
//--------------------------------------
function downloadPic(picUrl,folder){
    console.log("图片:"+picUrl+"下载开始");

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

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

    var picName=currUrl.slice(currUrl.lastIndexOf("/"));

    // 初始化options
    options={
        hostname:hostname,
            port:443,
            path:path,// 子路径
          method:'GET',
              // HTTP请求中有一个referer的报文头,用来指明当前流量的来源参考页.
              headers:{
                'Referer':'https://www.mimimn.com',// 设置Referer,没有这一步图片下载不下来,因为网站用Rederer做了低端的图片防盗链
              }

    };

    req=https.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();

关于Referer设置的参考文章如下:

http://blog.csdn.net/u011250882/article/details/49679535

https://www.cnblogs.com/rubylouvre/p/3541411.html

http://blog.csdn.net/fishmai/article/details/52388840

https://www.cnblogs.com/bukudekong/p/3829852.html

https://zhidao.baidu.com/question/1832550088624773020.html

2017年11月15日05:19:50

Node.js mimimn图片批量下载爬虫 1.00的更多相关文章

  1. Node.js mzitu图片批量下载爬虫1.00

    又攻下一座山头. //====================================================== // mzitu图片批量下载爬虫1.00 // 2017年11月19 ...

  2. Node.js 4493图片批量下载爬虫1.00

    这个爬虫依然需要iconv转码,想不到如今非utf8的网页还这么多.另外此网页找下一页的方式比较异常,又再次借助了正则表达式. 代码如下: //============================ ...

  3. Node.js monly图片批量下载爬虫1.00

    此爬虫又用到了iconv转码,代码如下: //====================================================== // mmonly图片批量下载爬虫1.00 ...

  4. Node.js m03122图片批量下载爬虫1.00

    //====================================================== // m03122图片批量下载爬虫1.00 // 2017年11月18日 //==== ...

  5. Node.js mm131图片批量下载爬虫1.00 iconv协助转码

    //====================================================== // mm131图片批量下载爬虫1.00 // 2017年11月15日 //===== ...

  6. Node.js nvshens图片批量下载爬虫 1.00

    //====================================================== // www.nvshens.com图片批量下载Node.js爬虫1.00 // 此程 ...

  7. Node.js mm131图片批量下载爬虫1.01 增加断点续传功能

    这里的断点续传不是文件下载时的断点续传,而是指在爬行页面时有时会遇到各种网络中断而从中断前的页面及其数据继续爬行的过程,这个过程和断点续传原理上相似故以此命名.我的具体做法是:在下载出现故障或是图片已 ...

  8. Node.js abaike图片批量下载爬虫1.02

    //====================================================== // abaike图片批量下载爬虫1.02 // 用最近的断点续传框架改写原有1.01 ...

  9. Node.js nvshens图片批量下载爬虫1.01

    //====================================================== // nvshens图片批量下载爬虫1.01 // 用最近的断点续传框架改写原有1.0 ...

随机推荐

  1. sonar rule

    bug类型: 1.".equals()" should not be used to test the values of "Atomic" classes.  ...

  2. Eclipse中快速 打出 main方法的签名

    有时,我们创建一个空白类,需要打出main方法 public static void main(String [] args){ } 在Eclipse先敲main字符,然后按住ALT+/,再按回车即可 ...

  3. 如何使用Web字体?

    如何使用Web字体 嵌入Web字体的关键是@font-face规则,通过它可以指定浏览器下载web字体的地址,以及如何在样式表中引用该字体 @font-face { font-family: Voll ...

  4. 数据库SQL归纳(二)

    数据定义功能 对象 创建 修改 删除 架构 CREATE SCHEMA DROP SCHEMA 表 CREATE TABLE ALTER TABLE DROP TABLE 视图 CREATE VIEW ...

  5. HDU 6035 Colorful Tree(补集思想+树形DP)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6035 [题目大意] 给出一颗树,一条路径的价值为其上点权的种类数,求路径总价值 [题解] 单独考虑 ...

  6. BZOJ 1042:[HAOI2008]硬币购物(容斥原理+DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1042 [题目大意] 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4. 某人去 ...

  7. rmq问题:ST表

    存板子.O(nlogn)预处理,O(1)查询.空间O(nlogn). int d[1000006][25]; int mn[1000006]; void rmq_init() { for(int i= ...

  8. [转]Spring 中的p标签

    spring的bean配置文件中p:代表什么 <bean id="daoTemplate" abstract="true" lazy-init=" ...

  9. 微软工具ILMerge

    释义 ILMerge是一个可用于将多个.NET程序集合并为单个程序集的实用程序. ILMerge接收一组输入程序集并将它们合并到一个目标程序集中.输入程序集列表中的第一个程序集是主程序集. 当主组件是 ...

  10. [EF]使用EF简单增删改查

    目录 认识EF 添加数据 删除数据 修改数据 查询数据 总结 认识EF ADO.NET Entity Framework 是微软以ADO.NET为基础所发展出来的对象关系对伊(O/R Mapping) ...