使用nodejs 批量下载虾米音乐的 方法。
使用到的工具 fs,cheerio,request,redis;

模块 作用
fs 主要完成建立目录和文件的功能
request 用于进行访问url
cheerio 页面解析
redis 使用数据库存储歌手的信息,持久化,也可不要,使用数组,看个人需求。

主要分为以下几个步骤。
1.输入你想要的歌手的名字
2.搜索歌手的专辑
3访问专辑页面
4获取专辑里歌曲id
5获取歌曲id对应的真实下载url。

首先1 完成下载某一首歌曲的功能。给定下载的歌名,歌曲id,歌手,下载路径

function download(songname,songid,singer,dir) {var requesturl = getSongUrl(songid);if(requesturl){request(requesturl, function (req, res, err) {var body;if (res) {var $ = cheerio.load(res.body, {xmlMode: true});var urlstr = $('location').text();if(urlstr){var songUrl = decodeUrl(urlstr);var path = dir+songname.trim().replace('\/','_') + '_' + singer + '.mp3';fs.access(path, function (err) {if (err) {if(songUrl) {console.log("正在下载"+songname);request(songUrl).pipe(fs.createWriteStream(path)).on('end',function(err){console(err?songname+'下载失败':songname+"下载成功");});}} });}else{console.log(songname+'无法下载');}} else {console.log(songname+'没有下载权限');}})}
}

2 完成下载专辑和图片的功能,使用request(url).pipe(stream)即可

function downloadAlbum(picurl,albumurl,albumname,singer){var basedir = './'+singer;var dir = basedir+'/'+albumname+'/';var picname = albumname+'.jpg';fs.access(basedir,function(err){if(err){fs.mkdir(basedir,function(err){fs.access(dir,function(err){if(err){fs.mkdir(dir,function(err){downloadCoverAndSongs(picurl,albumurl,dir,singer);})}else{downloadCoverAndSongs(picurl,albumurl,dir,singer);}});});}else{fs.access(dir,function(err){if(err){fs.mkdir(dir,function(err){downloadCoverAndSongs(picurl,albumurl,dir,picname,singer);})}else{downloadCoverAndSongs(picurl,albumurl,dir,picname,singer);}})}});}function downloadCoverAndSongs(picurl,albumurl,dir,picname,singer){request(picurl).pipe(fs.createWriteStream(dir+picname));request(albumurl,function(req,res,err){if(res) {var $ = cheerio.load(res.body, {decodeEntities: false});var songstable = $('#track_list tr[data-needpay]');if(songstable){for(var i in songstable){var song = songstable.eq(i).find('td.song_name a:first-child');if(song.text()){var songid = song.attr('href').slice(6);var songname = song.text();download(songname,songid,singer,dir);}}}}})
}

3,搜索歌手返回歌手的所有专辑id和相应的专辑url。

