源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

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

  • 时间:2021-10-20 12:54 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:nodejs制作爬虫实现批量下载图片
今天想获取一大批猫的图片,然后就在360流浪器搜索框中输入 [code]猫[/code] ,然后点击图片。就看到了一大波猫的图片: http://image.so.com/i?q=%E7%8... ,我在想啊,要是审查元素,一张张手动下载,多麻烦,所以打算写程序来实现。不写不知道,一写发现里面还是有很多道道的。 [img]http://img.1sucai.cn/uploads/article/2018010710/20180107100155_0_67350.png[/img] 1. 爬取图片链接 因为之前也写过nodejs爬虫功能(参见:[url=http://www.1sucai.cn/article/58819.htm]NodeJS制作爬虫全过程 [/url]),所以觉得应该很简单,就用cheerio来处理dom啦,结果打印一下啥也没有,后来查看源代码: [img]http://img.1sucai.cn/uploads/article/2018010710/20180107100155_1_79179.png[/img] 发现 [code]waterfall_zoom[/code] 里面空空如也,查找了一下,发现所有的数据都是写在 [code]<script>[/code] 里面,然后动态加载到页面的,所以用cheerio.load到的页面里面其实没数据的。真实数据: [img]http://img.1sucai.cn/uploads/article/2018010710/20180107100155_2_36467.png[/img] 分析完毕,刷刷写代码:
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);
  }
});
[img]http://img.1sucai.cn/uploads/article/2018010710/20180107100156_3_37777.png[/img] 2. 下载图片到本地 2.1 粗糙的方案 最初的思路很简单,简单的 [code]fs.createWriteStream()[/code] 就能解决:
var downloadPic = function(src, dest){
  request(src).pipe(fs.createWriteStream(dest)).on('close',function(){
    console.log('pic saved!')
  })
}
使用方式:
downloadPic(imgList[0],'./catpics/1.jpg');
[img]http://img.1sucai.cn/uploads/article/2018010710/20180107100156_4_76685.png[/img] 成功捕获一只猫!然后写了一个循环准备捕获所有猫。然而这种方式是串行的,速度很慢!下载一大批图片要花大量时间。 2.2 使用async异步批量下载 关于async的map操作,详见: [url=https://github.com/freewind/async_demo/blob/master/map.js]async_demo/map.js[/url] ,对集合中的每一个元素,执行某个异步操作,得到结果。所有的结果将汇总到最终的callback里。与forEach的区别是,forEach只关心操作不管最后的值,而map关心的最后产生的值。 提供了两种方式: 并行执行。 [code]async.map[/code] 同时对集合中所有元素进行操作,结果汇总到最终callback里。如果出错,则立刻返回错误以及已经执行完的任务的结果,未执行完的占个空位 顺序执行。 [code]async.mapSeries[/code] 对集合中的元素一个一个执行操作,结果汇总到最终callback里。如果出错,则立刻返回错误以及已经执行完的结果,未执行的被忽略。 在此处:
async.mapSeries(imgList,function(item, callback){
  setTimeout(function(){
    downloadPic(item, './catpics/'+ (new Date()).getTime() +'.jpg');
    callback(null, item);
  },400);
}, function(err, results){});
[code]注:[/code] 此处使用setTimeout,是因为下载需要一定时间,在笔者较慢网速下,需要400ms的间隔能确保每张图片下载完全。 [img]http://img.1sucai.cn/uploads/article/2018010710/20180107100157_5_73774.png[/img] 成功捕获一批猫猫! 2.3 使用bagpipe批量 [url=https://github.com/JacksonTian/bagpipe]bagpipe[/url] 是朴灵大大做的一个在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.总结 作为一个程序员,能用程序解决就不手动解决。每一次尝都会有新的收获。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部