今天想获取一大批猫的图片,而后就在360流浪器搜索框中输入
猫
,而后点击图片。就看到了一大波猫的图片:http://image.so.com/i?q=%E7%8...,我在想啊,要是审查元素,一张张手动下载,多麻烦,因此打算写程序来实现。不写不知道,一写发现里面仍是有不少道道的。html
由于以前也写过nodejs爬虫功能(参见:nodejs微信公众号开发——9.爬取网站素材定时推送消息),因此以为应该很简单,就用cheerio来处理dom啦,结果打印一下啥也没有,后来查看源代码:node
发现waterfall_zoom
里面空空如也,查找了一下,发现全部的数据都是写在<script>
里面,而后动态加载到页面的,因此用cheerio.load到的页面里面其实没数据的。真实数据:git
分析完毕,刷刷写代码:程序员
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); } });
最初的思路很简单,简单的fs.createWriteStream()
就能解决:github
var downloadPic = function(src, dest){ request(src).pipe(fs.createWriteStream(dest)).on('close',function(){ console.log('pic saved!') }) }
使用方式:npm
downloadPic(imgList[0],'./catpics/1.jpg');
成功捕获一只猫!而后写了一个循环准备捕获全部猫。然而这种方式是串行的,速度很慢!下载一大批图片要花大量时间。segmentfault
关于async的map操做,详见:async_demo/map.js,对集合中的每个元素,执行某个异步操做,获得结果。全部的结果将汇总到最终的callback里。与forEach的区别是,forEach只关心操做无论最后的值,而map关心的最后产生的值。微信
提供了两种方式:并发
并行执行。async.map
同时对集合中全部元素进行操做,结果汇总到最终callback里。若是出错,则马上返回错误以及已经执行完的任务的结果,未执行完的占个空位dom
顺序执行。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的间隔能确保每张图片下载彻底。
成功捕获一批猫猫!
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){ // }); }
做为一个程序员,能用程序解决就不手动解决。每一次尝都会有新的收获。