使用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 模块开发及发布详解分享
Mar 07 NodeJs
nodejs中操作mysql数据库示例
Dec 20 NodeJs
Nodejs中调用系统命令、Shell脚本和Python脚本的方法和实例
Jan 01 NodeJs
搭建简单的nodejs http服务器详解
Mar 09 NodeJs
nodejs 终端打印进度条实例代码
Apr 22 NodeJs
Windows下使用Nodejs运行js的方法
Sep 02 NodeJs
nodejs更改项目端口号的方法
May 13 NodeJs
Linux Centos7.2下安装nodejs&amp;npm配置全局路径的教程
May 15 NodeJs
对mac下nodejs 更新到最新版本的最新方法(推荐)
May 17 NodeJs
Nodejs把接收图片base64格式保存为文件存储到服务器上
Sep 26 NodeJs
nodejs微信开发之接入指南
Mar 17 NodeJs
使用 Koa + TS + ESLlint 搭建node服务器的过程详解
May 30 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实现蜘蛛访问日志统计
2013/07/05 PHP
php实现和c#一致的DES加密解密实例
2017/07/24 PHP
PHP文件管理之实现网盘及压缩包的功能操作
2017/09/20 PHP
Input 特殊事件onpopertychange和oninput
2009/06/17 Javascript
JavaScript 获取当前时间戳的代码
2010/08/05 Javascript
js中更短的 Array 类型转换
2011/10/30 Javascript
js或jquery实现页面打印可局部打印
2014/03/27 Javascript
javascript中typeof操作符和constucor属性检测
2015/02/26 Javascript
BootStrap iCheck插件全选与获取value值的解决方法
2016/08/24 Javascript
Angularjs CURD 详解及实例代码
2016/09/14 Javascript
JSON对象 详解及实例代码
2016/10/18 Javascript
概述如何实现一个简单的浏览器端js模块加载器
2016/12/07 Javascript
AngularJS表单基本操作
2017/01/09 Javascript
基于bootstrap实现收缩导航条
2017/03/17 Javascript
详解如何使用vue-cli脚手架搭建Vue.js项目
2017/05/19 Javascript
nodejs集成sqlite使用示例
2017/06/05 NodeJs
MUI实现上拉加载和下拉刷新效果
2017/06/30 Javascript
Angular实现响应式表单
2017/08/04 Javascript
详解Vue组件实现tips的总结
2017/11/01 Javascript
jquery实现侧边栏左右伸缩效果的示例
2017/12/19 jQuery
ES6 Symbol数据类型的应用实例分析
2019/06/26 Javascript
[01:08:32]DOTA2-DPC中国联赛 正赛 DLG vs PHOENIX BO3 第二场 1月18日
2021/03/11 DOTA
python实现rsa加密实例详解
2017/07/19 Python
Pyqt实现无边框窗口拖动以及窗口大小改变
2018/04/19 Python
python判断一个集合是否为另一个集合的子集方法
2018/05/04 Python
Django使用unittest模块进行单元测试过程解析
2019/08/02 Python
Python基于pygame实现单机版五子棋对战
2019/12/26 Python
pycharm下配置pyqt5的教程(anaconda虚拟环境下+tensorflow)
2020/03/25 Python
python redis存入字典序列化存储教程
2020/07/16 Python
python+opencv3.4.0 实现HOG+SVM行人检测的示例代码
2021/01/28 Python
化学教师教学反思
2014/01/17 职场文书
情人节活动策划方案
2014/02/27 职场文书
教师求职信
2014/06/17 职场文书
2015年基层党支部工作总结
2015/05/21 职场文书
仰望星空观后感
2015/06/10 职场文书
公司团队口号霸气押韵
2015/12/24 职场文书