Skip to content

Instantly share code, notes, and snippets.

@keng42
Created April 11, 2020 05:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save keng42/3ee556d746332cd8a6db307b008cc0b2 to your computer and use it in GitHub Desktop.
Save keng42/3ee556d746332cd8a6db307b008cc0b2 to your computer and use it in GitHub Desktop.
/**
* 用网易云音乐的歌单创建 macOS(iOS) Music(本地音乐文件,非 Apple Music) 的播放列表
*
* 1. 打开网易云音乐歌单网页版,打开控制台
* 2. 运行下面代码
* 3. run('歌单名', '音乐文件夹绝对路径')
* 或者替换 MUSIC_DIR 然后直接运行 run()
*
* 4. 下载音乐文件到自定义目录,打开 Music 导入播放列表
* 音乐文件需以 `歌手名 - 歌曲名.mp3` 格式命名
*
* created by keng42 @2020-04-11 13:19:50
*/
const MUSIC_DIR = 'macOS/Users/keng42/Music/FreeMusic/';
function download(content, filename) {
// 创建隐藏的可下载链接
const eleLink = document.createElement('a');
eleLink.download = filename;
eleLink.target = '_blank';
eleLink.style.display = 'none';
// 字符内容转变成blob地址
const blob = new Blob([content]);
eleLink.href = URL.createObjectURL(blob);
// 触发点击
document.body.appendChild(eleLink);
eleLink.click();
// 然后移除
document.body.removeChild(eleLink);
}
function run(playlist, musicDir = MUSIC_DIR) {
const frame = document.getElementById('g_iframe').contentWindow.document;
if (!playlist) {
playlist =
(
frame.querySelector('.f-ff2.f-thide') ||
frame.querySelector('.f-ff2.f-brk') ||
{}
).innerText || 'playlist';
}
// 移除表单中乱七八糟的字符
const soils = frame.querySelectorAll('.soil');
soils.forEach((item) => {
item.innerText = '';
});
const mvs = frame.querySelectorAll('.mv');
mvs.forEach((item) => {
item.innerText = '';
});
const trs = frame.querySelectorAll('tbody>tr');
const songs = [];
trs.forEach((item) => {
const name = item.children[1].innerText
.split('\n')
.join('')
.split(' ') // 这东西不是空格
.join(' ');
const artist = item.children[3].innerText
.split('\n')
.join('')
.split(' ')
.join(' ');
const album = item.children[4].innerText
.split('\n')
.join('')
.split(' ')
.join(' ');
if (name && artist) {
songs.push({ name, artist, album });
}
});
const header =
'Name\tArtist\tComposer\tAlbum\tGrouping\tWork\tMovement Number\tMovement Count\tMovement Name\tGenre\tSize\tTime\tDisc Number\tDisc Count\tTrack Number\tTrack Count\tYear\tDate Modified\tDate Added\tBit Rate\tSample Rate\tVolume Adjustment\tKind\tEqualizer\tComments\tPlays\tLast Played\tSkips\tLast Skipped\tMy Rating\tLocation';
const template =
'T_NAME\tT_ARTIST\t\tT_ALBUM\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tT_FILEPATH';
const playlistStr = songs
.map((item) => {
return template
.replace('T_NAME', item.name)
.replace('T_ARTIST', item.artist)
.replace('T_ALBUM', item.album)
.replace('T_FILEPATH', `${musicDir}${item.artist} - ${item.name}.mp3`);
})
.join('\n');
const content = `${header}\n${playlistStr}\n`;
download(content, playlist);
return `歌曲数量:${songs.length}`;
}
run();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment