nodejs批量下载图片的实现方法


Posted in NodeJs onMay 19, 2017

今天想获取一大批猫的图片,然后就在360流浪器搜索框中输入猫,然后点击图片。就看到了一大波猫的图片:http://image.so.com/i?q=%E7%8...,我在想啊,要是审查元素,一张张手动下载,多麻烦,所以打算写程序来实现。不写不知道,一写发现里面还是有很多道道的。

nodejs批量下载图片的实现方法

1. 爬取图片链接

因为之前也写过nodejs爬虫功能,所以觉得应该很简单,就用cheerio来处理dom啦,结果打印一下啥也没有,后来查看源代码:

nodejs批量下载图片的实现方法

发现waterfall_zoom里面空空如也,查找了一下,发现所有的数据都是写在<script>里面,然后动态加载到页面的,所以用cheerio.load到的页面里面其实没数据的。真实数据:

nodejs批量下载图片的实现方法

分析完毕,刷刷写代码:

var request = require('request');
var cheerio = require('cheerio');
var url = 'http://image.so.com/i?q=%E7%8C%AB&src=tab_www';

request(url,function(err,res,body){
  if(!err && res.statusCode === 200){
    var $ = cheerio.load(body);
    var imgList = []
    JSON.parse($('script[id="initData"]').html()).list.forEach(function(item){
      imgList.push(item.img)
    });
    console.log(imgList);
  }
});

nodejs批量下载图片的实现方法

2. 下载图片到本地

2.1 粗糙的方案

最初的思路很简单,简单的fs.createWriteStream()就能解决:

var downloadPic = function(src, dest){
  request(src).pipe(fs.createWriteStream(dest)).on('close',function(){
    console.log('pic saved!')
  })
}

使用方式:

downloadPic(imgList[0],'./catpics/1.jpg');

 nodejs批量下载图片的实现方法

成功捕获一只猫!然后写了一个循环准备捕获所有猫。然而这种方式是串行的,速度很慢!下载一大批图片要花大量时间。

2.2 使用async异步批量下载

关于async的map操作,详见:async_demo/map.js,对集合中的每一个元素,执行某个异步操作,得到结果。所有的结果将汇总到最终的callback里。与forEach的区别是,forEach只关心操作不管最后的值,而map关心的最后产生的值。

提供了两种方式:

  1. 并行执行。async.map同时对集合中所有元素进行操作,结果汇总到最终callback里。如果出错,则立刻返回错误以及已经执行完的任务的结果,未执行完的占个空位
  2. 顺序执行。async.mapSeries对集合中的元素一个一个执行操作,结果汇总到最终callback里。如果出错,则立刻返回错误以及已经执行完的结果,未执行的被忽略。

在此处:

async.mapSeries(imgList,function(item, callback){
  setTimeout(function(){
    downloadPic(item, './catpics/'+ (new Date()).getTime() +'.jpg');
    callback(null, item);
  },400);
}, function(err, results){});

注:此处使用setTimeout,是因为下载需要一定时间,在笔者较慢网速下,需要400ms的间隔能确保每张图片下载完全。

 nodejs批量下载图片的实现方法

成功捕获一批猫猫!

2.3 使用bagpipe批量

bagpipe是朴灵大大做的一个在nodejs中控制并发执行的模块。其安装和使用也比较简单:

npm install bagpipe --save

使用:

var Bagpipe = require('bagpipe');

var bagpipe = new Bagpipe(10);
var files = ['这里有很多很多文件'];
for(vari =0; i < files.length; i++){
  bagpipe.push(fs.readFile, files[i], 'utf-8',function(err, data){
    ...
  });
}

在此处:

var bagpipe = new Bagpipe(10,{timeout: 100});
for(var i = 0; i < imgList.length; i++) {
  console.log('i:'+i)
  bagpipe.push(downloadPic, imgList[i], './catpics/'+ i +'.jpg', function(err, data){
    //
   });
}

3.总结

作为一个程序员,能用程序解决就不手动解决。每一次尝都会有新的收获。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

