使用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 win7下安装方法
May 24 NodeJs
nodejs读取memcache示例分享
Jan 02 NodeJs
nodejs分页类代码分享
Jun 17 NodeJs
nodejs npm package.json中文文档
Sep 04 NodeJs
nodejs服务搭建教程 nodejs访问本地站点文件
Apr 07 NodeJs
CentOS 安装NodeJS V8.0.0的方法
Jun 15 NodeJs
nodejs创建简易web服务器与文件读写的实例
Sep 07 NodeJs
nodejs发送http请求时遇到404长时间未响应的解决方法
Dec 10 NodeJs
CentOS7中源码编译安装NodeJS的完整步骤
Oct 13 NodeJs
nodejs搭建本地服务器并访问文件操作示例
May 11 NodeJs
NodeJs 实现简单WebSocket即时通讯的示例代码
Aug 05 NodeJs
Nodejs文件上传、监听上传进度的代码
Mar 27 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
PHP 进程锁定问题分析研究
2009/11/24 PHP
使用PHP备份MYSQL数据的多种方法
2014/01/15 PHP
PHP中使用数组指针函数操作数组示例
2014/11/19 PHP
php遍历CSV类实例
2015/04/14 PHP
PHP性能测试工具xhprof安装与使用方法详解
2018/04/29 PHP
javascript appendChild,innerHTML,join性能比较代码
2009/08/29 Javascript
JavaScript中对循环语句的优化技巧深入探讨
2014/06/06 Javascript
Nodejs极简入门教程(三):进程
2014/10/27 NodeJs
使用Plupload实现直接上传附件至七牛云存储
2014/12/26 Javascript
Bootstrap中CSS的使用方法
2016/02/17 Javascript
JS判断iframe是否加载完成的方法
2016/08/03 Javascript
微信公众号 摇一摇周边功能开发
2016/12/08 Javascript
IntersectionObserver API 详解篇
2016/12/11 Javascript
JQuery validate 验证一个单独的表单元素实例
2017/02/17 Javascript
微信小程序实现图片轮播及文件上传
2017/04/07 Javascript
vue-cli3 项目从搭建优化到docker部署的方法
2019/01/28 Javascript
JS实现的点击按钮图片上下滚动效果示例
2019/01/28 Javascript
node删除、复制文件或文件夹示例代码
2019/08/13 Javascript
js实现开关灯效果
2020/03/30 Javascript
纯 JS 实现放大缩小拖拽功能(完整代码)
2019/11/25 Javascript
在vue中实现禁止回退上一步,路由不存历史记录
2020/07/22 Javascript
Python错误提示:[Errno 24] Too many open files的分析与解决
2017/02/16 Python
python面试题Python2.x和Python3.x的区别
2019/05/28 Python
python简单区块链模拟详解
2019/07/03 Python
利用Python的turtle库绘制玫瑰教程
2019/11/23 Python
Python字符串split及rsplit方法原理详解
2020/06/29 Python
Python通过getattr函数获取对象的属性值
2020/10/16 Python
Python使用eval函数执行动态标表达式过程详解
2020/10/17 Python
利用Python发送邮件或发带附件的邮件
2020/11/12 Python
pycharm 使用tab跳出正在编辑的括号(){}{}等问题
2021/02/26 Python
video结合canvas实现视频在线截图功能
2018/06/25 HTML / CSS
浅谈移动端网页图片预加载方案
2018/11/05 HTML / CSS
大学生志愿者感言
2014/01/15 职场文书
JS数组的常用方法整理
2021/03/31 Javascript
MySQL索引失效的典型案例
2021/06/05 MySQL
MySQL中datetime时间字段的四舍五入操作
2021/10/05 MySQL