博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
node 爬虫 --- 批量下载图片
阅读量:7282 次
发布时间:2019-06-30

本文共 6085 字,大约阅读时间需要 20 分钟。

步骤一:创建项目

npm init

步骤二:安装 request,cheerio,async 三个模块 

request 

用于请求地址和快速下载图片流。 
 
cheerio 
为服务器特别定制的,快速、灵活、实施的jQuery核心实现. 
便于解析html代码。 
 
async 
异步调用,防止堵塞。 

npm i request cheerio async -D

步骤三:核心思路

(1)用request 发送一个请求。获取html代码,取得其中的img标签和a标签。

//发送请求function requestall(url) {  request({    uri: url,    headers: setting.header  }, function (error, response, body) {    if (error) {      // 请求失败      console.log(error);    } else {      console.log(response.statusCode);      if (!error && response.statusCode == 200) {        // 请求成功      }    }  });}

(2)通过获取的a表情进行递归调用。不断获取img地址和a地址,继续递归

// 递归爬虫$('a').each(function () {  var murl = $(this).attr('href');  if (IsURL(murl)) {    setTimeout(function () {      fetchre(murl);    }, timeout);    timeout += setting.ajax_timeout;  } else {    setTimeout(function () {      fetchre("http://www.ivsky.com/" + murl);    }, timeout);    timeout += setting.ajax_timeout;  }})

(3)获取img地址通过request(photo).pipe(fs.createWriteStream(dir + “/” + filename));进行快速下载。

//发送请求function requestall(url) {  request({    uri: url,    headers: setting.header  }, function (error, response, body) {    if (error) {      console.log(error);    } else {      console.log(response.statusCode);      if (!error && response.statusCode == 200) {        var $ = cheerio.load(body);        var photos = [];        $('img').each(function () {          // 判断地址是否存在          if ($(this).attr('src')) {            var src = $(this).attr('src');            var end = src.substr(-4, 4).toLowerCase();            if (end == '.jpg' || end == '.gif' || end == '.png' || end == '.jpeg') {              if (IsURL(src)) {                photos.push(src);              }            }          }        });        downloadImg(photos, dir, setting.download_v);        // 递归爬虫        $('a').each(function () {          var murl = $(this).attr('href');          if (IsURL(murl)) {            setTimeout(function () {              fetchre(murl);            }, timeout);            timeout += setting.ajax_timeout;          } else {            setTimeout(function () {              fetchre("http://www.ivsky.com/" + murl);            }, timeout);            timeout += setting.ajax_timeout;          }        })      }    }  });}

步骤四:防坑

(1)在request通过图片地址下载时,绑定error事件防止爬虫异常的中断。

// 防止pipe错误request(photo)  .on('error', function (err) {    console.log(err);  })  .pipe(fs.createWriteStream(dir + "/" + filename));

(2)通过async的mapLimit限制并发。 

