这两天刚换了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 });