3

一
const request = require('request');
request 对http进行封装的npm
request(url,(err,req)=>{
let body=req.body
})
 
二
const cheerio=require('cheerio');
对返回的html进行解析 并支持jq
let $ = cheerio.load(body, {
            decodeEntities: false
        });
三
lodash
非常的工具函数
_.isObject()
_.isString()
 
抓取的过程 由request对象向网址发送http请求 到html到达以后出发callback 并 用cheerio load我们的body
使用接进 jq的语法访问元素并获取我们的东西
 
四
lib封装的过程
 拆分:request部分交给spider.js入口
 解析部分 又parse.js处理
 spider.js这个模块返回一个函数,完成请求的发出。
 return request(opts)
 spider 要做的其实是完成这个抓取配置参数的封装。
 来抓取业务,抽象。
 module.export=spider;
 

之前写过简单的爬取页面课程目录的爬虫 戳这里

今天写一个图片爬虫

基本思路

在我们想要批量爬取资源的站点,通过审查代码和观察url请求来找出一些规律,不同网站复杂程度各不相同,通常爬图片这种算比较简单的,

  • 分析规律,构造请求的页面地址,nodejs模块request模拟请求页面数据(简单静态页复杂些的可能还需要模拟ajax请求截取数据),

  • 利用cheerio模块从请求的页面数据中解析出我们需要的资源地址(类jquery 操作dom的库),

  • 最后就是简单的批量下载了(瞬间发送大量的请求可能会被站点和谐掉,所以一次性爬取的量很大的时候注意async限制异步并发的请求量,并发控制要视不同站点区别对待,这里暂时没做)

教程

1.创建工程

创建文件夹

mkdir image_spider && cd image_spider 

创建依赖文件package.json

 npm init

下载模块

npm install async cheerios colors request --save-dev

fspath模块均为nodejs自带,主要是下面两个,一个是request模块和cheerio模块,附带一个colors模块。

图片描述

简单来说,request模块是用来请求网页的,cheerio是对请求来的网页进行解析的,也就是从html中解析出来图片的src地址

用request来获取这个页面的html

图片描述

body返回的是请求页面的HTML,
然后我们该使用cheerio模块来解析这个页面,也就是analysisData()函数做的事情

2.创建index.js

vim index.js

esc 然后输入:wq 保存退出

3.编写index.js

const fs = require('fs');
const path =require('path');
const request =require('request');
const cheerio =require('cheerio');
const colors = require('colors');
const packagejson = require('./package.json');
console.log("版本" + packagejson.version.cyan)

//测试站点  如jandan.net/ooxx/page-1000

var urltxt = 'http://jandan.net/ooxx/page-',
    startpage = 1200,//起始页
    endpage = 1300,
    sourcedir = 'images',//资源保存的更目录名
    picdir = sourcedir + '' +startpage + '_' + endpage +'/',
    creatdir = './' +picdir;


//----------------------------------------
//创建 图片保存目录
//fs.mkdir 这里有个隐患,直接使用 对存在的 文件夹创建时会报错 ,在不存在的一级目录下创建二级目录也会报错,待封装fs.mkdir后修改
//-----------------

fs.mkdir(creatdir, function(err) {
    if (err) {throw err};
    //let newsourcesrc = '目录' + creatdir +'创建成功';console.log(newsourcesrc.cyan);
});

//----------
//爬取指定范围页
//------------

console.log('---------------开始抓取页面内容---------------'.cyan);
for (var i = startpage; i < endpage; i++) {
    var requrl =urltxt + i;

    request(requrl, function (error, response, body) {
        if(!error && response.statusCode == 200) {
            //console.log(body);//返回请求页面的HTML
            analysisData(body);//采集主函数
        };
    })

    //数据解析抓取主函数
    function analysisData(ourdata) {
        var $ =cheerio.load(ourdata);
        var pic = $('.text .view_img_link').toArray();//将所有的img放到一个数组中
        var thispage = "当前页" + pic.length + "张";
        console.log(thispage.rainbow);

        console.time("----创建当前页下载任务计时----");


        //用循环读出数组中每个src地址
        for (var i = 0; i < pic.length; i++) {
            //indexof筛选src是否带前缀http,此处取的是查看原图<a>的href,若$('.text img')则将herf改为src,其他站点类推
            var pics_src = pic[i].attribs.href;
            

            if (pics_src.indexOf('http') > 0 ) {
                var imgsrc = pics_src;

            }else {
                var imgsrc = 'http:' + pics_src;
            };

            console.log(imgsrc.green); //输出地址
            

            var filename = parseUrlForFileName(imgsrc); //生成文件名

            downloadImg(imgsrc, filename, function() {
                console.log(filename.cyan + 'done');
            });
        }

        console.timeEnd("----创建当前页下载任务计时----");
    }
  

  //图片命名
    function  parseUrlForFileName(address) {
        var filename = path.basename(address);
        return filename;
    }


  // --------------------------------------
    // 下载保存
    // NodeJs path API http://nodejs.org/api/path.html#path_path_basename_p_ext
    // request.head==》》fs模块createWriteStream写入到指定目录
    // 爬取资源较大时 用async来限制一下异步的并发,由于node并发连接数太多可能会被和谐
  // --------------------------------------
   var downloadImg = function(uri, filename, callback) {
       request.head(uri, function(err, res, body) {
           console.log('content-type:', res.header['content-type']);//返回图片的类型
           console.log('content-length:', res.header['content-length']);//图片大小
       if (err) {
           console.log('err: '+ err);
      return false;
       }
           console.log('请求:' + res);
           request(uri).pipe(fs.createWriteStream( picdir + filename)).on('close', function() {
               console.log(filename.cyan + "保存成功");//request的流数据pipe保存到 picdir文件夹下
         });
       });
   };
};

通过审查页面元素我们可以看出,这些妹子图都是放在 class="text" 下的 img 标签中
图片描述
图片描述

可以看到我们拿到了此页面中所有图的地址,最后一步就是下载这些图了,你不能是一个一个复制这些地址,然后粘贴到浏览器中右键另存为吧,首先,我们要先解析这些图片的文件名,解析文件名很简单,调用path模块中的basename方法就可以得到URL中的文件名
图片描述

图片描述
图片描述

现在我们有了图片的地址和图片的名字,就可以下载了,在这里我们调用的是request模块的head方法来下载,请求到图片再调用fs文件系统模块中的createWriteStream来下载到本地目录

图片描述

有的网站是有反爬机制的,并不是每个网站都可以爬,下次我们聊聊反爬虫机制

推送到github

图片描述

github仓库

戳这里

用法

本爬虫在windows,linux,安卓(安装模拟器Termux搭建node环境,操作流程同pc)平台都通用。
安装nodejs、git等环境步骤这里就不重复了。

拷贝本目录

git clone 

安装相关依赖,切到clone的目录下安装依赖在运行(推荐用cnpm install),具体爬虫参数修改看注释,如有错请指正

cd images_spider
cnpm install 

爬虫跑起来 index.js

node index

参考链接

cheerio 官网
request 官网
通读cheerio API
NodeJs path API
NodeJs妹子图爬虫
Node.js 爬虫爬取 58 同城租房信息


白鲸鱼
1k 声望110 粉丝

方寸湛蓝