这个与前作的差别在于地址的不规律性,需要找到下一页的地址再爬过去找。

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

// 内置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=[];

//--------------------------------------
// 爬取网页,找图片地址,再爬
// pageUrl sample:http://www.avbaike.net/27812.html
// pageUrl sample:http://www.avbaike.net/27812.html/2
//--------------------------------------
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){
        resp.setEncoding('utf8');
        var body="";

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

        resp.on('end',function(){
            //console.log("body="+body);
            var $ = cheerio.load(body);            

            // 找图片放入数组
            $("#post_content p a").each(function(index,element){
                var picUrl=$(element).attr("href");
                //console.log(picUrl);
                pictures.push(picUrl);
            })   

            var nextPageUrl=null;
            // 找下一页
            $(".pagelist a").each(function(index,element){
                var text=$(element).text();
                if(text.indexOf('下一页')!=-1){
                    nextPageUrl=$(element).attr("href");
                }
            })

            if(nextPageUrl==null){
                console.log(pageUrl+"已经是最后一页了.");
                download(pictures);
            }else{
                //console.log("下一页是"+nextPageUrl);
                crawl(nextPageUrl);
            }
        });
    });

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

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

    // 请求结束
    req.end();
}

//--------------------------------------
// 下载图片
//--------------------------------------
function download(pictures){
    var folder='pictures';
    // 创建目录
    fs.mkdir('./'+folder,function(err){
        if(err){
            console.log("目录"+folder+"已经存在");
        }
    });

    console.log("总计有"+pictures.length+"张图片将被下载.");
    for(var i=0;i<pictures.length;i++){
        var picUrl=pictures[i];
        downloadPic(picUrl);
    }
}

//--------------------------------------
// 下载单张图片
// picUrl sample:http://www.avbaike.net/wp-content/uploads/2016/08/108.jpg
//--------------------------------------
function downloadPic(picUrl){
    console.log("图片:"+picUrl+"下载开始");

    // 得到hostname和path
    var currUrl=picUrl.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);

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

    // 初始化options
    options={
        hostname:hostname,
            port:80,
            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="./pictures"+picName;
            fs.writeFile(fileName, imgData, "binary", function(err){
                if(err){
                    console.log("文件"+fileName+"下载失败.");
                    console.log(err);
                }else{
                    console.log("文件"+fileName+"下载成功");
                }
            });
        });
    });

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

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

    // 请求结束
    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();

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

  1. Node.js abaike图片批量下载Node.js爬虫1.01版

    //====================================================== // abaike图片批量下载Node.js爬虫1.01 // 1.01 修正了输出目 ...

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

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

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

    这个爬虫在abaike爬虫的基础上改改图片路径和下一页路径就出来了,代码如下: //====================================================== // ...

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

    即使是https网页,解析的方式也不是一致的,需要多试试. 代码: //====================================================== // aitaot ...

  5. Node.js mimimn图片批量下载爬虫 1.00

    这个爬虫在Referer设置上和其它爬虫相比有特殊性.代码: //====================================================== // mimimn图片批 ...

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

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

  7. Node.js meitulu图片批量下载爬虫1.06版

    //====================================================== // https://www.meitulu.com图片批量下载Node.js爬虫1. ...

  8. Node.js meitulu图片批量下载爬虫 1.05版(Final最终版)

    //====================================================== // https://www.meitulu.com图片批量下载Node.js爬虫1. ...

  9. Node.js meitulu图片批量下载爬虫1.04版

    //====================================================== // https://www.meitulu.com图片批量下载Node.js爬虫1. ...

随机推荐

  1. python多线程实现多任务

    #转载请联系 1.什么是线程? 进程是操作系统分配程序执行资源的单位,而线程是进程的一个实体,是CPU调度和分配的单位.一个进程肯定有一个主线程,我们可以在一个进程里创建多个线程来实现多任务. --- ...

  2. 【C++】继承中的隐藏与覆盖

    没有访问控制符时默认为私有继承. 当基类中的某个函数有若干个重载版本,继承类中也实现了该函数的某个重载版本时,参数完全相同的基类版本被覆盖,基类的其他版本被隐藏. 1.若要在继承类中使用基类的被覆盖方 ...

  3. Selenium2+python自动化63-简易项目搭建【转载】

    前言 到unittest这里基本上可以搭建一个简易的项目框架了,我们可以用一条run_main.py脚本去控制执行所有的用例,并生成报告,发送邮件一系列的动作 一.新建工程 1.打开pycharm左上 ...

  4. C#给IIS添加禁止IP限制

    /// <summary> /// 给IIS添加禁止IP限制 /// 仅针对iis 7及以上版本 /// 首先需要引入Microsoft.Web.Administration.dll // ...

  5. 安卓长按交互onCreateContextMenu的简单 用法

    1.可在activity和fragment中使用. 2.使用方法 (1)注册 registerForContextMenu(btn);//btn是要实现交互的控件 (2)重写onCreateConte ...

  6. RMQ问题心得

    RMQ(Range Minimum/Maximum Query)问题是指:对于长度为n的数列A,回答若干询问RMQ(A,i,j),返回数列A中下标i,j里的最小/大值,即RMQ问题是指求区间最值的问题 ...

  7. AMQ学习笔记 - 03. 消息的接收方式

    概述 消息有两种接收方式:同步接收和异步接收. 同步接收:主线程阻塞式等待下一个消息的到来,可以设置timeout,超时则返回null. 异步接收:主线程设置MessageListener,然后继续做 ...

  8. UVA 699 The Falling Leaves (递归先序建立二叉树)

    题目链接:http://acm.hust.edu.cn/vjudge/problem/19244 #include <iostream> #include <cstdio> # ...

  9. JavaScript函数中的参数(arguments)

    arguments argument是JavaScript中的一个关键字,用于指向调用者传入的所有参数. function example(x){ alert(x); alert(arguments. ...

  10. 【后缀数组】【线段树】poj3974 Palindrome

    考虑奇数长度的回文,对于字符串上的每个位置i,如果知道从i开始的后缀和到i为止的前缀反转后的字符串的lcp长度的话,也就知道了以第i个字符为对称中心的最长回文的长度了.因此,我们用在S中不会出现的字符 ...