function searchSinger(singer){const singerurl = 'http://www.xiami.com/search?key='+encodeURIComponent(singer)+'&pos=1';var albumarr = [];request(singerurl,function(req,res,err){//if(err){//    console.log('something wrong');////}else{if(res.body){var $ = cheerio.load(res.body,{decodeEntities:false});var albumslist = $('div.result_main ul.clearfix').eq(0);var albums = albumslist.find("li[data-needpay]");var picurl,albumname,songsurl;for(var i in albums){var album = albums.eq(i);picurl = album.find('a.CDcover100 img').attr('src');albumname = album.find('p.name a.song').attr('title');songsurl = album.find('p.name a.song').attr('href');if(album.data('needpay')){console.log(albumname+'需要付费');}else{if(album.data('needpay')=='0'){var albumobj = {picurl:picurl,albumname:albumname,songsurl:songsurl};albumarr.push(JSON.stringify(albumobj));}}}if(albumarr) {client.lpush("singer_albums", albumarr, function (err) {if (err) {console.log(err);}})}}//}});}
function getSongUrl(songid){const urlPrefix = 'http://www.xiami.com/widget/xml-single/uid/0/sid/';return urlPrefix+songid;
}

getSongurl函数就是通过给定songid访问到以上页面,得到一个xml的数据格式,然后从xml数据中找到 location这一项。

可以看到一串乱码,这串乱码的开头是一个数字,代表是一个n行的矩阵,对这个字符串数字以后的进行n行排列,然后再按列读取,最后进行URL译码,再对剩下的’^’,进行替换就找到了歌曲的url。

function decodeUrl(str) {var finalresult;var needstr = str.slice(1);var lines = str.slice(0, 1) - 0;var cols = Math.ceil(needstr.length / lines);var leftline = needstr.length % lines;var arr = [];var result = "";for (var j = 0; j < leftline; j++) {arr[j] = needstr.slice(cols * j, cols * (j + 1));}var leftstr = needstr.slice((leftline) * cols);for (var j = 0; j < lines - leftline; j++) {arr[leftline + j] = leftstr.slice((cols - 1) * j, (cols - 1) * (j + 1))}for (var i = 0; i < cols; i++) {for (var j = 0; j < lines; j++) {if (arr[j][i]) {result += arr[j][i];}}}try{finalresult = decodeURIComponent(result).replace(/[\^]/g, '0');}catch(err){if(err){return ;}}finally{return finalresult;}
}

decodeUrl函数是译码函数。完成译码工作。

还可以下载collects里的歌曲。只不过就是简单的获取到collect对应的界面而已

function getCollectsSongUrl() {var now = new Date();rankurl = rankurl + now.valueOf();options = {url:rankurl,headers:headers};request(options, function (req, res, err) {if (res.body) {var body = JSON.parse(res.body).data.charts;var $ = cheerio.load(body, {decodeEntities: false});var songlists = $('div.content div.info');var songs = [];for (var i in songlists) {var song = songlists.eq(i);if (song.text()) {var name = song.find('p strong>a').text();var songid = song.find('p strong>a').attr('href').slice(6);var singer = song.find('p.singer a').attr('title');var songobj = {name:name,id:songid,singer:singer};songobj = JSON.stringify(songobj);songs.push(songobj);}}client.sadd('songs',songs,function(err,val){console.log(val);});}});
};

如果使用redis,请提前安装redis.

完整程序如下

/*** Created by aidim78 on 2016/11/23.*/
const request = require('request');
const cheerio = require('cheerio');
const fs = require('fs');
const redis = require('redis');
const client = redis.createClient();var headers={'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Safari/602.1.50'}
;
function getCollectsSongUrl() {var rankurl = 'http://www.xiami.com/index/collect?_=';var now = new Date();rankurl = rankurl + now.valueOf();options = {url:rankurl,headers:headers};request(options, function (req, res, err) {if (res.body) {var body = JSON.parse(res.body).data.charts;var $ = cheerio.load(body, {decodeEntities: false});var songlists = $('div.content div.info');var songs = [];for (var i in songlists) {var song = songlists.eq(i);if (song.text()) {var name = song.find('p strong>a').text();var songid = song.find('p strong>a').attr('href').slice(6);var singer = song.find('p.singer a').attr('title');var songobj = {name:name,id:songid,singer:singer};songobj = JSON.stringify(songobj);songs.push(songobj);}}client.sadd('songs',songs,function(err,val){console.log(val);});}});
};function decodeUrl(str) {var finalresult;var needstr = str.slice(1);var lines = str.slice(0, 1) - 0;var cols = Math.ceil(needstr.length / lines);var leftline = needstr.length % lines;var arr = [];var result = "";for (var j = 0; j < leftline; j++) {arr[j] = needstr.slice(cols * j, cols * (j + 1));}var leftstr = needstr.slice((leftline) * cols);for (var j = 0; j < lines - leftline; j++) {arr[leftline + j] = leftstr.slice((cols - 1) * j, (cols - 1) * (j + 1))}for (var i = 0; i < cols; i++) {for (var j = 0; j < lines; j++) {if (arr[j][i]) {result += arr[j][i];}}}try{finalresult = decodeURIComponent(result).replace(/[\^]/g, '0');}catch(err){if(err){return ;}}finally{return finalresult;}
}function getSongUrl(songid){const urlPrefix = 'http://www.xiami.com/widget/xml-single/uid/0/sid/';return urlPrefix+songid;
}
function download(songname,songid,singer,dir) {var requesturl = getSongUrl(songid);if(requesturl){request(requesturl, function (req, res, err) {var body;if (res) {var $ = cheerio.load(res.body, {xmlMode: true});var urlstr = $('location').text();if(urlstr){var songUrl = decodeUrl(urlstr);var path = dir+songname.trim().replace('\/','_') + '_' + singer + '.mp3';fs.access(path, function (err) {if (err) {if(songUrl) {console.log("正在下载"+songname);request(songUrl).pipe(fs.createWriteStream(path)).on('end',function(err){console(err?songname+'下载失败':songname+"下载成功");});}} });}else{console.log(songname+'无法下载');}} else {console.log(songname+'没有下载权限');}})}
}
function doit() {const rl = require('readline').createInterface(process.stdin,process.stdout);console.log('输入你想要的歌手!');rl.on('line',function(singer){searchSinger(singer.trim());client.lrange('singer_albums',0,-1,function(err,val){if(err){console.log(err);} else{var arr = val;if(arr) {for (var i in arr) {var songinfo = JSON.parse(arr[i]);var albumpic = songinfo.picurl;var albumname = songinfo.albumname;var albumurl = songinfo.songsurl;downloadAlbum(albumpic, albumurl, albumname, singer);}}}});});}
function searchSinger(singer){const singerurl = 'http://www.xiami.com/search?key='+encodeURIComponent(singer)+'&pos=1';var albumarr = [];request(singerurl,function(req,res,err){//if(err){//    console.log('something wrong');////}else{if(res.body){var $ = cheerio.load(res.body,{decodeEntities:false});var albumslist = $('div.result_main ul.clearfix').eq(0);var albums = albumslist.find("li[data-needpay]");var picurl,albumname,songsurl;for(var i in albums){var album = albums.eq(i);picurl = album.find('a.CDcover100 img').attr('src');albumname = album.find('p.name a.song').attr('title');songsurl = album.find('p.name a.song').attr('href');if(album.data('needpay')){console.log(albumname+'需要付费');}else{if(album.data('needpay')=='0'){var albumobj = {picurl:picurl,albumname:albumname,songsurl:songsurl};albumarr.push(JSON.stringify(albumobj));}}}if(albumarr) {client.lpush("singer_albums", albumarr, function (err) {if (err) {console.log(err);}})}}//}});}
// function searchSong(songname){//     var searchurl = 'http://www.xiami.com/search?key='+encodeURIComponent(songname)+'&pos=1';// }
function downloadAlbum(picurl,albumurl,albumname,singer){var basedir = './'+singer;var dir = basedir+'/'+albumname+'/';var picname = albumname+'.jpg';fs.access(basedir,function(err){if(err){fs.mkdir(basedir,function(err){fs.access(dir,function(err){if(err){fs.mkdir(dir,function(err){downloadCoverAndSongs(picurl,albumurl,dir,singer);})}else{downloadCoverAndSongs(picurl,albumurl,dir,singer);}});});}else{fs.access(dir,function(err){if(err){fs.mkdir(dir,function(err){downloadCoverAndSongs(picurl,albumurl,dir,picname,singer);})}else{downloadCoverAndSongs(picurl,albumurl,dir,picname,singer);}})}});}function downloadCoverAndSongs(picurl,albumurl,dir,picname,singer){request(picurl).pipe(fs.createWriteStream(dir+picname));request(albumurl,function(req,res,err){if(res) {var $ = cheerio.load(res.body, {decodeEntities: false});var songstable = $('#track_list tr[data-needpay]');if(songstable){for(var i in songstable){var song = songstable.eq(i).find('td.song_name a:first-child');if(song.text()){var songid = song.attr('href').slice(6);var songname = song.text();download(songname,songid,singer,dir);}}}}})
}
doit();

自己更具兴趣可以添加 下载指定歌曲和指定专辑 指定 电台 指定 歌单等歌曲,原理类似不再做讲解。

nodejs虾米音乐批量下载某个歌手的专辑相关推荐

  1. 获取Google音乐的详细信息(方便对Google音乐批量下载)

    Google音乐都是正版音乐, 不像百度全部都是盗链, 而且死链也多. 但有一个麻烦就是要下载Google音乐的时候得一个一个的点击下载链接, 进入下载页面再点"下载", 才能下载 ...

  2. 批量下载指定歌手的百度mp3

    批量下载指定歌手的百度mp3 Luo Weifeng 2011-3-30 尊重作者,转载请保留:http://blog.csdn.net/luoweifeng1989/archive/2011/03/ ...

  3. Sahi案例分享:音乐批量下载

    from http://www.infoq.com/cn/articles/sahi-google-music-download 作者沈锐发布于2012年6月13日 领域 运维 & 基础架构, ...

  4. 从百度MP3中批量下载某歌手的歌

    #!/usr/bin/python # -*- coding: utf-8 -*- ############################### #百度中批量下载某歌手的歌 ############ ...

  5. 网易云音乐批量下载器v1.1软件介绍(修正版)

    网易云音乐批量下载器简介 网易云音乐批量下载器v1.1 软件介绍 1.编写初衷 2.界面展示 3.使用方法 如何获取cookie? 4.其他说明 5.下载地址 网易云音乐批量下载器v1.1 软件介绍 ...

  6. 最简单的虾米音乐爬虫下载

    今天玩乐队的舍友让我给他扒一首歌,是虾米音乐上的,之前也帮他批量爬取过网易云的付费音乐歌曲 先按照惯例我打开了他给的音乐链接 https://www.xiami.com/song/1775018820 ...

  7. 网易云音乐批量下载python

    # #批量下载 import requests from lxml import etree url='https://music.163.com/discover/toplist?id=377962 ...

  8. 豆瓣FM加心音乐批量下载

    如何批量下载豆瓣电台加红心歌曲 注:批量从豆瓣电台抓取歌曲列表的功能(来自@牛牛 微博) 1.登陆豆瓣电台 2.进入加红星的网页或者输入网址http://douban.fm/mine?type=lik ...

  9. 全民K歌音乐批量下载源码

    源码介绍: 我有个朋友,他无意间登录全民K歌发现前女友居然在上面唱歌,唱的都是"你还好嘛""我最爱的人""单身的我"等这些歌曲,朋友听后一阵 ...

最新文章

  1. 史上首次,强化学习算法控制核聚变登上Nature:DeepMind让人造太阳向前一大步...
  2. Linux怎么查询全部容器时间,docker容器与Linux主机环境获取时间不一致
  3. 史上最全,最完美的 JAVA 技术体系思维导图总结,没有之一!
  4. spring系列-注解驱动原理及源码-自动装配
  5. NoSuchMethodError和NoSuchMethodException 区别
  6. boost::equal_range相关的测试程序
  7. Kafka集成Spring-AcknowledgeMessageListener接口实现
  8. springboot+shiro+redis项目整合
  9. SpringBoot_配置-properties配置文件编码问题
  10. Web前端开发笔记——第三章 CSS语言 第六节 CSS定位
  11. html显示数据库的数据类型,将HTML插入mysql数据库,显示E类型
  12. 魔方层先法简明图解,最少记6个公式即可完成魔方六面
  13. LightGBM 二元分类、多类分类、 Python的回归和分类器应用
  14. 网页版office服务器,Office 网页版服务说明
  15. linux下C++编程学习
  16. ANSI 标准是为了确保 C++ 的便携性
  17. 阿里大数据之路:数据模型篇大总结(收藏)
  18. python df 合并_pandas两个df数据如何合并?
  19. Qt扫盲-QList使用总结
  20. python批量检索文献_快解锁新姿势,教你如何用Python搞定文献搜索和科研图片!...

热门文章

  1. SQLite 创建表
  2. Vue中$emit的用法
  3. aucad1012_64位安装前必须安装的程序
  4. org.apache.jasper.JasperException: The absolute uri: [http://java.sun.com/jsp/jstl/core] cannot be r
  5. 学习笔记 - CFA 权益
  6. 曼彻斯特编码 C语言 解码程序
  7. setsockopt函数功能及参数详解
  8. 品牌形象设计的流程解析
  9. 基于微信小程序实现番茄钟专注时间项目演示【附项目源码+论文说明】分享
  10. notifyAll()