async.mapLimit(photos, asyncNum, function (photo, callback) {  // 请求成功}, function (err, result) {  // 请求失败})

(3)加入请求报头,防止ip被屏蔽。 

setting.js

/** * 加入请求报头,防止ip被屏蔽 */module.exports = {  header : {    'User-Agent': 'request',    "Referer":"http://www.ivsky.com/",  },  // 并发数  ajax_timeout : 2000,  // 下载图片速度  download_v : 5}

(4)获取一些图片和超链接地址,可能是相对路径(待考虑解决是否有通过方法)。

// 下载图片function downloadImg(photos, dir, asyncNum) {  console.log("即将异步并发下载图片,当前并发数为:" + asyncNum);  async.mapLimit(photos, asyncNum, function (photo, callback) {    var filename = (new Date().getTime()) + photo.substr(-4, 4);    if (filename) {      console.log('正在下载' + photo);      // 默认      // fs.createWriteStream(dir + "/" + filename)      // 防止pipe错误      request(photo)        .on('error', function (err) {          console.log(err);        })        .pipe(fs.createWriteStream(dir + "/" + filename));      console.log('下载完成');      callback(null, filename);    }  }, function (err, result) {    if (err) {      console.log(err);    } else {      console.log(" all right ! ");      console.log(result);    }  })}

步骤五:完整代码

app.js

/** * node 爬虫 */var fs = require('fs');var request = require("request");var cheerio = require("cheerio");var async = require('async');// 目标网址var url = 'http://www.ivsky.com/tupian/ziranfengguang/';// 本地存储目录var dir = './images';var setting = require('./setting');var timeout = 100;// 封装了一层函数function fetchre(url) {  requestall(url);}// 发送请求function requestall(url) {  request({    uri: url,    headers: setting.header  }, function (error, response, body) {    if (error) {      console.log(error);    } else {      console.log(response.statusCode);      if (!error && response.statusCode == 200) {        var $ = cheerio.load(body);        var photos = [];        $('img').each(function () {          // 判断地址是否存在          if ($(this).attr('src')) {            var src = $(this).attr('src');            var end = src.substr(-4, 4).toLowerCase();            if (end == '.jpg' || end == '.gif' || end == '.png' || end == '.jpeg') {              if (IsURL(src)) {                photos.push(src);              }            }          }        });        downloadImg(photos, dir, setting.download_v);        // 递归爬虫        $('a').each(function () {          var murl = $(this).attr('href');          if (IsURL(murl)) {            setTimeout(function () {              fetchre(murl);            }, timeout);            timeout += setting.ajax_timeout;          } else {            setTimeout(function () {              fetchre("http://www.ivsky.com/" + murl);            }, timeout);            timeout += setting.ajax_timeout;          }        })      }    }  });}// 下载图片function downloadImg(photos, dir, asyncNum) {  console.log("即将异步并发下载图片,当前并发数为:" + asyncNum);  async.mapLimit(photos, asyncNum, function (photo, callback) {    var filename = (new Date().getTime()) + photo.substr(-4, 4);    if (filename) {      console.log('正在下载' + photo);      // 默认      // fs.createWriteStream(dir + "/" + filename)      // 防止pipe错误      request(photo)        .on('error', function (err) {          console.log(err);        })        .pipe(fs.createWriteStream(dir + "/" + filename));      console.log('下载完成');      callback(null, filename);    }  }, function (err, result) {    if (err) {      console.log(err);    } else {      console.log(" all right ! ");      console.log(result);    }  })}// 判断是否为完整地址function IsURL(str_url) {  var strRegex = '^((https|http|ftp|rtsp|mms)?://)';  var re = new RegExp(strRegex);  if (re.test(str_url)) {    return (true);  } else {    return (false);  }}requestall(url);

步骤六:执行

(1)在根路径下创建 images 空文件夹,用于存放下载下来的图片

(2)打开终端,执行

node app.js

(3)项目目录

转载地址:http://bukjm.baihongyu.com/

你可能感兴趣的文章
关于 Git 你所不知道的一些事
查看>>
《现代体系结构上的UNIX系统:内核程序员的对称多处理和缓存技术(修订版)》——1.3 进程地址空间...
查看>>
中国青年报:COS 有义务回应公众质疑
查看>>
《HFSS电磁仿真设计从入门到精通》一第1章 HFSS概述
查看>>
Java并发/多线程教程——3多线程的开销
查看>>
ForestDB —— 快速的 Key-Value 存储引擎
查看>>
《智能数据时代:企业大数据战略与实战》一1.5 大数据环境下的处理分析工具...
查看>>
Let's Encrypt 客户端将由EFF管理
查看>>
基于Servlet的技术问答网站系统实现(附源码)
查看>>
写给 Python 初学者的设计模式入门
查看>>
使用Redis存储Nginx+Tomcat负载均衡集群的Session
查看>>
《电路分析导论(原书第12版)》一1.3 测量单位与单位制
查看>>
《VoIP技术构架(第2版·修订版)》一第1章 PSTN概览及与VoIP的比较
查看>>
《PPT高手之道:六步变身职场幻灯派》一0.1 PPT/Presentation的本质
查看>>
fqueue初步分析
查看>>
《Node.js区块链开发》——3.3 PoS:股权证明机制
查看>>
FaceBook API
查看>>
《Swift 权威指南》——第6章,第6.11节小结
查看>>
自己动手开发一个 Web 服务器(二)
查看>>
《Node.js入门经典》一2.6 本地和全局的安装
查看>>