步骤一:创建项目

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. 【HIHOCODER 1529】 不上升序列

    描述 给定一个长度为 n 的非负整数序列 a[1..n]. 你每次可以花费 1 的代价给某个 a[i] 加1或者减1. 求最少需要多少代价能将这个序列变成一个不上升序列. 输入 第一行一个正整数 n. ...

  2. Java中HashMap底层原理源码分析

    在介绍HashMap的同时,我会把它和HashTable以及ConcurrentHashMap的区别也说一下,不过本文主要是介绍HashMap,其实它们的原理差不多,都是数组加链表的形式存储数据,另外 ...

  3. awk支持多个记录分隔符的写法

    awk的-F参数可以指定新的记录分隔符,有些时候可能需求指定多个分隔符,比如下面的内容 width:720 height:360 如果需要取出width和height后面的值的话,一般大家会这样做,即 ...

  4. VBS脚本获取安全标识符SID(Security Identifiers)的方法

    一.SID简介       SID也就是安全标识符(Security Identifiers),是标识用户.组和计算机帐户的唯一的号码.在第一次创建该帐户时,将给网络上的每一个帐户发布一个唯一的 SI ...

  5. appium+python自动化-xpath定位

    基本属性定位 以淘宝app为例,定位左上角扫一扫按钮 1.可以通过text文本定位到 //*[@text='text文本属性'] # 定位text driver.find_element_by_xpa ...

  6. C++ char数组和string类简单使用总结

    使用char数组,进行字符串的操作,是c风格的操作方式. string是C++的风格,感觉string本质上就是一个vector<char> 以下代码详细展示了字符串的常见操作 #incl ...

  7. acm之简单博弈 Nim Bash Wythoff

    前些日子我打算开了博弈基础,事后想进行总结下 一句话就是分析必胜或必败,异或为0. 以下内容来自转载: Nim游戏的概述: 还记得这个游戏吗?给出n列珍珠,两人轮流取珍珠,每次在某一列中取至少1颗珍珠 ...

  8. BZOJ2244 [SDOI2011]拦截导弹 【cdq分治 + 树状数组】

    题目 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高于前一发的高度,其 ...

  9. 刷题总结——shortest(ssoi)

    题目: 题目背景 SOURCE:NOIP2015-SHY-3 题目描述 给定一张 n 个点的有向带权完全图,和一个数组 a[] ,请按顺序删除数组中的点,请求出在删除点 a[i] 以前,所有未删除点对 ...

  10. 巴蜀2904 MMT数

    Description FF博士最近在研究MMT数. 如果对于一个数n,存在gcd(n,x)<>1并且n mod x<>0 那么x叫做n的MMT数,显然这样的数可以有无限个. ...