nodejs制作爬虫实现批量下载图片


Posted in NodeJs onMay 19, 2017

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

nodejs制作爬虫实现批量下载图片

1. 爬取图片链接

因为之前也写过nodejs爬虫功能(参见: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关心的最后产生的值。

提供了两种方式:

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

顺序执行。 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访问ActiveX对象,以操作Access数据库为例。
Dec 15 NodeJs
NodeJS的模块写法入门(实例代码)
Mar 07 NodeJs
Nodejs学习笔记之Global Objects全局对象
Jan 13 NodeJs
nodeJS代码实现计算交社保是否合适
Mar 09 NodeJs
Nodejs抓取html页面内容(推荐)
Aug 11 NodeJs
学习 NodeJS 第八天:Socket 通讯实例
Dec 21 NodeJs
Nodejs实现短信验证码功能
Feb 09 NodeJs
Ajax异步文件上传与NodeJS express服务端处理
Apr 01 NodeJs
nodejs实现的简单web服务器功能示例
Mar 15 NodeJs
nodejs require js文件入口,在package.json中指定默认入口main方法
Oct 10 NodeJs
Nodejs实现多文件夹文件同步
Oct 17 NodeJs
Nodejs让异步变成同步的方法
Mar 02 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
NodeJS、NPM安装配置步骤(windows版本) 以及环境变量详解
May 13 #NodeJs
You might like
PHP跨平台获取服务器IP地址自定义函数分享
2014/12/29 PHP
PHP Streams(流)详细介绍及使用
2015/05/12 PHP
PHP判断文件是否被引入的方法get_included_files用法示例
2016/11/29 PHP
php传值方式和ajax的验证功能
2017/03/27 PHP
学习YUI.Ext第五日--做拖放Darg&amp;Drop
2007/03/10 Javascript
javascript 一段左右两边随屏滚动的代码
2009/06/18 Javascript
jquery 仿QQ校友的DIV模拟窗口效果源码
2010/03/24 Javascript
动态改变div的z-index属性的简单实例
2013/08/08 Javascript
jtable列中自定义button示例代码
2013/11/21 Javascript
jquery获取选中的文本和值的方法
2014/07/08 Javascript
JavaScript中连接操作Oracle数据库实例
2015/04/02 Javascript
你所不了解的javascript操作DOM的细节知识点(一)
2015/06/17 Javascript
JavaScript学习笔记之DOM基础 2.4
2015/08/14 Javascript
jquery.validate 自定义验证方法及validate相关参数
2016/01/18 Javascript
jQuery实现的纵向下拉菜单实例详解【附demo源码下载】
2016/07/09 Javascript
安装vue-cli报错 -4058 的解决方法
2017/10/19 Javascript
Phaser.js实现简单的跑酷游戏附源码下载
2018/10/26 Javascript
基于Vue实现图片在指定区域内移动的思路详解
2018/11/11 Javascript
超好用的jQuery分页插件jpaginate用法示例【附源码下载】
2018/12/06 jQuery
浅谈vue获得后台数据无法显示到table上面的坑
2020/08/13 Javascript
Python+threading模块对单个接口进行并发测试
2019/06/25 Python
Python类中的魔法方法之 __slots__原理解析
2019/08/26 Python
Pytorch.nn.conv2d 过程验证方式(单,多通道卷积过程)
2020/01/03 Python
Python如何访问字符串中的值
2020/02/09 Python
解决Jupyter因卸载重装导致的问题修复
2020/04/10 Python
python实现按日期归档文件
2021/01/30 Python
Raffaello Network西班牙:意大利拉斐尔时尚购物网
2019/03/12 全球购物
网络安全类面试题
2015/08/01 面试题
Python里面如何拷贝一个对象
2014/02/17 面试题
高分子材料与工程专业个人求职信
2013/12/15 职场文书
致铅球运动员广播稿精选
2014/01/12 职场文书
中学自我评价
2014/01/31 职场文书
2015小学教师年度考核工作总结
2015/05/12 职场文书
教师听课学习心得体会
2016/01/15 职场文书
2019财务毕业实习报告
2019/06/27 职场文书
2019年农民幸福观调查的实践感悟
2019/12/19 职场文书