这两天刚换了linux系统,一直感觉自带的桌面图片有限而且不是特别“性感”,决定去弄几张图片回来当桌面壁纸,搜索了一下壁纸站点,觉得zol的还不错,分类清晰,壁纸质量上乘,就决定下载几张,但是网站繁琐的导流量页面导致下载一个图片非常繁琐和缓慢,而且效率太低下了,作为码农怎么能忍,分析一下,给他来个一锅端,12万的壁纸,尽收硬盘中。好了,上边的就是需求的描述了,下边是干货抓取过程。
1. 开发环境Nodejs。环境搭建就不累述了,知道的去nodejs官网自己简单科普一下就好了。传送到nodejs官网
2. 手把手过程
2.1 初始化工程
#新建个项目目录 mkdir zol_desk #进入项目目录 cd zol_desk #初始化npm npm init #一路回车知道完成 #安装crawler工具 npm install crawler --save #安装个lodash工具,有可能会用到,处理数据方便一些。 npm install lodash --save #创建个list.js文件,用来抓取列表数据 touch list.js
2.2 list.js 内容
1 const fs = require('fs'); 2 const Crawler = require('crawler'); 3 const _ = require('lodash'); //就用到一个range函数,其实用for循环也可以,只是用习惯了而已 4 //桌面站点的路由模式http://desk.zol.com.cn/pc/x.html, 这里的x代表页数,如1,2,3,...2000 5 const PATH_URL = 'http://desk.zol.com.cn/pc/x.html'; 6 const L = 334; //334是最大页数,实际网站分析得到的这个数 7 8 let cnt = 0; 9 10 let RS = []; 11 12 var c = new Crawler({ 13 maxConnections : 10, 14 callback : function (error, res, done) { 15 if(error) { 16 console.log(error) 17 } else { 18 var $ = res.$; 19 var list = $('.pic-list2 li a'); 20 list.each((k, item)=>{ 21 RS.push(item.attribs.href); 22 }); 23 console.log(`${cnt++} / ${L}`); //这里就是为了自己在console中看到进展,没有实际用处。 24 } 25 done(); 26 } 27 }); 28 29 const makeList = ()=> { 30 return _.range(1, L + 1).map(item=>PATH_URL.replace('x', item)); 31 } 32 33 const writeListJson = ()=>{
//写入列表文件 34 fs.writeFile('./data/list.json', JSON.stringify(RS), function(){ 35 console.log('all requests done and json saved!') 36 }); 37 } 38 39 c.queue(makeList()); 40 41 c.on('drain', writeListJson);
2.3 pics.js 图片详情页面,因为是每一个合集,里面还有更多的具体图片路径,将其中图片路径整理出来。
1 const fs = require('fs'); 2 const Crawler = require('crawler'); 3 const _ = require('lodash'); 4 let data = require('./data/list.json'); 5 const DOMAIN = 'http://desk.zol.com.cn'; 6 7 let cnt = 0; 8 let RS = []; 9 10 const makeList = ()=> { 11 return data.map(item=> DOMAIN + item); 12 } 13 14 data = makeList(); 15 16 var c = new Crawler({ 17 maxConnections : 10, 18 callback : function (error, res, done) { 19 if(error) { 20 console.log(error) 21 } else { 22 var s = res.body.match(/var deskPicArr .+;/)[0]; 23 s = s.replace(/var\sdeskPicArr\s+=\s+/, ''); 24 s = s.replace(/;\s{0,}$/g, ''); 25 var x = JSON.parse(s).list; 26 x = x.map(item=>{ 27 return item.imgsrc.replace('##SIZE##', item.oriSize) 28 }); 29 RS = [...RS, ...x]; 30 console.log(cnt++ + '/' + data.length ) 31 } 32 done(); 33 } 34 }); 35 36 37 c.queue(data); 38 39 c.on('drain', function(){ 40 fs.writeFile('data/pics.json', JSON.stringify(RS), function(err, data){ 41 if(err) console.log(err); 42 console.log('fileSaved!') 43 }) 44 });
2.4 images.js 根据整理出来的图片路径,下载相应的图片到本地磁盘路径下。
1 const fs = require('fs'); 2 const chalk = require('chalk'); 3 const Crawler = require('crawler'); 4 const _ = require('lodash'); 5 let data = require('./data/pics.json'); 6 let cnt = 0; 7 const DOMAIN = 'http://desk.zol.com.cn'; 8 const parseFileNameFromUrl = (url)=> { 9 var a = url.split('/'); 10 return a[a.length -1]; 11 } 12 13 14 var c = new Crawler({ 15 encoding: null, 16 jQuery: false, 17 maxConnections : 10, 18 callback: function (error, res, done) { 19 if(error) { 20 console.log(error) 21 } else { 22 const fileName = parseFileNameFromUrl(res.options.uri); 23 const str = chalk.blue('fileName = ' + fileName) 24 console.log(str); 25 fs.createWriteStream('./data/images/' + fileName).write(res.body); 26 console.log(cnt++ + '/' + data.length ) 27 } 28 done(); 29 } 30 }); 31 32 33 c.queue(data); 34 35 c.on('drain', function(){ 36 console.log('All images saved!') 37 });