NodeJs 相关文章推荐
nodejs命令行参数处理模块commander使用实例
Sep 17 NodeJs
Nodejs实现的一个静态服务器实例
Dec 06 NodeJs
NodeJS学习笔记之(Url,QueryString,Path)模块
Jan 13 NodeJs
搭建简单的nodejs http服务器详解
Mar 09 NodeJs
初识NodeJS服务端开发入门(Express+MySQL)
Apr 07 NodeJs
nodejs入门教程一:概念与用法简介
Apr 24 NodeJs
NodeJS链接MySql数据库的操作方法
Jun 27 NodeJs
详解nodejs的express如何自动生成项目框架
Jul 12 NodeJs
NodeJS使用Range请求实现下载功能的方法示例
Oct 12 NodeJs
Nodejs中怎么实现函数的串行执行
Mar 02 NodeJs
nodejs中request库使用HTTPS代理的方法
Apr 30 NodeJs
分享五个Node.js开发的优秀实践 
Apr 07 NodeJs
nodejs制作爬虫实现批量下载图片
May 19 #NodeJs
详解Windows下安装Nodejs步骤
May 18 #NodeJs
nodejs+websocket实时聊天系统改进版
May 18 #NodeJs
nodejs6下使用koa2框架实例
May 18 #NodeJs
Nodejs中使用captchapng模块生成图片验证码
May 18 #NodeJs
详解使用nodeJs安装Vue-cli
May 17 #NodeJs
NodeJS创建最简单的HTTP服务器
May 15 #NodeJs
You might like
PHP数组交集的优化代码分析
2011/03/06 PHP
php通过header发送自定义数据方法
2018/01/18 PHP
分享27款非常棒的jQuery 表单插件
2011/03/28 Javascript
有关JavaScript的10个怪癖和秘密分享
2011/08/28 Javascript
jQuery 中使用JSON的实现代码
2011/12/01 Javascript
javascript中的绑定与解绑函数应用示例
2013/06/24 Javascript
jquery each的几种常用的使用方法示例
2014/01/21 Javascript
jQuery:delegate中select()不起作用的解决方法(实例讲解)
2014/01/26 Javascript
js中top的作用深入剖析
2014/03/04 Javascript
JavaScript闭包详解
2015/02/02 Javascript
JavaScript中判断变量是数组、函数或是对象类型的方法
2015/02/25 Javascript
JavaScript通过元素索引号删除数组中对应元素的方法
2015/03/18 Javascript
jQuery中$.extend()用法实例
2015/06/24 Javascript
js变形金刚文字特效代码分享
2015/08/20 Javascript
详解axios在node.js中的post使用
2017/04/27 Javascript
layui导航栏实现代码
2017/05/19 Javascript
Vue-cli中为单独页面设置背景色的实现方法
2018/02/11 Javascript
jquery 给动态生成的标签绑定事件的几种方法总结
2018/02/24 jQuery
vue中mint-ui的使用方法
2018/04/04 Javascript
node和vue实现商城用户地址模块
2018/12/05 Javascript
Vue-cli3.X使用px2 rem遇到的问题及解决方法
2019/08/08 Javascript
Python实现的十进制小数与二进制小数相互转换功能
2017/10/12 Python
Python内建函数之raw_input()与input()代码解析
2017/10/26 Python
浅析python3字符串格式化format()函数的简单用法
2018/12/07 Python
python爬虫之验证码篇3-滑动验证码识别技术
2019/04/11 Python
pandas中遍历dataframe的每一个元素的实现
2019/10/23 Python
用python对excel进行操作(读,写,修改)
2020/12/25 Python
SheIn俄罗斯:时尚女装网上商店
2017/02/28 全球购物
丝芙兰香港官网:Sephora香港
2018/03/13 全球购物
Java面试笔试题大全
2016/11/23 面试题
爱国卫生月实施方案
2014/02/21 职场文书
学习型班组申报材料
2014/05/31 职场文书
党员群众路线自我剖析材料
2014/10/06 职场文书
员工保密协议范本,您一定得收藏!很有用!
2019/08/08 职场文书
Android Studio 计算器开发
2022/05/20 Java/Android
css如何把元素固定在容器底部的四种方式
2022/06/16 HTML / CSS