使用nodejs下載風(fēng)景壁紙
需要用到的第三方模塊有:
superagent
superagent-charset (手動(dòng)指定編碼,解決GBK中文亂碼)
cheerio
express
async (并發(fā)控制)
完整的代碼,可以在我的github中可以下載。主要的邏輯邏輯在 netbian.js 中。
以彼岸桌面(http://www.netbian.com/)欄目下的風(fēng)景壁紙(http://www.netbian.com/fengjing/index.htm)為例進(jìn)行講解。
1. 分析URL

不難發(fā)現(xiàn):
首頁(yè): 欄目/index.htm
分頁(yè): 欄目/index_具體頁(yè)碼.htm
知道這個(gè)規(guī)律,就可以批量下載壁紙了。
2. 分析壁紙縮略圖,找到對(duì)應(yīng)壁紙的大圖
使用chrome的開(kāi)發(fā)者工具,可以發(fā)現(xiàn),縮略圖列表在 class="list"的div里,a標(biāo)簽的href屬性的值就是單張壁紙所在的頁(yè)面。

部分代碼:
request
.get(url)
.end(function(err, sres){
var $ = cheerio.load(sres.text);
var pic_url = []; // 中等圖片鏈接數(shù)組
$('.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”繼續(xù)分析
打開(kāi)這個(gè)頁(yè)面,發(fā)現(xiàn)此頁(yè)面顯示的壁紙,依舊不是最高的分辨率。
點(diǎn)擊“下載壁紙”按鈕里的鏈接,打開(kāi)新的頁(yè)面。

4. 以“http://www.netbian.com/desk/17662-1920x1080.htm”繼續(xù)分析
打開(kāi)這個(gè)頁(yè)面,我們最終要下載的壁紙,放在一個(gè)table里面。如下圖,http://img.netbian.com/file/2017/0203/bb109369a1f2eb2e30e04a435f2be466.jpg
才是我們最終要下載的圖片的URL(幕后BOSS終于現(xiàn)身了(@ ̄ー ̄@))。

下載圖片的代碼:
request
.get(wallpaper_down_url)
.end(function(err, img_res){
if(img_res.status == 200){
// 保存圖片內(nèi)容
fs.writeFile(dir + '/' + wallpaper_down_title + path.extname(path.basename(wallpaper_down_url)), img_res.body, 'binary', function(err){
if(err) console.log(err);
});
}
});
打開(kāi)瀏覽器,訪問(wèn) http://localhost:1314/fengjing
選擇欄目和頁(yè)面,點(diǎn)擊“開(kāi)始”按鈕:

并發(fā)請(qǐng)求服務(wù)器,下載圖片。

完成~

圖片的存放目錄按照 欄目+頁(yè)碼 的形式保存。

附上完整的圖片下載的代碼:
/**
* 下載圖片
* @param {[type]} url [圖片URL]
* @param {[type]} dir [存儲(chǔ)目錄](méi)
* @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 = []; // 中等圖片鏈接數(shù)組
$('.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; // 并發(fā)計(jì)數(shù)器
var wallpaper = []; // 壁紙數(shù)組
var fetchPic = function(_pic_url, callback){
count++; // 并發(fā)加1
var delay = parseInt((Math.random() * 10000000) % 2000);
console.log('現(xiàn)在的并發(fā)數(shù)是:' + count + ', 正在抓取的圖片的URL是:' + _pic_url + ' 時(shí)間是:' + 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--; // 并發(fā)減1
// 請(qǐng)求大圖鏈接
request
.get(pic_down)
.charset('gbk') // 設(shè)置編碼, 網(wǎng)頁(yè)以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){
// 保存圖片內(nèi)容
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); // 返回?cái)?shù)據(jù)
});
}, delay);
};
// 并發(fā)為2,下載壁紙
async.mapLimit(pic_url, 2, function(_pic_url, callback){
fetchPic(_pic_url, callback);
}, function (err, result){
console.log('success');
res.send(result[0]); // 取下標(biāo)為0的元素
});
});
};
特別需要注意的兩點(diǎn):
1. “彼岸桌面”網(wǎng)頁(yè)的編碼是“GBK”的。而nodejs本身只支持“UTF-8”編碼。這里我們引入“superagent-charset”模塊,用于處理“GBK”的編碼。

附上github里的一個(gè)例子
https://github.com/magicdawn/superagent-charset

2. nodejs是異步的,同一時(shí)間發(fā)送大量的請(qǐng)求,有可能被服務(wù)器認(rèn)為是惡意請(qǐng)求而拒絕。 因此這里引入“async”模塊,用于并發(fā)的處理,使用的方法是:mapLimit。
mapLimit(arr, limit, iterator, callback)
這個(gè)方法有4個(gè)參數(shù):
第1個(gè)參數(shù)是數(shù)組。
第2個(gè)參數(shù)是并發(fā)請(qǐng)求的數(shù)量。
第3個(gè)參數(shù)是迭代器,通常是一個(gè)函數(shù)。
第4個(gè)參數(shù)是并發(fā)執(zhí)行后的回調(diào)。
這個(gè)方法的作用是將arr中的每個(gè)元素同時(shí)并發(fā)limit次拿給iterator去執(zhí)行,執(zhí)行結(jié)果傳給最后的callback。
后話
至此,便完成了圖片的下載。
完整的代碼,已經(jīng)放在github上
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持腳本之家!
相關(guān)文章
簡(jiǎn)單的說(shuō)Node.js就是運(yùn)行在服務(wù)端的JavaScript。Node.js是一個(gè)基于Chrome JavaScript運(yùn)行時(shí)建立的一個(gè)平臺(tái)。Node.js是一個(gè)事件驅(qū)動(dòng)I/O服務(wù)端JavaScript環(huán)境,基于Google的V8引擎,V8引擎執(zhí)行Javascript的速度非??欤阅芊浅:?/div> 2021-06-06
Node.js刷新session過(guò)期時(shí)間的實(shí)現(xiàn)方法推薦
下面小編就為大家?guī)?lái)一篇Node.js刷新session過(guò)期時(shí)間的實(shí)現(xiàn)方法推薦。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-05-05
關(guān)于Node.js中Buffer的一些你可能不知道的用法
網(wǎng)上關(guān)于Node.js中Buffer用法的文章有很多,但是感覺(jué)還是不夠詳細(xì),所以這篇文章主要介紹了關(guān)于Node.js中Buffer的一些你可能不知道的用法,文中介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-03-03
Node發(fā)出HTTP POST請(qǐng)求的方法實(shí)例小結(jié)
這篇文章主要介紹了Node發(fā)出HTTP POST請(qǐng)求的方法,結(jié)合實(shí)例形式總結(jié)分析了三種常用的post請(qǐng)求操作方法,以及相關(guān)庫(kù)操作注意事項(xiàng),需要的朋友可以參考下2023-05-05
nodejs和php實(shí)現(xiàn)圖片訪問(wèn)實(shí)時(shí)處理
這篇文章主要為大家詳細(xì)介紹了nodejs和php分別實(shí)現(xiàn)圖片訪問(wèn)實(shí)時(shí)處理,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01
詳解nodejs微信公眾號(hào)開(kāi)發(fā)——3.封裝消息響應(yīng)模塊
上一篇文章:nodejs微信公眾號(hào)開(kāi)發(fā)(2)自動(dòng)回復(fù),實(shí)現(xiàn)了簡(jiǎn)單的關(guān)注回復(fù)。采用拼接字符串的形式,并不是很方便,這里我們將其封裝承接口。2017-04-04
Node.js中使用Buffer編碼、解碼二進(jìn)制數(shù)據(jù)詳解
這篇文章主要介紹了Node.js中使用Buffer編碼、解碼二進(jìn)制數(shù)據(jù)詳解,Buffer支持ascii、utf8、ucs2、base64等編碼格式,需要的朋友可以參考下2014-08-08最新評(píng)論

