网易云下载

歌单里好多歌用以前的脚本都404了,于是简单修改了下。

目前为 2017-06-17 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name 网易云下载
  3. // @description 歌单里好多歌用以前的脚本都404了,于是简单修改了下。
  4. // @version 20170617
  5. // @author 糖果君
  6. // @include http*://music.163.com/*
  7. // @grant unsafeWindow
  8. // @grant GM_xmlhttpRequest
  9. // @require https://gf.qytechs.cn/scripts/26727-网易云音乐歌曲封面下载/code/网易云音乐歌曲封面下载.user.js
  10. // @namespace
  11. // ==/UserScript==
  12. //参考 https://gf.qytechs.cn/zh-CN/scripts/10548-网易云音乐下载
  13. //以及更早的 https://gf.qytechs.cn/zh-CN/scripts/1099-netease-music-download
  14. var api = {
  15. //参考 https://gf.qytechs.cn/zh-CN/scripts/10582-网易云音乐高音质支持
  16. getTrackURL: function(dfsId) {
  17. var byte1 = '3go8&$8*3*3h0k(2)2';
  18. var byte2 = dfsId + '';
  19. var byte3 = [];
  20. for (var i = 0; i < byte2.length; i++) {
  21. byte3[i] = byte2.charCodeAt(i) ^ byte1.charCodeAt(i % byte1.length);
  22. }
  23. byte3 = byte3.map(function(i) {
  24. return String.fromCharCode(i);
  25. }).join('');
  26. var results = unsafeWindow.CryptoJS.MD5(byte3).toString(unsafeWindow.CryptoJS.enc.Base64).replace(/\//g, '_').replace(/\+/g, '-');
  27. var url = 'http://p2.music.126.net/' + results + '/' + byte2 + '.jpg';
  28. return url;
  29. },
  30. encrypt_request: function(callback, url, data) {
  31. // 这个好像不重要。var token = unsafeWindow.document.cookie.split('__csrf') [1].split(';') [0].substring(1);
  32. var token = '';
  33. data.csrf_token = token;
  34. var req = new XMLHttpRequest();
  35. req.open('POST', url + token, true);
  36. req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
  37. req.onload = function() {
  38. callback(JSON.parse(this.responseText));
  39. };
  40. //参考 https://github.com/darknessomi/musicbox/wiki/网易云音乐新版WebAPI分析。
  41. var pubKey = '010001';
  42. var modulus = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7';
  43. var nonce = '0CoJUm6Qyw8W8jud';
  44. var result = unsafeWindow.asrsea(JSON.stringify(data), pubKey, modulus, nonce);
  45. req.send('params=' + encodeURIComponent(result.encText) + '&encSecKey=' + encodeURIComponent(result.encSecKey));
  46. },
  47. detail: function(songId, callback) {
  48. var url = '/weapi/v3/song/detail?csrf_token=';
  49. var data = {
  50. c:
  51. JSON.stringify([{
  52. id: songId
  53. }
  54. ])
  55. };
  56. this.encrypt_request(callback, url, data);
  57. },
  58. lrc: function(songId, callback) {
  59. var url = '/weapi/song/lyric?csrf_token=';
  60. var data = {
  61. id: songId,
  62. lv: -1,
  63. tv: -1
  64. };
  65. this.encrypt_request(callback, url, data);
  66. },
  67. newsong: function(songId, callback) {
  68. var url = '/weapi/song/enhance/player/url?csrf_token=';
  69. var data = {
  70. ids: [songId],
  71. br: 999000,
  72. };
  73. this.encrypt_request(callback, url, data);
  74. },
  75. mv: function(mvId, callback) {
  76. var url = '/weapi/mv/detail/';
  77. var data = {
  78. id: mvId,
  79. };
  80. this.encrypt_request(callback, url, data);
  81. },
  82. search: function(songid, callback) {
  83. var url = '/weapi/search/pc';
  84. var data = {
  85. s: songid,
  86. limit: 1,
  87. type: 1,
  88. offset: 0,
  89. };
  90. this.encrypt_request(callback, url, data);
  91. },
  92. sign: function (type, callback) {
  93. var url = '/weapi/point/dailyTask';
  94. var data = {
  95. type: type
  96. };
  97. this.encrypt_request(callback, url, data);
  98. },
  99. xiamisearch: function (key, callback) {
  100. GM_xmlhttpRequest({
  101. method: 'GET',
  102. url: 'http://musicafe.co:8080/api/search/song/xiami?&limit=1&page=1&key=' + key,
  103. // onload: function (response) {
  104. // callback(JSON.parse(this.responseText));
  105. // }
  106. onreadystatechange: function (res) {
  107. if (res.readyState == 4 && res.status == 200) {
  108. callback(JSON.parse(res.responseText));
  109. }
  110. }
  111. });
  112. },
  113. };
  114. var innerFrame = document.querySelector('iframe');
  115. var pages = [
  116. {
  117. url: 'music.163.com/#/song?id=',
  118. handler: function() {
  119. var songId = location.href.match(/id=([0-9]+)/)[1];
  120. var downloadLine = this.createDownloadLine(songId);
  121. var innerFrameDoc = innerFrame.contentWindow.document;
  122. var albumNode = innerFrameDoc.querySelectorAll('p.des.s-fc4')[1];
  123. var parentNode = albumNode.parentNode;
  124. parentNode.insertBefore(downloadLine, albumNode.nextElementSibling);
  125.  
  126. },
  127. createDownloadLine: function(songId) {
  128. var disableStyle = function(link) {
  129. link.text += '(无)';
  130. link.style.color = 'gray';
  131. link.style.textDecoration = 'none';
  132. link.style.cursor = 'auto';
  133. };
  134. var setUrlAndSize = function(mp3Link, Music) {
  135. if (Music) {
  136. var href = Music.url;
  137. if (href) {
  138. mp3Link.href = href;
  139. mp3Link.text += (Music.size / 1024 / 1024).toFixed(1) + 'M';
  140. return;
  141. }
  142. else {
  143. api.search(songId,
  144. function(result) {
  145. var song = result.result.songs[0];
  146. var music = song.hMusic || song.mMusic || song.lMusic || song.bMusic;
  147. var mp3url;
  148. var dfsId=music.dfsId_str||music.dfsId;
  149. if (music && dfsId != 0) {
  150. mp3url = api.getTrackURL(dfsId) + '.mp3';
  151. } else if(!song.mp3Url.endsWith("==/0.mp3")) {
  152. mp3url = song.mp3Url;
  153. }
  154. if (mp3url) {
  155. mp3Link.href = mp3url;
  156. mp3Link.text += (music.size / 1024 / 1024).toFixed(1) + 'M';
  157.  
  158. } else {
  159. api.xiamisearch(document.title.replace(/- 网易云音乐/, ''), function (result) {
  160. mp3url = result.songList[0].file;
  161. if (mp3url) {
  162. mp3Link.href = mp3url;
  163. mp3Link.text += '(虾米)';
  164. } else {
  165. disableStyle(mp3Link);
  166. }
  167. });
  168. }
  169. });
  170. }
  171. }
  172. };
  173. var setLyric = function(LycLink, result) {
  174. var LrC = '';
  175. var lrc = result.lrc;
  176. var tlrc = result.tlyric;
  177. var num = 0;
  178. if (lrc && lrc.lyric) {
  179. LrC += lrc.lyric + '\n';
  180. num+=1;}
  181. if (tlrc && tlrc.lyric) {
  182. LrC += tlrc.lyric;
  183. num+=2;}
  184.  
  185.  
  186. if (num != 0) {
  187. var html = '';
  188. switch (num) {
  189. case 1:html="(原)";break;
  190. case 2:html="(译)";break;
  191. case 3:html="(合)";break;
  192. }
  193. LycLink.href = 'data:text/plain;charset=utf-8,' + encodeURIComponent(LrC);
  194. LycLink.innerHTML += html;
  195. } else {
  196. disableStyle(LycLink);
  197. }
  198. };
  199.  
  200. var newMp3Link = this.createLink('歌曲');
  201. var lyricLink = this.createLink('歌词');
  202. var mvLink = this.createLink('mv');
  203. var picLink = this.createLink('封面');
  204. api.detail(songId, function (result) {
  205. var song = result.songs[0];
  206. if (song.mv) {
  207. api.mv(song.mv, function (result) {
  208. var mv = result.data.brs;
  209. mvLink.href = mv[720] || mv[480] || mv[240];
  210. });
  211. }
  212. else {
  213. disableStyle(mvLink);
  214. };
  215.  
  216. if (song.al.pic_str || song.al.pic) {
  217. var img = innerFrame.contentWindow.document.querySelector(".j-img");
  218. picLink.href = img.dataset["src"] = api.getTrackURL(song.al.pic_str || song.al.pic);
  219. img.src = img.dataset["src"] + "?param=130y130";
  220. } else {
  221. disableStyle(picLink);
  222. };
  223.  
  224. });
  225. api.newsong(songId, function (result) {
  226. var song = result.data[0];
  227. setUrlAndSize(newMp3Link, song);
  228. });
  229. api.lrc(songId, function (result) {
  230. setLyric(lyricLink, result);
  231. });
  232. if (document.cookie.indexOf('appsign=true')==-1) {
  233. api.sign(0, function (result) {
  234. if (result.code == - 2 || result.code == 200) {
  235. console.log(result);
  236. var cookieime = new Date();
  237. cookieime.setTime(24 * 60 * 60 * 1000 + new Date(new Date() .toDateString()) .getTime() - 1);
  238. document.cookie = 'appsign=true;' + ';expires=' + cookieime.toGMTString();
  239. }
  240. });
  241. };
  242. if (document.cookie.indexOf('websign=true')==-1) {
  243. api.sign(1, function (result) {
  244. if (result.code == - 2 || result.code == 200) {
  245. console.log(result);
  246. var cookieime = new Date();
  247. cookieime.setTime(24 * 60 * 60 * 1000 + new Date(new Date() .toDateString()) .getTime() - 1);
  248. document.cookie = 'websign=true;' + ';expires=' + cookieime.toGMTString();
  249. }
  250. });
  251. };
  252. var container = this.createLineContainer('下载');
  253. container.appendChild(newMp3Link);
  254. container.appendChild(lyricLink);
  255. container.appendChild(mvLink);
  256. container.appendChild(picLink);
  257.  
  258. return container;
  259. },
  260. createLink: function(label) {
  261. var link = document.createElement('a');
  262. link.innerHTML = label;
  263. link.className = 's-fc7';
  264. link.style.marginRight = '10px';
  265. link.href = 'javascript:void(0);';
  266. link.target = '_blank';
  267. return link;
  268. },
  269. createLineContainer: function(label) {
  270. var container = document.createElement('p');
  271. container.className = 'desc s-fc4';
  272. container.innerHTML = label + ':';
  273. container.style.margin = '10px 0';
  274. return container;
  275. },
  276. },
  277. ];
  278. if (innerFrame) {
  279. innerFrame.addEventListener('load', function () {
  280. var i, page;
  281. for (i = 0; i < pages.length; i += 1) {
  282. page = pages[i];
  283. if (location.href.indexOf(page.url) != -1) {
  284. page.handler();
  285. }
  286. }
  287. });
  288. }
  289. document.cookie = 'os=linux';

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址