在单曲页面显示歌词、翻译、封面、MV、歌曲下载链接并以高音质试听。同时支持歌单、专辑等页面直接下载单曲、封面、歌词(压缩包)。如遇到错误,请阅读附加信息后进行反馈。
// ==UserScript== // @name 网易云音乐直接下载 // @namespace https://www.ocrosoft.com/ // @description 在单曲页面显示歌词、翻译、封面、MV、歌曲下载链接并以高音质试听。同时支持歌单、专辑等页面直接下载单曲、封面、歌词(压缩包)。如遇到错误,请阅读附加信息后进行反馈。 // @match *://music.163.com/* // @grant GM.xmlHttpRequest // @grant GM_xmlhttpRequest // @version 4.1.6 // @author ocrosoft // @connect 126.net // @connect 163.com // @connect 172.* // @license GPLV2 // @require https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/crypto-js/3.1.9/core.min.js // @require https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/crypto-js/3.1.9/crypto-js.min.js // @require https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/crypto-js/3.1.9/aes.min.js // @require https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/crypto-js/3.1.9/enc-utf8.min.js // @require https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/crypto-js/3.1.9/enc-base64.min.js // @require https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/jszip/3.1.5/jszip.min.js // @require https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/FileSaver.js/1.3.8/FileSaver.min.js // ==/UserScript== var GM__xmlHttpRequest; if("undefined" != typeof(GM_xmlhttpRequest)){ GM__xmlHttpRequest = GM_xmlhttpRequest; } else { GM__xmlHttpRequest = GM.xmlHttpRequest; } let COOKIE = { set: function(name, value, will_expire_ms) { let expire = new Date(); if (will_expire_ms) { expire.setTime(expire.getTime() + will_expire_ms); } else { expire.setTime(expire.getTime() + 180 * 24 * 60 * 60 * 1000); } document.cookie = name + "=" + JSON.stringify(value) + ";expires=" + expire.toGMTString() + ';path=\/'; }, get: function(name) { let arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)"); if (arr = document.cookie.match(reg)) { return unescape(arr[2]); } return null; }, }; /* * 请求播放地址时的比特率,具体含义如下 * 999000: 请求无损flac格式 * 320000: 320K * 192000: 192K * 128000: 128K * 没有对应格式时下发低一级格式 */ let BITRATE = { FLAC: 999000, B320: 320000, B192: 192000, B128: 128000, }; let g_bitrate = BITRATE.B320; function setBitrate(bitrate) { g_bitrate = bitrate; COOKIE.set('bitrate', g_bitrate); } if (COOKIE.get('bitrate')) { g_bitrate = parseInt(COOKIE.get('bitrate')); COOKIE.set('bitrate', g_bitrate); } let NAMERULE = { TITLE_ARTIST: 0, ARTIST_TITLE: 1, }; let g_nameRule = NAMERULE.ARTIST_TITLE; function setNameRule(rule) { g_nameRule = rule; COOKIE.set('namerule', g_nameRule); } if (COOKIE.get('namerule')) { g_nameRule = parseInt(COOKIE.get('namerule')); COOKIE.set('namerule', g_nameRule); } // 参考 https://github.com/darknessomi/musicbox/blob/master/NEMbox/api.py function _WEAPI() { function _REQUEST() { let _base_url = 'https://music.163.com'; let _send_request = function(url, method, headers, data) { return new Promise(function(resolve, reject) { GM__xmlHttpRequest({ method: method, url: url, headers: headers, data: data, onreadystatechange: function(res) { if (res.readyState == 4) { if (res.status == 200) { resolve(res.response); return; } reject(res.status); } } }); }); }; let _headers = { 'Accept':'*/*', 'Accept-Encoding':'gzip,deflate,sdch', 'Accept-Language':'zh-CN,zh;q=0.8,gl;q=0.6,zh-TW;q=0.4', 'Connection':'keep-alive', 'Content-Type':'application/x-www-form-urlencoded', 'Host':'music.163.com', 'Origin':'http://music.163.com', 'Referer':'http://music.163.com/', 'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36', //'Cookie': document.cookie + ';os=osx' 'Cookie': 'os=osx' }; this.sendRequest = function(path, data) { return _send_request(_base_url + path, 'POST', _headers, data); }; this.sendRequestWrapped = function(path, data, response_process) { let sendRequest = this.sendRequest; return new Promise(function(resolve) { sendRequest(path, data) .then(function(response) { let data = JSON.parse(response); if (response_process) { data = response_process(data); } resolve(data); }) .catch(function(status) { resolve([]); }); }); }; this.sendRequestWithMethod = function(path, method, data) { return _send_request(_base_url + path, method, _headers, data); } } function _ENCRYPT() { let _MODULUS = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7' + 'b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280' + '104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932' + '575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b' + '3ece0462db0a22b8e7'; let _NONCE = '0CoJUm6Qyw8W8jud'; let _PUBKEY = '010001'; let _create_key = function() { return (Math.random().toString(16).substring(2) + Math.random().toString(16).substring(2)).substring(0,16); }; let _rsaEncrypt = function(text, pubKey, modulus) { setMaxDigits(256); var keys = new RSAKeyPair(pubKey, '', modulus); var encText = encryptedString(keys, text); return encText; } let _aesEncrypt = function (text, secKey){ secKey = CryptoJS.enc.Utf8.parse(secKey); text = CryptoJS.enc.Utf8.parse(text); var encrypted = CryptoJS.AES.encrypt(text, secKey, { iv: CryptoJS.enc.Utf8.parse('0102030405060708'), mode: CryptoJS.mode.CBC }); encrypted = encrypted.toString(); return encrypted; } this.encryptedId = function(id) { throw('not impl!'); }; this.encryptedRequest = function(map) { let text = JSON.stringify(map); let secret = _create_key(); let params = _aesEncrypt(_aesEncrypt(text, _NONCE), secret); let encseckey = _rsaEncrypt(secret, _PUBKEY, _MODULUS); return 'params=' + encodeURIComponent(params) + '&encSecKey=' + encodeURIComponent(encseckey); }; }; let REQUEST = new _REQUEST(); let ENCREYPT = new _ENCRYPT(); let QENC = function(map) { return ENCREYPT.encryptedRequest(map); } let QREQ = function(path, data, response_process) { return REQUEST.sendRequestWrapped(path, data, response_process); } this.songsDetail = function(ids) { let path = '/weapi/v3/song/detail'; let c = []; for (let i = 0; i < ids.length; ++i) { c.push({'id': ids[i]}); } let map = { 'ids': ids, 'c': JSON.stringify(c) } let data = QENC(map); return QREQ(path, data, function(data) { try { return data.songs; } catch (e) { return []; } }); } this.songsUrl = function(ids) { let path = '/weapi/song/enhance/player/url'; let data = QENC({'ids': ids, 'br': g_bitrate}); return QREQ(path, data, function(data) { try { return data.data; } catch (e) { return []; } }); }; this.songLyric = function(music_id) { let path = '/weapi/song/lyric'; let data = QENC({'os': 'osx', 'id': music_id, 'lv': '-1', 'kv': '-1', 'tv': '-1'}); return QREQ(path, data); } this.mvUrl = function(mv_id) { return new Promise(function(resolve, reject) { let path = '/api/mv/detail?id=' + mv_id + '&type=mp4'; REQUEST.sendRequestWithMethod(path, 'GET', null).then(function(data) { try { data = JSON.parse(data).data; resolve(data); } catch (e) { resolve(null); } }).catch (function (status) { resolve(null); }); }); }; this.playlistDetail = function(playlist_id) { let path = '/weapi/v3/playlist/detail'; let data = QENC({'id': playlist_id, 'total': 'true', 'limit': 1000, 'n': 1000, 'offest': 0}); return QREQ(path, data, function(data) { try { return data.playlist; } catch (e) { return null; } }); }; this.album = function(album_id) { let path = '/weapi/v1/album/' + album_id; return QREQ(path, QENC({}), function(data) { try { return { 'album': data.album, 'songs': data.songs }; } catch (e) { return null; } }); }; this.login = function(username, password) { throw('not impl!'); return new Promise(function(resolve, reject) { let path = ''; let data = ''; if (username.match(/^[0-9]+$/)) { path = '/weapi/login/cellphone'; data = encrypted_request({'phone': username, 'password': password, 'rememberLogin': 'true'}); } else { path = '/weapi/login'; let client_token = '1_jVUMqWEPke0/1/Vu56xCmJpo5vP1grjn_SOVVDzOc78w8OKLVZ2JH7IfkjSXqgfmh'; data = encrypted_request({'phone': username, 'password': password, 'rememberLogin': 'true', 'clientToken': client_token}); } WEAPI._send_request(path, data) .then(function(response) { resolve(true); }) .catch(function(status) { resolve(false); }); }); }; this.test = function() { function funcLog(data) { console.log(data); } this.songsUrl([1333340512, 1308363066]).then(funcLog); this.playlistDetail(4945521505).then(funcLog); this.playlistDetail(2659719519).then(funcLog); this.songLyric(1333340512).then(funcLog); this.songsDetail([1341532699]).then(funcLog); this.mvUrl(10847631).then(funcLog); this.album(75292754).then(funcLog); } } let WEAPI = new _WEAPI(); //WEAPI.test(); (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) & 255; } 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; this.FileRequest = FileRequest; var anthorEvents = { onprogress: function (res) { if (this.anchor.getAttribute('data-res-action') == 'downloadDirect') { if (res.lengthComputable) { this.anchor.querySelector('i').innerText = '下载:' + (res.loaded * 100 / res.total).toFixed(2) + '%'; } else { this.anchor.querySelector('i').innerText = '下载:' + anthorEvents.calcLength(res.loaded); } } else { if (res.lengthComputable) { this.anchor.innerText = '下载:' + (res.loaded * 100 / res.total).toFixed(2) + '%'; } else { this.anchor.innerText = '下载:' + anthorEvents.calcLength(res.loaded); } } }, calcLength: function (b) { b = Number(b) / ####; if (b < ####) { return b.toFixed(1) + 'KB'; } b = b / ####; if (b < ####) { return b.toFixed(2) + 'MB'; } b = b / ####; return b.toFixed(3) + 'GB'; }, onsuccess: function () { this.anchor.innerHTML = this.Html; this.doing = false; if (this.anchor.id == 'tmp') { this.anchor.previousElementSibling.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(); var innerFrame = document.querySelector('iframe'); var tit, // 标题 cov, // 封面 dl, // 下载按钮 fileName, // 文件名 mvId = '', // mvID allDownloadButton, // 歌单/专辑页的下载按钮 downloadPics; // 歌单/专辑页的歌曲封面下载按钮 // api这个东西的调用方先不改,有空再说。内部实现替换成WEAPI。 var api = { detail: function(songIds, callback) { WEAPI.songsUrl(songIds).then(function(data) { if (data) { let br = data[0].br; let url = data[0].url; innerFrame.contentWindow.document.querySelector('#wyyyydda').setAttribute('data-br', br); innerFrame.contentWindow.document.querySelector('#wyyyydda').src = url; } }); }, media: function (songId, callback, index) { WEAPI.songLyric(songId).then(function(data) { if (data) { callback(data, index); } }); }, mv: function (mvId, callback) { WEAPI.mvUrl(mvId).then(function(data) { var brs = [240, 480, 720, 1080]; for (var i = brs.length - 1; i >= 0; --i) { if (data.brs[brs[i]]) { callback(data.brs[brs[i]], brs[i]); break; } } }); }, }; 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.querySelector('.tit'); cov = innerFrameDoc.querySelector('.u-cover > img'); dl = innerFrameDoc.querySelector('.u-btni-dl'); let sfc = tit.parentNode.nextElementSibling.querySelectorAll('.s-fc7'); let author = ''; for (let i = 0; i < sfc.length; ++i) { if (author != '') { author += ','; } author += sfc[i].innerText; } if (g_nameRule == NAMERULE.ARTIST_TITLE) { fileName = author + ' - ' + tit.querySelector('.f-ff2').innerText + '.'; } else { fileName = tit.querySelector('.f-ff2').innerText + ' - ' + author + '.'; } var parentNode = albumNode.parentNode; var songId = location.href.match(/id=([0-9]+)/) [1]; var mvHref = innerFrameDoc.querySelector('a[title="播放mv"]'); if(mvHref) { mvId = mvHref.href.split('=')[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('歌曲试听'); let switchDownloadBitrate = this.createLink(g_bitrate > 320000 ? '切换到MP3下载模式' : '切换到无损下载模式(需黑胶VIP)'); let switchNameRule = this.createLink(g_nameRule == NAMERULE.ARTIST_TITLE ? '命名风格:艺术家-歌曲名' : '命名风格:歌曲名-艺术家'); mp3Help.addEventListener('click', function () { alert('点击下方的下载按钮之后等待即可。'); }); showPlayer.addEventListener('click', function () { var player = innerFrame.contentWindow.document.querySelector('#wyyyydda'); player.setAttribute('controls', 'true'); player.play(); }); showPlayer.id = 'wyyyysp'; switchDownloadBitrate.addEventListener('click', function() { if (g_bitrate > 320000) { setBitrate(BITRATE.B320); } else { setBitrate(BITRATE.FLAC); alert('请注意,无损下载文件为.flac格式,部分歌曲没有无损格式,且非黑胶VIP无法下载无损。'); } location.reload(); }); switchNameRule.addEventListener('click', (ev) => { if (g_nameRule == NAMERULE.ARTIST_TITLE) { g_nameRule = NAMERULE.TITLE_ARTIST; ev.srcElement.text = '命名风格:歌曲名-艺术家'; } else { g_nameRule = NAMERULE.ARTIST_TITLE; ev.srcElement.text = '命名风格:艺术家-歌曲名'; } setNameRule(g_nameRule); location.reload(); }); lyricLink.setAttribute('download', fileName + 'lrc'); tlyricLink.setAttribute('download', fileName + 'lrc'); coverLink.setAttribute('download', fileName + 'jpg'); coverLink.href = cov.getAttribute('data-src'); downloader.BindAnthor(coverLink); downloader.BindAnthor(dl); dl.href = 'javascript:;'; dl.setAttribute('data-res-action', 'downloadDirect'); dl.querySelector('i').innerText = '下载(稍候)'; api.detail([songId]); api.media(songId, function (r###lt) { if (r###lt.lrc && r###lt.lrc.lyric) { lyricLink.href = 'data:text/plain;charset=utf-8,' + encodeURIComponent(r###lt.lrc.lyric); } else { disableStyle(lyricLink); } if (r###lt.tlyric && r###lt.tlyric.lyric) { tlyricLink.href = 'data:text/plain;charset=utf-8,' + encodeURIComponent(r###lt.tlyric.lyric); } else { disableStyle(tlyricLink); } }); var container = this.createLineContainer('下载'); container.appendChild(lyricLink); // 原文lrc container.appendChild(tlyricLink); // 翻译lrc container.appendChild(coverLink); // 封面 if (mvId != '') { // MV下载,没有不显示 var el = this.createLink('MV'); el.setAttribute('download', fileName + 'mp4'); api.mv(mvId, function(r###lt, br) { el.innerHTML += '(' + br + 'P)'; el.href = r###lt; }); downloader.BindAnthor(el); container.appendChild(el); } container.appendChild(mp3Help); // 帮助 container.appendChild(showPlayer); // 试听 container.appendChild(document.createElement('br')); container.appendChild(switchDownloadBitrate); container.appendChild(document.createElement('br')); container.appendChild(mp3Link); // audio标签 container.appendChild(switchNameRule); 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.setAttribute('id', 'wyyyydda'); link.style.marginTop = '10px'; link.addEventListener('canplay', function () { dl.href = this.src; if (this.src.match('\.flac$')) { dl.setAttribute('download', fileName + 'flac'); } else { dl.setAttribute('download', fileName + 'mp3'); } let br_digit = parseInt(parseInt(innerFrame.contentWindow.document.querySelector('#wyyyydda').getAttribute('data-br')) / 1000); var br = '(' + br_digit + 'K)'; if (br_digit > 320) { br = '(无损)'; } dl.querySelector('i').innerText = '下载' + br; }); link.addEventListener('error', function () { //alert('无法加载此歌曲。可能此歌曲需要##或版权受限。'); dl.querySelector('i').innerText = '无法下载'; }); 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; allDownloadButton = innerFrameDoc.querySelector('.u-btni-dl'); var cover = innerFrameDoc.querySelector('.cover>img'); // 封面图片<img> var mask = innerFrameDoc.querySelector('.cover>span'); // 封面图片后一个元素,用来加<a></a> if (cover && (location.href.indexOf('#/playlist') != -1 || location.href.indexOf('#/album') != -1)) { var title = innerFrameDoc.querySelector('.tit>h2').innerText; // 专辑名称/歌单名称 var url = cover.src.split('?')[0]; // 封面的链接 mask.outerHTML = '<a download="' + title + '.jpg" href=" ' + url + '">' + mask.outerHTML + '</a>'; mask = innerFrameDoc.querySelector('.cover>a'); downloader.BindAnthor(mask); let _this = this; allDownloadButton.addEventListener('click', function(e) { if (e.shiftKey) { _this.downloadMusicZip(); } else { _this.downloadLyricsZip(); } }); allDownloadButton.setAttribute('data-res-action', 'downloadLyrics'); allDownloadButton.childNodes[0].innerText = '歌词下载'; if (location.href.indexOf('#/playlist') != -1) { downloadPics = allDownloadButton.cloneNode(true); downloadPics.addEventListener('click', this.downloadAlbumImageZip); downloadPics.setAttribute('data-res-action', 'downloadLyrics'); downloadPics.childNodes[0].innerText = '歌单中歌曲封面下载'; downloadPics.title = '点击左侧图片下载歌单封面'; allDownloadButton.parentNode.insertBefore(downloadPics, allDownloadButton.nextSibling); } } var audio = document.createElement('audio'); audio.setAttribute('id', 'wyyyydda'); audio.addEventListener('canplay', function () { var a = document.createElement('a'); a.setAttribute('href', this.src); if (this.src.match('\.flac$')) { a.setAttribute('download', this.getAttribute('data-fileName') + '.flac'); } else { a.setAttribute('download', this.getAttribute('data-fileName') + '.mp3'); } a.setAttribute('id', 'tmp'); downloader.BindAnthor(a); var _cele = innerFrameDoc.querySelector('[downloading]'); _cele.parentNode.appendChild(document.createElement('br')); _cele.parentNode.appendChild(a); _cele.removeAttribute('downloading'); a.click(); }); audio.addEventListener('error', function () { alert('无法加载此歌曲。可能此歌曲需要##或版权受限。'); }); innerFrameDoc.querySelector('body').appendChild(audio); // 网页版只能加载10首歌曲,处理一下让它显示全部(但是小于1000) let rep = this.replaceAction; this.showAllPlaylistItems(innerFrameDoc).then(function() { let downloadButtons = innerFrameDoc.querySelectorAll('span.icn-dl'); rep(innerFrameDoc, downloadButtons); // 使下载按钮不换行 if (location.href.indexOf('/#/artist?id=') != -1) { let table = innerFrameDoc.querySelector('.m-table-1'); if (table) { table.className = table.className.replace(/ ?m-table-1/, ''); } } }); }, showAllPlaylistItems: function(doc, song, index) { function dtToString(dt) { let h = parseInt(dt / 1000 / 60 / 60); let m = parseInt(dt / 1000 / 60 - h * 60); let s = parseInt(dt / 1000 - h * 60 * 60 - m * 60); let str = ''; if (h > 10) str += h + ':'; else if (h > 0) str += '0' + h + ':'; if (m > 10) str += m + ':'; else str += '0' + m + ':'; if (s > 10) str += s; else str += '0' + s; return str; } function fillTemplate(template, song, index) { let tp = template; template = template.cloneNode(true); template.innerHTML = template.innerHTML.replace(/ ?data-res-data="\d+"/, ''); let match = template.innerHTML.match(/data-res-id="(\d+)"/); if (match == null) { return; } let id = match[1]; template.innerHTML = template.innerHTML.replace(new RegExp(id, 'g'), song.id); template.querySelector('.num').innerText = index + 1; template.className = (index % 2 == 0) ? 'even' : ''; let b = template.querySelector('.txt>a>b'); b.title = b.innerText = song.name; template.querySelector('.u-dur').innerText = dtToString(song.dt); let texts = template.querySelectorAll('.text'); let ar_name = (song.ar && song.ar.length > 0) ? song.ar[0].name : ''; let ar_id = (song.ar && song.ar.length > 0) ? song.ar[0].id : '0'; texts[0].querySelector('span').title = ar_name; texts[0].querySelector('.text>span').title = ar_name; texts[0].querySelector('.text>span>a').innerText = ar_name; let a1 = texts[0].querySelector('.text>span>a'); a1.href = a1.href.replace(/\?id=\d+/, '?id=' + ar_id); template.querySelector('[data-res-action="share"]').setAttribute('data-res-name', song.name); template.querySelector('[data-res-action="share"]').setAttribute('data-res-author', ar_name); let a2 = texts[1].querySelector('a'); a2.href = a2.href.replace(/\?id=\d+/, '?id=' + song.al.id); a2.title = song.al.name; a2.innerText = song.al.name; return template; } return new Promise(function(resolve) { resolve(); return; /*let match = location.href.match(/#\/playlist\?id=(\d+)/); let playlist_id = ''; if (match) { playlist_id = match[1]; } let text = doc.querySelector('#playlist-track-count').innerText; let num = parseInt(text); if (num > 10 && playlist_id != '') { WEAPI.playlistDetail(playlist_id).then(function(data) { let tracks = data.tracks; let template = doc.querySelector('.m-table>tbody>tr'); let tbody = doc.querySelector('.m-table>tbody'); for (let i = 10; i < 25; ++i) { let tp = fillTemplate(template, tracks[i], i); tbody.append(tp); } doc.querySelector('.m-playlist-see-more>.text').innerText = '查看更多内容,请耐心等待脚本更新(龟速)'; resolve(); }); } else { resolve(); }*/ }); }, replaceAction: function (innerFrameDoc, downloadButtons) { innerFrame.contentWindow.document.querySelectorAll('.js-dis').forEach(function(ele){ ele.className = ele.className.replace('js-dis',''); ele.querySelectorAll('b[title]').forEach(function(b){ b.style.color='#aeaeae'; }); }); for (var i = 0; i < downloadButtons.length; i++) { if (downloadButtons[i].getAttribute('data-res-action') == 'download') { downloadButtons[i].setAttribute('data-res-action', 'downloadDirect'); downloadButtons[i].addEventListener('click', function () { var id = this.getAttribute('data-res-id'); let name = ''; if (g_nameRule == NAMERULE.ARTIST_TITLE) { name = this.previousElementSibling.getAttribute('data-res-author') + ' - ' + this.previousElementSibling.getAttribute('data-res-name'); } else { name = this.previousElementSibling.getAttribute('data-res-name') + ' - ' + this.previousElementSibling.getAttribute('data-res-author'); } innerFrame.contentWindow.document.querySelector('#wyyyydda').setAttribute('data-fileName', name); innerFrame.contentWindow.document.querySelector('#wyyyydda').setAttribute('data-res-id', id); this.setAttribute('downloading','true'); api.detail([id], null); }); } } }, downloadLyricsZip: function(){ function artistListToString(ar) { let str = ''; if (ar == null) { return str; } for (let i = 0; i < ar.length; ++i) { if (str != '') { str += ' & '; } str += ar[i].name; } str = str.trim(); return str; } if (location.href.indexOf('#/playlist') != -1 || location.href.indexOf('#/album') != -1) { let playListId = location.href.split('id=')[1]; let isPlayList = location.href.indexOf('#/playlist') != -1; function onComplete(r###lt) { let initialText = allDownloadButton.childNodes[0].innerText; let failedText = '歌词下载失败...'; try { if (!r###lt) { return; } var zip = new JSZip(); var tracks = isPlayList ? r###lt.tracks : r###lt.songs; let zipFileName = ''; if (isPlayList) { zipFileName = r###lt.creator.nickname + ' - ' + r###lt.name; } else { zipFileName = artistListToString(r###lt.album.artists); if (zipFileName != '') { zipFileName += ' - '; } zipFileName += r###lt.album.name; } zipFileName += ' - 歌词'; zipFileName = zipFileName.replace(/[\/:*?"<>|]*/g, '').trim(); if (isPlayList) { if (r###lt.description) { zip.file("歌单简介.txt", r###lt.description.replace(/\n/g, '\r\n')); } } else { if (r###lt.album.description) { zip.file("专辑简介.txt", r###lt.album.description.replace(/\n/g, '\r\n')); } } zip.file("说明.txt", "lyrics:.lrc格式的滚动歌词\r\nnlyrics:.txt格式的歌词\r\ntlyrics:.lrc格式的翻译后的滚动歌词\r\n\r\n记事本打开可能不换行,请尝试notepad++等软件\r\n\r\n由\"网易云音乐直接下载\"脚本下载。\r\n脚本链接:https://greasyfork.org/zh-CN/scripts/33046"); // 不要删除好不好(✺ω✺) if (isPlayList) { zip.file("歌单链接.url", "[{000214A0-0000-0000-C000-000000000046}]\nProp3=19,2\n[InternetShortcut]\nIDList=\nURL=http://music.163.com/#/playlist?id=" + playListId); } else { zip.file("专辑链接.url", "[{000214A0-0000-0000-C000-000000000046}]\nProp3=19,2\n[InternetShortcut]\nIDList=\nURL=http://music.163.com/#/album?id=" + playListId); } function downloadLyricAsync(index) { let fileName = ''; if (g_nameRule == NAMERULE.ARTIST_TITLE) { fileName = artistListToString(tracks[index].ar); if (fileName != '') { fileName += ' - '; } fileName += tracks[index].name; } else { fileName = tracks[index].name; let artists = artistListToString(tracks[index].ar); if (artists != '') { fileName += ' - '; fileName += artists; } } // 删除文件中不允许的字符 fileName = fileName.replace(/[\/:*?"<>|]*/g, '').trim(); allDownloadButton.childNodes[0].innerText = '正在下载:' + index + '/' + tracks.length; function onComplete(data) { if (data.lrc && data.lrc.lyric) { // 这句保留两位小数 zip.file('lyrics\\' + fileName + ".lrc", data.lrc.lyric.replace(/\[(\d\d.\d\d.\d\d)\d\]/g, '[$1]')); // 这句保留原来的格式(原来几位就几位) //zip.file('lyrics\\' + fileName + ".lrc", r###lt.lrc.lyric); zip.file('nlyrics\\' + fileName + ".txt", data.lrc.lyric.replace(/\[.*]/g, '')); // :: /\[\d\d:\d\d.\d{2,3}]/g } if (data.tlyric && data.tlyric.lyric) { zip.file('tlyrics\\' + fileName + ".lrc", data.tlyric.lyric.replace(/\[(\d\d.\d\d.\d\d)\d\]/g, '[$1]')); } allDownloadButton.childNodes[0].innerText = index + '/' + tracks.length; if (index == tracks.length - 1) { zip.generateAsync({type:"blob"}) .then(function(content) { saveAs(content, zipFileName + ".zip"); allDownloadButton.childNodes[0].innerText = initialText; }); } else { downloadLyricAsync(index + 1); } } api.media(tracks[index].id, onComplete); } downloadLyricAsync(0); } catch(e) { alert(failedText); allDownloadButton.childNodes[0].innerText = initialText; } } if (isPlayList) { WEAPI.playlistDetail(playListId).then(onComplete); } else { WEAPI.album(playListId).then(onComplete); } } }, downloadAlbumImageZip: function() { function artistListToString(ar) { let str = ''; if (ar == null) { return str; } for (let i = 0; i < ar.length; ++i) { if (str != '') { str += ' & '; } str += ar[i].name; } str = str.trim(); return str; } try { if (location.href.indexOf('#/playlist') != -1) { var playListId = location.href.split('id=')[1]; let initialText = downloadPics.childNodes[0].innerText; WEAPI.playlistDetail(playListId).then(function (r###lt) { try{ if (r###lt == null) { throw("封面下载失败..."); } var zip = new JSZip(); if (r###lt.description) zip.file("歌单介绍.txt", r###lt.description.replace(/\n/g, '\r\n')); zip.file("说明.txt", "由\"网易云音乐直接下载\"脚本下载。\r\n脚本链接:https://greasyfork.org/zh-CN/scripts/33046"); zip.file("歌单链接.url", "[{000214A0-0000-0000-C000-000000000046}]\nProp3=19,2\n[InternetShortcut]\nIDList=\nURL=http://music.163.com/#/playlist?id=" + playListId); var tracks = r###lt.tracks; var zipFileName = r###lt.creator.nickname + ' - ' + r###lt.name + ' - 封面'; zipFileName = zipFileName.replace(/[\/:*?"<>|]*/g, '').trim(); function downloadAlbumImageAsync(index) { let fileName = ''; if (g_nameRule == NAMERULE.ARTIST_TITLE) { fileName = artistListToString(r###lt.tracks[index].ar); if (fileName != '') { fileName += ' - '; } fileName += r###lt.tracks[index].name; } else { fileName = r###lt.tracks[index].name; let artists = artistListToString(r###lt.tracks[index].ar); if (artists != '') { fileName += ' - '; fileName += artists; } } // 删除文件中不允许的字符 fileName = fileName.replace(/[\/:*?"<>|]*/g, '').trim(); let url = tracks[index].al.picUrl; function onComplete(blob, status) { downloadPics.childNodes[0].innerText = '正在下载:' + index + '/' + tracks.length; if (status == 200) { zip.file('pics\\' + fileName + url.match('\.[a-zA-Z]+$')[0], blob); } if (index == tracks.length - 1) { zip.generateAsync({type:"blob"}) .then(function(content) { saveAs(content, zipFileName + ".zip"); downloadPics.childNodes[0].innerText = initialText; }); } else { downloadAlbumImageAsync(index + 1); } } if (tracks[index].al && url && url != '') { downloader.FileRequest(url, null, onComplete); } else { onComplete(null, 404); } } downloader.FileRequest(r###lt.coverImgUrl, null, function(blob, status) { if (status == 200) { zip.file(r###lt.name + ' - ' + r###lt.creator.nickname + r###lt.coverImgUrl.match('\.[a-zA-Z]+$')[0], blob); } downloadAlbumImageAsync(0); downloadPics.childNodes[0].innerText = '正在下载:0/' + tracks.length; }); } catch (e) { alert('封面下载失败...'); downloadPics.childNodes[0].innerText = initialText; } }); } } catch(e) { alert('封面下载失败...'); downloadPics.childNodes[0].innerText = initialText; } }, downloadMusicZip: function() { function artistListToString(ar) { let str = ''; if (ar == null) { return str; } for (let i = 0; i < ar.length; ++i) { if (str != '') { str += ' & '; } str += ar[i].name; } str = str.trim(); return str; } try { if (location.href.indexOf('#/album') != -1) { var albumId = location.href.split('id=')[1]; let initialText = allDownloadButton.childNodes[0].innerText; WEAPI.album(albumId).then(function (r###lt) { try{ if (r###lt == null) { throw("歌曲下载失败..."); } var zip = new JSZip(); if (r###lt.album.description) { zip.file("专辑介绍.txt", r###lt.album.description.replace(/\n/g, '\r\n')); } zip.file("说明.txt", "由\"网易云音乐直接下载\"脚本下载。\r\n脚本链接:https://greasyfork.org/zh-CN/scripts/33046"); zip.file("专辑链接.url", "[{000214A0-0000-0000-C000-000000000046}]\nProp3=19,2\n[InternetShortcut]\nIDList=\nURL=http://music.163.com/#/album?id=" + albumId); var songs = r###lt.songs; var zipFileName = r###lt.album.artist.name + ' - ' + r###lt.album.name; zipFileName = zipFileName.replace(/[\/:*?"<>|]*/g, '').trim(); function downloadSongAsync(index) { let fileName = ''; if (g_nameRule == NAMERULE.ARTIST_TITLE) { fileName = artistListToString(songs[index].ar); if (fileName != '') { fileName += ' - '; } fileName += songs[index].name; } else { fileName = songs[index].name; let artists = artistListToString(songs[index].ar); if (artists != '') { fileName += ' - '; fileName += artists; } } // 删除文件中不允许的字符 fileName = fileName.replace(/[\/:*?"<>|]*/g, '').trim() + songs[index].songExt; let url = songs[index].songUrl; function onComplete(blob, status) { allDownloadButton.childNodes[0].innerText = '正在下载:' + index + '/' + songs.length; if (status == 200) { zip.file('songs\\' + fileName, blob); } if (index == songs.length - 1) { zip.generateAsync({type:"blob"}) .then(function(content) { saveAs(content, zipFileName + ".zip"); allDownloadButton.childNodes[0].innerText = initialText; }); } else { downloadSongAsync(index + 1); } } if (url && url != '') { allDownloadButton.childNodes[0].innerText = '正在下载:0/' + songs.length; downloader.FileRequest(url, null, onComplete); } else { onComplete(null, 404); } } let array = []; for (let i = 0; i < songs.length; ++i) { array.push(songs[i].id); } WEAPI.songsUrl(array).then(function(urls) { for (let i = 0; i < urls.length; ++i) { for (let j = 0; j < songs.length; ++j) { if (songs[j].id == urls[i].id) { songs[j].songUrl = urls[i].url; songs[j].songExt = '.' + urls[i].type; break; } } } downloadSongAsync(0); }); } catch (e) { alert('歌曲下载失败...'); allDownloadButton.childNodes[0].innerText = initialText; } }); } } catch(e) { alert('歌曲下载失败...'); allDownloadButton.childNodes[0].innerText = initialText; } } }, ]; function matchPag###RL(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 (matchPag###RL(location.href, page.url)) { page.handler(); } } }); } }) (window);