node爬取網易雲歌曲

原由:老爸讓我下載幾千首歌曲給他在車上播放,感受手動下載,就算批量下載也要時間,索性寫個爬蟲自動下載吧。。html

對於這個爬蟲小項目,選擇了node+koa2,初始化項目koa2 projectName(須要先全局安裝koa-generator),而後進入項目文件,npm install && npm start,其中依賴用到了superagent, cheerio, async, fs, pathnode

打開網易雲網頁版,點擊歌單頁面,我選擇了華語分類,右鍵查看框架源碼,獲取真實url,找到id爲m-pl-container的html結構,這就是此次須要爬取的歌單列表,直接用superagent請求url,只能爬取到第一頁的數據,須要async來併發爬取npm

static getPlayList(){
	const pageUrlList = this.getPageUrl();

	return new Promise((resolve, reject) => {
		asy.mapLimit(pageUrlList, 1, (url, callback) => {
			this.requestPlayList(url, callback);
		}, (err, result) => {
			if(err){
				reject(err);
			}

			resolve(result);
		})
	})
}
複製代碼

其中const asy = require('async'),由於用到async/await,因此區分下,requestPlayList是superagent發起的請求小程序

static requestPlayList(url, callback){
	superagent.get(url).set({
		'Connection': 'keep-alive'
	}).end((err, res) => {
		if(err){
			console.info(err);
			callback(null, null);
			return;
		}

		const $ = cheerio.load(res.text);
		let curList = this.getCurPalyList($);
		callback(null, curList);  
	})
}
複製代碼

getCurPalyList是獲取頁面上的信息,傳入$用於dom操做bash

static getCurPalyList($){
	let list = [];

	$('#m-pl-container li').each(function(i, elem){
		let _this = $(elem);
		list.push({
			name: _this.find('.dec a').text(),
			href: _this.find('.dec a').attr('href'),
			number: _this.find('.nb').text()
		});
	});

	return list;
}
複製代碼

至此,歌單列表爬取完成,接下來要爬取歌曲列表併發

static async getSongList(){
	const urlCollection = await playList.getPlayList();

	let urlList = [];
	for(let item of urlCollection){
		for(let subItem of item){
			urlList.push(baseUrl + subItem.href);
		}
	}

	return new Promise((resolve, reject) => {
		asy.mapLimit(urlList, 1, (url, callback) => {
			this.requestSongList(url, callback);
		}, (err, result) => {
			if(err){
				reject(err);
			}

			resolve(result);
		})
	})
}
複製代碼

requestSongList的使用跟上面playList的差很少,所以再也不重複。上面代碼獲取到歌曲列表後,須要下載到本地框架

static async downloadSongList(){
	const songList = await this.getSongList();

	let songUrlList = [];
	for(let item of songList){
		for(let subItem of item){
			let id = subItem.url.split('=')[1];
			songUrlList.push({
				name: subItem.name,
				downloadUrl: downloadUrl + '?id=' + id + '.mp3'
			});
		}
	}

	if(!fs.existsSync(dirname)){
		fs.mkdirSync(dirname);
	}
	
	return new Promise((resolve, reject) => {
		asy.mapSeries(songUrlList, (item, callback) => {
			setTimeout(() => {
				this.requestDownload(item, callback);
				callback(null, item);
			}, 5e3);
		}, (err, result) => {
			if(err){
				reject(err);
			}

			resolve(result);
		})
	})
}
複製代碼

其中requestDownload是請求downloadUrl並下載保存到本地dom

static requestDownload(item, callback){
	let stream = fs.createWriteStream(path.join(dirname, item.name + '.mp3'));

	superagent.get(item.downloadUrl).set({
		'Connection': 'keep-alive'
	}).pipe(stream).on('error', (err) => {
		console.info(err);   // error處理,爬取錯誤時,打印錯誤並繼續向下執行
	})
}
複製代碼

到此,爬蟲小程序完成。該項目爬取歌單列表-->歌曲列表-->下載到本地,固然也能夠直接找到某位歌手的主頁,修改傳入songList的url,直接下載該歌手的熱門歌曲。koa

相關文章
相關標籤/搜索