网易云音乐缓存文件

1.Ubuntu版的网易云音乐已经懒得加密了吗…名字里甚至都已经带了md5码的加密方法…

╰─$ ls ~/.cache/netease-cloud-music/CachedSongs 
567602-128-55881971d77b3ec1a5a134e2670a72e7.mp3

2.如果是windows或Android,需要借助Python脚本解密加密了的缓存文件

解密用Python脚本来源:https://github.com/mbinary/netease-cached-music

使用方法:

将缓存文件放到脚本文件所在目录下,在python3中运行该脚本。解密结果会输出到”cached_网易云音乐“目录下。

以下为解密用脚本:(注:因为Python2.7对UTF8编码的支持问题,需要Python3或以上版本)

#coding : utf-8
import os
import sys
import glob
import requests

DESDIR = './cached_网易云音乐'
LRCDIR = os.path.join(DESDIR, 'lyric')
MSCDIR = os.path.join(DESDIR, 'music')

API = 'https://api.imjad.cn/cloudmusic/?'
# two args: id  type
# type=song, lyric, comments, detail, artist, album, search
# eg  API = 'https://api.imjad.cn/cloudmusic/?type=song&id=1234132'    download music

hasModu = False
try:
    from mutagen.easyid3 import EasyID3
    from mutagen.mp3 import MP3
    hasModu = True
except:
    pass

def safeprint(s):
    '''deal with invalid encoded filename'''
    try:
        print(s)
    except:
        print(repr(s)[1:-1])

class netease_music:
    def __init__(self, path=''):
        '''path is the direcoty that contains Music files(cached)'''
        if path == '':
            path = input('input the path of cached netease_music')
        self.path = path
        safeprint('[+] Current Path: ' + path)
        os.chdir(path)
        self.files = glob.glob('*.uc') + glob.glob('*.uc!')
        self.id_mp = {}
        for i in self.files:
            self.id_mp[self.getId(i)] = i
        if not os.path.exists(DESDIR):
            os.mkdir(DESDIR)
        if not os.path.exists(LRCDIR):
            os.mkdir(LRCDIR)
        if not os.path.exists(MSCDIR):
            os.mkdir(MSCDIR)
        # import re
        # self.nameXpath ='//div[@class="tit"]/em[@class="f-ff2"]/text()'
        # self.lrcSentencePt=re.compile(r'\[\d+:\d+\.\d+\](.*?)\\n')         # wrong  (r'\[\d+,\d+\](\(\d+,\d+\)(\w))+\n')

    def getId(self, name):
        return name[:name.find('-')]

    def getInfoFromWeb(self, musicId):
        dic = {}
        url = API+'type=detail&id=' + musicId
        info = requests.get(url).json()['songs'][0]
        dic['artist'] = [info['ar'][0]['name']]
        dic['title'] = [info['name']]
        dic['cover'] = [info['al']['picUrl']]
        return dic

    def getInfoFromFile(self, path):
        if not os.path.exists(path):
            safeprint('Can not find file ' + path)
            return {}
        elif hasModu:
            return dict(MP3(path, ID3=EasyID3))
        else:
            print('[Error] You can use pip3 to install mutagen or connet to the Internet')
            raise Exception('Failed to get info of ' + path)

    def getPath(self, dic,musicId):
        title = dic['title'][0]
        artist = dic['artist'][0]
        if artist in title:
            title = title.replace(artist, '').strip()
        name = (title + '--' + artist)
        for i in '>?*/\:"|<':
            name = name.replace(i,'-') # form valid file name
        self.id_mp[musicId] = name
        #print('''{{title: "{title}",artist: "{artist}",mp3: "http://ounix1xcw.bkt.clouddn.com/{name}.mp3",cover: "{cover}",}},'''\
               #.format(title = title,name = name,artist=artist,cover=dic['cover'][0]))
        return os.path.join(MSCDIR, name + '.mp3')
    
    def decrypt(self, cachePath):
        musicId = self.getId(cachePath)
        idpath = os.path.join(MSCDIR, musicId + '.mp3')
        try:  # from web
            dic = self.getInfoFromWeb(musicId)
            path = self.getPath(dic,musicId)
            if os.path.exists(path): return 
            with open(path,'wb') as f:
                f.write(bytes(self._decrypt(cachePath)))
        except Exception as e:  # from file
            print(e)
            if not os.path.exists(idpath):
                with open(idpath,'wb') as f:
                    f.write(bytes(self._decrypt(cachePath)))
            dic = self.getInfoFromFile(idpath)
            path = getPath(dic,musicId)
            if os.path.exists(path):
                os.remove(idpath)
                return 
            os.rename(idpath, path)
            
    def _decrypt(self,cachePath):
        with open(cachePath, 'rb') as f:
            btay = bytearray(f.read())
        for i, j in enumerate(btay):
            btay[i] = j ^ 0xa3
        return btay
    
    def getLyric(self, musicId):
        name = self.id_mp[musicId]
        url = API + 'type=lyric&id=' + musicId
        url2 = 'https://music.163.com/api/song/lyric?id='+ musicId +'&lv=1&kv=1&tv=-1'
        try:
            lrc = requests.get(url).json()['lrc']['lyric']
            if lrc=='':
                lrc = requests.get(url2).json()['lrc']['lyric']
            if lrc=='':
                raise Exception('')
            file = os.path.join(LRCDIR, name + '.lrc')
            if not os.path.exists(file):
                with open(file, 'w', encoding='utf8') as f:
                    f.write(str(lrc))
        except Exception as e:
            print(e,end='')
            safeprint(': Failed to get lyric of music '+name)
    def getMusic(self):
        for ct, cachePath in enumerate(self.files):
            self.decrypt(cachePath)
            musicId = self.getId(cachePath)
            print('[{}]'.format(ct+1).ljust(5)+self.id_mp[musicId])
            self.getLyric(musicId)


if __name__ == '__main__':
    if len(sys.argv) > 1:
        path = sys.argv[1].strip()
    else:
        path = os.path.join(os.getcwd(), '.')
    handler = netease_music(path)
    handler.getMusic()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值