使用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 22 NodeJs
NodeJS Web应用监听sock文件实例
Feb 18 NodeJs
Nodejs中解决cluster模块的多进程如何共享数据问题
Nov 10 NodeJs
async/await与promise(nodejs中的异步操作问题)
Mar 03 NodeJs
详解nodejs爬虫程序解决gbk等中文编码问题
Apr 06 NodeJs
Nodejs中使用captchapng模块生成图片验证码
May 18 NodeJs
nodeJS(express4.x)+vue(vue-cli)构建前后端分离实例(带跨域)
Jul 05 NodeJs
nodejs使用express获取get和post传值及session验证的方法
Nov 09 NodeJs
nodejs+mongodb aggregate级联查询操作示例
Mar 17 NodeJs
nodejs更新package.json中的dependencies依赖到最新版本的方法
Oct 10 NodeJs
Nodejs + sequelize 实现增删改查操作
Nov 07 NodeJs
nodejs中内置模块fs,path常见的用法说明
Nov 07 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
通过文字传递创建的图形按钮
2006/10/09 PHP
phpfans留言版用到的install.php
2007/01/04 PHP
部署PHP时的4个配置修改说明
2015/10/19 PHP
smarty学习笔记之常见代码段用法总结
2016/03/19 PHP
PHP页面输出搜索后跳转下一页的处理方法
2016/09/30 PHP
通过php动态传数据到highcharts
2017/04/05 PHP
PHP常用函数之base64图片上传功能详解
2019/10/21 PHP
基于jQuery的试卷自动排版系统实现代码
2011/01/06 Javascript
jquery不会自动回收xmlHttpRequest对象 导致了内存溢出
2012/06/18 Javascript
jquery 无限级下拉菜单的简单实现代码
2014/02/21 Javascript
瀑布流布局代码一例
2014/04/11 Javascript
浅谈jQuery的offset()方法及示例分享
2015/07/17 Javascript
SWFObject基本用法实例分析
2015/07/20 Javascript
jQuery实现的经典竖向伸缩菜单效果代码
2015/09/24 Javascript
Javascript中return的使用与闭包详解
2017/01/11 Javascript
Vue实例中生命周期created和mounted的区别详解
2017/08/25 Javascript
使用cropper.js裁剪头像的实例代码
2017/09/29 Javascript
微信小程序使用checkbox显示多项选择框功能【附源码下载】
2017/12/11 Javascript
vue1.0和vue2.0的watch监听事件写法详解
2018/09/11 Javascript
Python实现统计单词出现的个数
2015/05/28 Python
详谈Python中列表list,元祖tuple和numpy中的array区别
2018/04/18 Python
PyQt5实现无边框窗口的标题拖动和窗口缩放
2018/04/19 Python
利用python的socket发送http(s)请求方法示例
2018/05/07 Python
浅谈Python中的可迭代对象、迭代器、For循环工作机制、生成器
2019/03/11 Python
Python面向对象程序设计类的封装与继承用法示例
2019/04/12 Python
vue常用指令代码实例总结
2020/03/16 Python
Python3如何实现Win10桌面自动切换
2020/08/11 Python
python 多进程和协程配合使用写入数据
2020/10/30 Python
使用HTML5在网页中嵌入音频和视频播放的基本方法
2016/02/22 HTML / CSS
瑞典领先的汽车零部件网上零售商:bildelaronline24.se
2017/01/12 全球购物
装修施工安全责任书
2014/07/24 职场文书
2015届大学生就业推荐表自我评价
2014/09/27 职场文书
2014年校长工作总结
2014/12/11 职场文书
幼儿学前班评语
2014/12/29 职场文书
2015年十一国庆节演讲稿
2015/03/20 职场文书
无保留意见审计报告
2015/06/05 职场文书