网易云音乐缓存解密Python脚本

会员下载限制的替代方案

Category: ExperienceSharing Tag: NetEaseMusic&Python&Decrypt Created on 2019-10-23 Latest Update on 2019-10-23

网易云缓存解密Python脚本


相信大家都有听到好听的歌曲,但是因为会员问题无法下载的经历,而为了一首歌曲就去充一个月的会员就感觉有些亏,这就很难受了。我也遇到了这个问题,于是花了一中午写了一个关于网易云缓存的解密脚本来用,希望能给其他小伙伴带来帮助。但是还是要多多支持正版才好啊~

具体原理就是网易云在播放歌曲时会将歌曲文件加密后存放在本地,以便离线时还可以听,这就给了我们可乘之机。将缓存文件解密后就得到了歌曲的源文件,也不需要充会员啦。

我简单写了三个模式,分别实现了转换某个特定的文件、转换全部文件、转换最近的几个文件。在使用时可以按需选择。具体使用方法的话在脚本中已经说的很详细了,调用脚本的话:Linux不多说,shell就可以;Windows可以打开cmd运行脚本。(Python3环境是必须的诶~)

注意

  • 由于我们解密的是缓存的文件,所以对于那些没有会员就不能听的歌曲,这个脚本就没有用武之地啦。
  • 对于音质,当然就是在线收听时的音质了,原因基本同上。
  • 由于网易云在缓存时使用的不是歌曲的名字,所以没有办法通过歌曲名来选择。你可以清除缓存之后再听一遍你想要的那首歌,这样运行脚本就可以啦;或者如果你是最近才听的这首歌,你可以使用转换最近几个文件的功能,这样也还算方便。

Cheers!

# Author: C0n5t4ntK
# Personal Blog: www.elapse.life

import os
import time

# Decrypt file using nor 0xa3 for each byte
def decrypt(cache_path, export_path, password = 0xa3):
    f_read = open(cache_path, 'rb')
    f_write = open(export_path, 'wb')
    for obj in f_read:
        for byte in obj:
            new_byte = byte ^ password
            f_write.write(bytes([new_byte]))
    f_read.close()
    f_write.close()

# Mode 1
def decrypt_file():
    cache_path = input('Pls input the path of the file!\n')
    export_path = input('Where do you want to export? Pls input the specific file\'s path,(including file name and extension). Or press ENTER to use the default directory.\n')
    if export_path == '':
        print('You didn\'t write down the path to export, the default path is D:\\\\decrypt_Export_From_Netease_Music\\decrypted.mp3.')
        if not os.path.exists('D:\\decrypt_Export_From_Netease_Music'):
            os.makedirs('D:\\decrypt_Export_From_Netease_Music')
        export_path = 'D:\\decrypt_Export_From_Netease_Music\\decrypted.mp3'
    try:
        print('Wait a second pls...')
        time_start = time.time()
        decrypt(cache_path, export_path)
        time_end = time.time()
        time_used = time_end - time_start
    except Exception:
        print('The path is wrong!')
        return
    else:
        print('Done! It took ' + "{:.2f}".format(time_used) + 's. Enjoy!')

# Mode 2
def decrypt_files():
    cache_path = input('Pls input the path of cache directory!\n')
    export_path = input('Where do you want to export? Input a directory path! Or press ENTER to use the default directory.\n')
    if export_path == '':
        print('You didn\'t write down the path to export, the default path is D:\\\\decrypt_Export_From_Netease_Music.')
        if not os.path.exists('D:\\decrypt_Export_From_Netease_Music'):
            os.makedirs('D:\\decrypt_Export_From_Netease_Music')
        export_path = 'D:\\decrypt_Export_From_Netease_Music'
    try:
        print('Wait a second pls...')
        time_start = time.time()
        count = 0
        for root, dirs, files in os.walk(cache_path):
            for file in files:
                (filename, extension) = os.path.splitext(file)
                if (extension == '.uc'):
                    decrypt(cache_path + '\\' + file, export_path + '\\' + filename + '.mp3')
                    count += 1
                    print('Already converted ' + str(count) + ' file(s)...')
        time_end = time.time()
        time_used = time_end - time_start
    except Exception:
        print('Wrong path! Pls try again later.')
        return
    else:
        print('Done! It took ' + "{:.2f}".format(time_used) + 's. Enjoy!')

# Mode 3
def decrypt_recent_files():
    num = input('How many files do you want to convert? Input a number.\n')
    try:
        num = int(num)
    except Exception:
        print('The number is invalid...')
        return
    cache_path = input('Pls input the path of cache directory!\n')
    export_path = input('Where do you want to export? Input a directory path! Or press ENTER to use the default directory.\n')
    if export_path == '':
        print('You didn\'t write down the path to export, the default path is D:\\\\decrypt_Export_From_Netease_Music.')
        if not os.path.exists('D:\\decrypt_Export_From_Netease_Music'):
            os.makedirs('D:\\decrypt_Export_From_Netease_Music')
        export_path = 'D:\\decrypt_Export_From_Netease_Music'
    try:
        print('Wait a second pls...')
        time_start = time.time()
        count = 0
        files_list = []
        files = os.listdir(cache_path)
        for file in files:
            (filename, extension) = os.path.splitext(file)
            if (extension == '.uc'):
                files_list.append(file)
        files_list.sort(key=lambda file: os.path.getmtime(cache_path + '\\'+ file) if not os.path.isdir(cache_path + '\\'+ file) else 0)
        lens = len(files_list)
        if num <= lens:
            for file in files_list[-1:-(num + 1):-1]:
                (filename, extension) = os.path.splitext(file)
                decrypt(cache_path + '\\' + file, export_path + '\\' + filename + '.mp3')
                count += 1
                print('Already converted ' + str(count) + ' file(s)...')
        else:
            print('There\'re not enough files to convert, try to input smaller.')
            return
        time_end = time.time()
        time_used = time_end - time_start
    except Exception:
        print('Sorry the path is wrong, pls try again later.')
        return
    else:
        print('Done! It took ' + "{:.2f}".format(time_used) + 's. Enjoy!')

if __name__ == '__main__':
    print('------------------------------')
    print('This is a small python script(on windows) which can decrypt music files with \".uc\" extension from Netease Cloud Music\'s cache.')
    print('It has three simple modes, which are: convert single file, convert all files in a directory or convert the most recently used files. You can follow the coming hints.')
    print('------------------------------')
    print('Attention: You can find the cache directory in the settings of Netease Cloud Music.')
    print('And the default directory is C:\\\\Users\\$your_username\\AppData\\Local\\Netease\\CloudMusic\\Cache\\Cache.')
    print('Type \'CTRL + C\' to stop.')
    print('And sorry Netease Cloud Music didn\'t cache files by song\'s name, so I cannot name the files by the song.^_^')
    print('------------------------------')
    choose = input('Please pick a number to choose a mode you want to use.\n1. Single file\n2. All files in directory\n3. Most recently used file\n')
    if choose == '1':
        print('You chose single file mode, of course.')
        decrypt_file()
    elif choose == '2':
        print('Here\'s the directory mode.')
        decrypt_files()
    elif choose == '3':
        print('Seems like you want to convert recent files.')
        decrypt_recent_files()
    else:
        print('Invalid number! Please try again later!'