// ==UserScript== // @name 网易云音乐直接下载 // @namespace https://www.ocrosoft.com/ // @description 在单曲页面显示歌词、翻译、封面、歌曲下载链接并以高音质试听,同时支持歌单、专辑等页面直接下载单曲。该脚本受 GPL V2.0 许可证保护。脚本还在测试中,有不支持的页面麻烦反馈下。 // @match *://music.163.com/* // @grant GM_xmlhttpRequest // @version 1.8 // @downloadURL none // ==/UserScript== /** * 修改自 https://greasyfork.org/zh-CN/scripts/10548-%E7%BD%91%E6%98%93%E4%BA%91%E9%9F%B3%E4%B9%90%E4%B8%8B%E8%BD%BD * API 源码: https://github.com/Ocrosoft/NetEase_OutChain * 此脚本开源,API开源,但请不要在未经允许的情况下在其他程序中调用此脚本中的API,在非程序调用且小流量的个人使用场景下可以使用。 **/ /** * */ (function(root) { 'use strict'; /* * @opentdoor 的跨域下载接口 */ function Downloader() { // request function FileRequest(url, progress, callback) { var req = GM_xmlhttpRequest({ method: 'GET', url: url, onprogress: function(res) { if (progress) progress(res); }, overrideMimeType: "text/plain;charset=x-user-defined", onreadystatechange: function(res) { if (res.readyState == 4) { if (res.status == 200) { var str = res.response; var ta1 = []; for (var i = 0; i < str.length; i++) { ta1[i] = str.charCodeAt(i) & 0x00ff; } var ua8 = new Uint8Array(ta1); var blob = new Blob([ua8]); callback(blob, res.status); } else { callback(null, res.status); } } } }); }; //save file function SaveFile(blob, filename) { if (root.navigator.msSaveBlob) { root.navigator.msSaveBlob(blob, filename); } else { var anchor = root.document.createElement('a'); var url = root.URL.createObjectURL(blob); anchor.download = filename; anchor.href = url; var evt = root.document.createEvent("MouseEvents"); evt.initEvent("click", true, true); anchor.dispatchEvent(evt); root.URL.revokeObjectURL(url); } } //interface function FileDownload(url, filename, downloading, success, error) { FileRequest(url, downloading, function(blob, status) { if (status == 200) { SaveFile(blob, filename); if (typeof success == 'function') success(); } else { if (typeof error == 'function') error(status); } }); } this.FileDownload = FileDownload; var anthorEvents = { onprogress: function(res) { if ($(this.anchor).attr('data-res-action') == 'downloadDirect') { if (res.lengthComputable) { $(this.anchor).children('i')[0].text(`下载:${(res.loaded*100 / res.total).toFixed(2)}%`); } else { $(this.anchor).children('i').text("下载:" + anthorEvents.calcLength(res.loaded)); } } else { if (res.lengthComputable) { this.anchor.innerHTML = `下载:${(res.loaded*100 / res.total).toFixed(2)}%`; } else { this.anchor.innerHTML = "下载:" + anthorEvents.calcLength(res.loaded); } } }, calcLength: function(b) { b = Number(b) / 1024; if (b < 1024) { return b.toFixed(1) + "KB"; } b = b / 1024; if (b < 1024) { return b.toFixed(2) + "MB"; } b = b / 1024; return b.toFixed(3) + "GB"; }, onsuccess: function() { this.anchor.innerHTML = this.Html; this.doing = false; if (this.anchor.id == 'tmp') { $(this.anchor).prev().remove(); $(this.anchor).remove(); } }, onerror: function() { this.anchor.innerHTML = "下载失败"; this.handler = setTimeout(function(t) { t.anchor.innerHTML = t.Html; t.doing = false; }, 2000, this); }, onAnthorClick: function(e) { e = e || event; var a = this.anchor; var ex = /([\w\s]+)(\.\w)(\?.*)?$/i.exec(a.href || ""); var name = a.download || a.title; if (ex) { if (!name && ex.length > 1) name = ex[1]; if (name && name.indexOf('.') == -1 && ex.length > 2) name += ex[2]; } if (!name || !a.href) return; e.preventDefault(); if (this.doing) return; this.doing = true; FileDownload(a.href, name, anthorEvents.onprogress.bind(this), anthorEvents.onsuccess.bind(this), anthorEvents.onerror.bind(this)); } }; //interface function BindAnthor(a) { var env = { Html: a.innerHTML, anchor: a }; a.addEventListener('click', anthorEvents.onAnthorClick.bind(env), true); } this.BindAnthor = BindAnthor; } var downloader = new Downloader(); try { var jqs = document.createElement('script'); jqs.src = 'http://code.jquery.com/jquery-2.1.4.min.js'; document.body.insertBefore(jqs, document.body.firstChild); } catch(e) { // } var api = { detailUrl: function(songIds) { var tpl = (location.href.indexOf('https') == -1 ? 'http://music.ocrosoft.com/GetMusicLink.php?id=${songIds}': 'https://www.ocrosoft.com/outchain/GetMusicLink.php?id=${songIds}'); return tpl.replace('${songIds}', songIds.join(',')); }, detail: function(songIds, callback) { $.ajax({ type: "get", url: this.detailUrl(songIds), dataType: "jsonp", success: function(json) { callback(json); } }); }, mediaUrl: function(songId) { return (location.href.indexOf('https') == -1 ? 'http': 'https') + '://music.163.com/api/song/lyric?os=pc&id=' + songId + '&lv=-1&kv=-1&tv=-1'; //503207093 }, media: function(songId, callback) { var req = new XMLHttpRequest(); req.open('GET', this.mediaUrl(songId), true); req.onload = function() { callback(JSON.parse(this.responseText)); }; req.send(); }, }; var innerFrame = document.querySelector('iframe'); var tit, cov, dl; var fileName; var pages = [{ url: 'http://music.163.com/#/song?id=', handler: function() { var innerFrameDoc = innerFrame.contentWindow.document; var albumNode = innerFrameDoc.querySelectorAll('p.des.s-fc4')[1]; tit = $(innerFrameDoc).find('.tit'); cov = $(innerFrameDoc).find('.u-cover').children('img'); dl = $(innerFrameDoc).find('.u-btni-dl'); fileName = $(tit).children('.f-ff2')[0].innerText + ' - ' + tit.parent().next().find('.s-fc7')[0].innerText + '.'; var parentNode = albumNode.parentNode; var songId = location.href.match(/id=([0-9]+)/)[1]; var downloadLine = this.createDownloadLine(songId); parentNode.insertBefore(downloadLine, albumNode.nextElementSibling); }, createDownloadLine: function(songId) { var disableStyle = function(link) { link.text += '(无)'; link.style.color = 'gray'; link.style.textDecoration = 'none'; link.style.cursor = 'auto'; }; var mp3Link = this.createMP3Link(); var lyricLink = this.createLink('歌词'); var tlyricLink = this.createLink('翻译'); var coverLink = this.createLink('封面'); var mp3Help = this.createLink('如何下载歌曲?'); var showPlayer = this.createLink('高音质试听'); $(mp3Help).attr({ 'href': 'javascript:;' }).click(function() { alert("点击下方的下载按钮之后等待即可。"); }); $(showPlayer).attr({ 'href': 'javascript:;' }).click(function() { $(innerFrame.contentWindow.document).find('#wyyyydda').attr('controls', 'true')[0].play(); }); $(lyricLink).attr('download', fileName + 'lrc'); $(tlyricLink).attr('download', fileName + 'lrc'); $(coverLink).attr('download', fileName + 'jpg').attr('href', cov.attr('data-src')); downloader.BindAnthor(coverLink); downloader.BindAnthor(dl[0]); $(dl).attr({ 'href': 'javascript:;', 'data-res-action': 'downloadDirect' }).children('i').text('下载(稍候)'); api.detail([songId], function(result) { mp3Link.src = result.mp3Url; }); api.media(songId, function(result) { if (result.lrc.lyric) { lyricLink.href = 'data:text/plain;charset=utf-8,' + encodeURIComponent(result.lrc.lyric); } else { disableStyle(lyricLink); } if (result.tlyric.lyric) { tlyricLink.href = 'data:text/plain;charset=utf-8,' + encodeURIComponent(result.tlyric.lyric); } else { disableStyle(tlyricLink); } }); var container = this.createLineContainer('下载'); container.appendChild(lyricLink); // 原文lrc container.appendChild(tlyricLink); // 翻译lrc container.appendChild(coverLink); // 封面 container.appendChild(mp3Help); // 帮助 container.appendChild(showPlayer); // 试听 container.appendChild(document.createElement('br')); container.appendChild(mp3Link); // audio标签 return container; }, createLink: function(label) { var link = document.createElement('a'); link.innerHTML = label; link.className = 's-fc7'; link.style.marginRight = '10px'; link.href = 'javascript:;'; return link; }, createMP3Link: function() { var link = document.createElement('audio'); $(link).attr('id', 'wyyyydda').css('margin-top', '10px'); $(link).bind('canplay', function() { $(dl).attr('href', this.src).attr('download', fileName + 'mp3').children('i').text('下载'); }).bind('error', function() { $(dl).attr('href', 'javascript:alert("无法加载歌曲,请前往反馈。");').children('i').text('下载(错误)'); }); return link; }, createLineContainer: function(label) { var container = document.createElement('p'); container.className = 'desc s-fc4'; container.innerHTML = label + ':'; container.style.margin = '10px 0'; return container; }, }, { url: ['http://music.163.com/#/playlist?id=', // 歌单 'http://music.163.com/#/artist?id=', // 歌手 'http://music.163.com/#/discover/toplist', // 榜单 'http://music.163.com/#/album?id=', // 专辑 'http://music.163.com/#/discover/recommend/taste' // 每日推荐 ], handler: function() { var innerFrameDoc = innerFrame.contentWindow.document; var downloadButtons = $(innerFrameDoc).find('span.icn-dl'); this.replaceAction(innerFrameDoc, downloadButtons); }, replaceAction: function(innerFrameDoc, downloadButtons) { for (var i = 0; i < downloadButtons.length; i++) { if ($(downloadButtons[i]).attr('data-res-action') == 'download') { $(downloadButtons[i]).attr('data-res-action', 'downloadDirect'); $(downloadButtons[i]).click(function() { var id = $(this).attr('data-res-id'); var ele = this; var nameAndAuthor = $(this).prev().attr('data-res-name') + ' - ' + $(this).prev().attr('data-res-author'); api.detail([id], function(res) { var audio = document.createElement('audio'); $(audio).attr({ 'src': res.mp3Url, 'id': 'wyyyydda' }); $(audio).bind('canplay', function() { var a = document.createElement('a'); $(a).attr({ 'href': this.src, 'download': nameAndAuthor + '.mp3', 'id': 'tmp' }); downloader.BindAnthor(a); ele.parentNode.appendChild(document.createElement('br')); ele.parentNode.appendChild(a); a.click(); }); $(audio).bind('error', function() { alert('无法加载歌曲,请前往反馈。'); }); }); }); } } } }, ]; function matchPagesURL(href, urls) { var ret = false; var t = location.href.split('://')[1]; if (Array.isArray(urls)) { urls.forEach(function(ele) { if (t.indexOf(ele.split('://')[1]) === 0) { ret = true; return; } }); } else { if (t.indexOf(urls.split('://')[1]) === 0) { ret = true; } } return ret; } if (innerFrame) { innerFrame.addEventListener('load', function() { var i, page; for (i = 0; i < pages.length; i += 1) { page = pages[i]; if (matchPagesURL(location.href, page.url)) { page.handler(); /*setTimeout(function() { var covp = $(innerFrame.contentWindow.document).find('.covdl').parent(); var covs = covp.children('.des'); if (covs.length != 2) return; $(covs[1]).css('margin-right', '10px'); $(covs[1]).addClass('covdl'); covp[0].replaceChild(covs[1], covs[0]); }, 55); setTimeout(function() { var covp = $(innerFrame.contentWindow.document).find('.covdl').parent(); var covs = covp.children('.des'); $(covs[1]).remove(); }, 2222);*/ } } }); } })(window);