步骤一:创建项目

npm init

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

request 
用于请求地址和快速下载图片流。 
https://github.com/request/request 
cheerio 
为服务器特别定制的,快速、灵活、实施的jQuery核心实现. 
便于解析html代码。 
https://www.npmjs.com/package/cheerio 
async 
异步调用,防止堵塞。 
http://caolan.github.io/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)项目目录

node 爬虫 --- 批量下载图片的更多相关文章

  1. 【Python】nvshens按目录批量下载图片爬虫1.00(单线程版)

    # nvshens按目录批量下载图片爬虫1.00(单线程版) from bs4 import BeautifulSoup import requests import datetime import ...

  2. python图片爬虫 - 批量下载unsplash图片

    前言 unslpash绝对是找图的绝佳场所, 但是进网站等待图片加载真的令人捉急, 仿佛是一场拼RP的战争 然后就开始思考用爬虫帮我批量下载, 等下载完再挑选, 操作了一下不算很麻烦, 顺便也给大家提 ...

  3. scrapy操作mysql/批量下载图片

    1.操作mysql items.py meiju.py 3.piplines.py 4.settings.py -------------------------------------------- ...

  4. Node.js 使用爬虫批量下载网络图片到本地

    图片网站往往广告众多,用Node.js写个爬虫下载图片,代码不长,省事不少,比手动一张张保存简直是天与地的区别.以前用Java也做过远程图片下载,但Node.js的下载速度更让人咂舌,这也是非阻塞式变 ...

  5. 利用Node 搭配uglify-js压缩js文件,批量下载图片到本地

    Node的便民技巧-- 压缩代码 下载图片 压缩代码 相信很多前端的同学都会在上线前压缩JS代码,现在的Gulp Webpack Grunt......都能轻松实现.但问题来了,这些都不会,难道就要面 ...

  6. 用python批量下载图片

    一 写爬虫注意事项 网络上有不少有用的资源, 如果需要合理的用爬虫去爬取资源是合法的,但是注意不要越界,前一阶段有个公司因为一个程序员写了个爬虫,导致公司200多个人被抓,所以先进入正题之前了解下什么 ...

  7. python——批量下载图片

    前言 批量下载网页上的图片需要三个步骤: 获取网页的URL 获取网页上图片的URL 下载图片 例子 from html.parser import HTMLParser import urllib.r ...

  8. 如何用node.js批量给图片加水印

    上一篇我们讲了如何用node.js给图片加水印,但是只是给某一张图片加,并没有涉及到批量处理.这一篇,我们学习如果批量进行图片加水印处理. 一.准备工作: 首先,你要阅读完这篇文章:http://ww ...

  9. javaWeb 批量下载图片

      批量下载网页图片 CreateTime--2017年9月26日15:40:43 Author:Marydon 所用技术:javascript.java 测试浏览器:chrome 开发工具:Ecli ...

随机推荐

  1. Linux Shell脚本教程:30分钟玩转Shell脚本编程

    http://c.biancheng.net/cpp/shell/ Linux在线体验: http://compileonline.com/ Linux命令查询: http://man.linuxde ...

  2. WIN10配置JDK

    系统变量→新建 JAVA_HOME 变量 变量值填写jdk的安装目录(本人是 E:\Java\jdk1.7.0) 系统变量→寻找 Path 变量→编辑 在变量值最后输入 %JAVA_HOME%\bin ...

  3. Atrenta电话面试(C++研发工程师)

    1.代码量是多少,你负责哪一块,工作量占%几,改进了什么   2.c++ 和 c 的 区别   3.list 和 vector 的 适用条件   4.hash_map 和 map 的 区别 , 使用h ...

  4. EFCore CodeFirst模型迁移生成数据库备注(mysql)

    重写Mysql下sql脚本生成器 using Framework.NetCore.Extensions; using Framework.NetCore.Models; using Microsoft ...

  5. 【01】CSS规范

    [01]CSS规范 []https://drafts.csswg.org/indexes/(下图)   https://www.w3.org/TR/2011/REC-CSS2-20110607/   ...

  6. .NET重构(七):VS报表的制作

    导读:机房做到最后阶段,就是报表的制作了.想到第一次,是借助外部控件进行实现的,这次采用VS进行编写,在这个软件中,有自带的报表编辑工具,更加的方便和简洁,现在就对这一块的学习,进行总结. 一.报表制 ...

  7. FineMessBox的js依赖导致错误Uncaught ReferenceError: addEvent is not defined

    /**  * COMMON DHTML FUNCTIONS  * These are handy functions I use all the time.  *  * By Seth Banks ( ...

  8. ajax原生post请求

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. GT考试 BZOJ 1009

    GT考试 [问题描述] 阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字. 他的不吉利数学A1A2...Am(0< ...

  10. Fabrice Bellard其人 ---- FFMPEG及其他……

    有些计算机科学家的名字耳熟能详:阿兰·图灵(Alan Turing).高纳德(Donald Knuth).艾兹赫尔·戴克斯特拉(Edsger Dijkstra),这些人的名气甚至大于他们突破性的成就. ...