使用nodejs下载风景壁纸


Posted in NodeJs onFebruary 05, 2017

需要用到的第三方模块有:

superagent

superagent-charset  (手动指定编码,解决GBK中文乱码)

cheerio

express

async (并发控制)

完整的代码,可以在我的github中可以下载。主要的逻辑逻辑在 netbian.js 中。

以彼岸桌面(http://www.netbian.com/)栏目下的风景壁纸(http://www.netbian.com/fengjing/index.htm)为例进行讲解。

1. 分析URL

使用nodejs下载风景壁纸

不难发现:

首页: 栏目/index.htm

分页: 栏目/index_具体页码.htm

知道这个规律,就可以批量下载壁纸了。

2. 分析壁纸缩略图,找到对应壁纸的大图

使用chrome的开发者工具,可以发现,缩略图列表在 class="list"的div里,a标签的href属性的值就是单张壁纸所在的页面。

使用nodejs下载风景壁纸

部分代码:

request
 .get(url)
 .end(function(err, sres){
 var $ = cheerio.load(sres.text);
 var pic_url = []; // 中等图片链接数组
 $('.list ul', 0).find('li').each(function(index, ele){
 var ele = $(ele);
 var href = ele.find('a').eq(0).attr('href'); // 中等图片链接
 if(href != undefined){
 pic_url.push(url_model.resolve(domain, href));
 }
 });
});

3. 以“http://www.netbian.com/desk/17662.htm”继续分析

打开这个页面,发现此页面显示的壁纸,依旧不是最高的分辨率。

点击“下载壁纸”按钮里的链接,打开新的页面。

使用nodejs下载风景壁纸

4. 以“http://www.netbian.com/desk/17662-1920x1080.htm”继续分析

打开这个页面,我们最终要下载的壁纸,放在一个table里面。如下图,http://img.netbian.com/file/2017/0203/bb109369a1f2eb2e30e04a435f2be466.jpg

才是我们最终要下载的图片的URL(幕后BOSS终于现身了(@ ̄? ̄@))。

使用nodejs下载风景壁纸

下载图片的代码:

request
.get(wallpaper_down_url)
.end(function(err, img_res){
 if(img_res.status == 200){
 // 保存图片内容
 fs.writeFile(dir + '/' + wallpaper_down_title + path.extname(path.basename(wallpaper_down_url)), img_res.body, 'binary', function(err){
 if(err) console.log(err);
 });
 }
});

打开浏览器,访问  http://localhost:1314/fengjing

选择栏目和页面,点击“开始”按钮:

使用nodejs下载风景壁纸

并发请求服务器,下载图片。

使用nodejs下载风景壁纸

完成~

使用nodejs下载风景壁纸

图片的存放目录按照 栏目+页码 的形式保存。

使用nodejs下载风景壁纸

附上完整的图片下载的代码:

/**
 * 下载图片
 * @param {[type]} url [图片URL]
 * @param {[type]} dir [存储目录]
 * @param {[type]} res [description]
 * @return {[type]} [description]
 */
var down_pic = function(url, dir, res){
 var domain = 'http://www.netbian.com'; // 域名
 request
 .get(url)
 .end(function(err, sres){
 var $ = cheerio.load(sres.text);
 var pic_url = []; // 中等图片链接数组
 $('.list ul', 0).find('li').each(function(index, ele){
 var ele = $(ele);
 var href = ele.find('a').eq(0).attr('href'); // 中等图片链接
 if(href != undefined){
 pic_url.push(url_model.resolve(domain, href));
 }
 });
 var count = 0; // 并发计数器
 var wallpaper = []; // 壁纸数组
 var fetchPic = function(_pic_url, callback){
 count++; // 并发加1
 var delay = parseInt((Math.random() * 10000000) % 2000);
 console.log('现在的并发数是:' + count + ', 正在抓取的图片的URL是:' + _pic_url + ' 时间是:' + delay + '毫秒');
 setTimeout(function(){
 // 获取大图链接
 request
 .get(_pic_url)
 .end(function(err, ares){
  var $$ = cheerio.load(ares.text);
  var pic_down = url_model.resolve(domain, $$('.pic-down').find('a').attr('href')); // 大图链接
  count--; // 并发减1
  // 请求大图链接
  request
  .get(pic_down)
  .charset('gbk') // 设置编码, 网页以GBK的方式获取
  .end(function(err, pic_res){
  var $$$ = cheerio.load(pic_res.text);
  var wallpaper_down_url = $$$('#endimg').find('img').attr('src'); // URL
  var wallpaper_down_title = $$$('#endimg').find('img').attr('alt'); // title
  // 下载大图
  request
  .get(wallpaper_down_url)
  .end(function(err, img_res){
  if(img_res.status == 200){
  // 保存图片内容
  fs.writeFile(dir + '/' + wallpaper_down_title + path.extname(path.basename(wallpaper_down_url)), img_res.body, 'binary', function(err){
   if(err) console.log(err);
  });
  }
  });
  wallpaper.push(wallpaper_down_title + '下载完毕<br />');
  });
  callback(null, wallpaper); // 返回数据
 });
 }, delay);
 };
 // 并发为2,下载壁纸
 async.mapLimit(pic_url, 2, function(_pic_url, callback){
 fetchPic(_pic_url, callback);
 }, function (err, result){
 console.log('success');
 res.send(result[0]); // 取下标为0的元素
 });
 });
};

特别需要注意的两点:

1. “彼岸桌面”网页的编码是“GBK”的。而nodejs本身只支持“UTF-8”编码。这里我们引入“superagent-charset”模块,用于处理“GBK”的编码。

使用nodejs下载风景壁纸

附上github里的一个例子

https://github.com/magicdawn/superagent-charset

使用nodejs下载风景壁纸

2.  nodejs是异步的,同一时间发送大量的请求,有可能被服务器认为是恶意请求而拒绝。 因此这里引入“async”模块,用于并发的处理,使用的方法是:mapLimit。

mapLimit(arr, limit, iterator, callback)

这个方法有4个参数:

第1个参数是数组。

第2个参数是并发请求的数量。

第3个参数是迭代器,通常是一个函数。

第4个参数是并发执行后的回调。

这个方法的作用是将arr中的每个元素同时并发limit次拿给iterator去执行,执行结果传给最后的callback。

后话

至此,便完成了图片的下载。

完整的代码,已经放在github上

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

NodeJs 相关文章推荐
详谈nodejs异步编程
Dec 04 NodeJs
NodeJS制作爬虫全过程
Dec 22 NodeJs
Nodejs中读取中文文件编码问题、发送邮件和定时任务实例
Jan 01 NodeJs
nodejs事件的监听与触发的理解分析
Feb 12 NodeJs
详解如何在NodeJS项目中优雅的使用ES6
Apr 22 NodeJs
nodejs结合socket.io实现websocket通信功能的方法
Jan 12 NodeJs
NodeJS 中Stream 的基本使用
Jul 30 NodeJs
详解webpack打包nodejs项目(前端代码)
Sep 19 NodeJs
nodejs中函数的调用实例详解
Oct 31 NodeJs
nodejs实现百度舆情接口应用示例
Feb 07 NodeJs
nodeJs项目在阿里云的简单部署
Nov 27 NodeJs
分享node.js实现简单登录注册的具体代码
Apr 26 NodeJs
nodeJs链接Mysql做增删改查的简单操作
Feb 04 #NodeJs
nodejs基础应用
Feb 03 #NodeJs
nodejs基础知识
Feb 03 #NodeJs
windows 下安装nodejs 环境变量设置
Feb 02 #NodeJs
图片上传之FileAPI与NodeJs
Jan 24 #NodeJs
初探nodeJS
Jan 24 #NodeJs
进阶之初探nodeJS
Jan 24 #NodeJs
You might like
追求程序速度,而不是编程的速度
2008/04/23 PHP
PHP判断一个字符串是否是回文字符串的方法
2015/03/23 PHP
php使用socket post数据到其它web服务器的方法
2015/06/02 PHP
PHP简单获取随机数的常用方法小结
2017/06/07 PHP
jQuery中filter(),not(),split()使用方法
2010/07/06 Javascript
javascript中Date()函数在各浏览器中的显示效果
2015/06/18 Javascript
JavaScript淡入淡出渐变简单实例
2015/08/06 Javascript
js实现iPhone界面风格的单选框和复选框按钮实例
2015/08/18 Javascript
jquery中each循环的简单回滚操作
2017/05/05 jQuery
详解vue如何使用rules对表单字段进行校验
2018/10/17 Javascript
jquery ajax 请求小技巧实例分析
2019/11/11 jQuery
微信小程序wx.navigateTo方法里的events参数使用详情及场景
2020/01/07 Javascript
JS对象属性的检测与获取操作实例分析
2020/03/17 Javascript
vscode调试node.js的实现方法
2020/03/22 Javascript
JS面向对象实现飞机大战
2020/08/26 Javascript
[01:03:22]LGD vs OG 2018国际邀请赛淘汰赛BO3 第一场 8.25
2018/08/29 DOTA
详解Python中的各种函数的使用
2015/05/24 Python
Python利用IPython提高开发效率
2016/08/10 Python
Python序列操作之进阶篇
2016/12/08 Python
Python爬虫实例扒取2345天气预报
2018/03/04 Python
Win7 64位下python3.6.5安装配置图文教程
2020/10/27 Python
python求最大连续子数组的和
2018/07/07 Python
Python3+PyInstall+Sciter解决报错缺少dll、html等文件问题
2019/07/15 Python
python打印n位数“水仙花数”(实例代码)
2019/12/25 Python
解决Python3.8用pip安装turtle-0.0.2出现错误问题
2020/02/11 Python
Django Channel实时推送与聊天的示例代码
2020/04/30 Python
python代码能做成软件吗
2020/07/24 Python
Python实现扫码工具的示例代码
2020/10/09 Python
求职自荐书范文
2013/12/04 职场文书
公司建议书怎么写
2014/05/15 职场文书
医院标语大全
2014/06/23 职场文书
小学开学典礼新闻稿
2015/07/17 职场文书
2016年感恩母亲节活动总结
2016/04/01 职场文书
用Python的绘图库(matplotlib)绘制小波能量谱
2021/04/17 Python
mysql数据插入覆盖和时间戳的问题及解决
2022/03/25 MySQL
介绍一下28个JS常用数组方法
2022/05/06 Javascript