写这篇随笔时,代码已经写完好久了,最近一直在琢磨如何用pyinstaller打包,正好最近开始用博客园,现在才决定写一写(大佬不喜勿喷)
这有个前身版本,我写在CSDN上了,可以去看看,是关于api分析的(只是最后学校开学就断更了,不知道以后有没有机会补上)
好,现在可以进入正题了(●\'◡\'●)写了点注释供小白参考
下载酷我音乐:
def kuwo(tempath): songid = re.findall(r\'.*?play_detail/(\d*)\', songurl)[0] audiolink = json.loads( requests.get(f\'http://m.kuwo.cn/newh5app/api/mobile/v1/music/src/{songid}\').text)[\'data\'][\'url\'] audio = requests.get(audiolink, timeout=10).content # 获取信息 res = requests.get(f\'https://m.kuwo.cn/newh5/singles/songinfoandlrc?musicId={songid}\').text text = json.loads(res)[\'data\'][\'songinfo\'] name = text[\'songName\'] artists = text[\'artist\'].replace(\'&\', \'、\') album = text[\'album\'] lyric = \'\' for i in json.loads(res)[\'data\'][\'lrclist\']: lyric += \'[{}:{}.{}]\'.format(\'%02d\' % math.floor(float(i[\'time\']) / 60), \'%02d\' % math.floor(float(i[\'time\']) % 60), (\'%.2f\' % math.modf(float(i[\'time\']))[0])[2:]) lyric += i[\'lineLyric\'] + \'\n\' # 保存文件 filename = re.sub(r"[\\/:*?\"<>|]", "", artists) + \' - \' + re.sub(r"[\\/:*?\"<>|]", "", name) with open(path + filename + \'.aac\', \'wb\') as f1: f1.write(audio) f1.close() if len(lyric) != 0: with open(path + filename + \'.lrc\', \'w\', encoding="UTF-8") as f2: f2.write(lyric) f2.close() strcmd = fr\'"{tempath}\ffmpeg\bin\ffmpeg.exe" -i "{path + filename}.aac" -acodec libmp3lame "{path + filename}.mp3"\' subprocess.call(strcmd, creationflags=0x08000000) os.remove(path + filename + \'.aac\') file = ID3(path + filename + \'.mp3\') file[\'TIT2\'] = TIT2(encoding=3, text=name) file[\'TPE1\'] = TPE1(encoding=3, text=artists) file[\'TALB\'] = TALB(encoding=3, text=album) file.save() return f\'《{name}》下载完成!\'
这当中要注意的是酷我音乐下下来的歌曲文件是aac格式,我调用了ffmpeg把格式转换成了mp3,然后才能调用mutagen库写入歌曲信息,所以运行时要确保ffmpeg在tempath下哦(没有ffmpeg的小朋友请戳这里,当然也可以自己去官网找最新版)。
下载网易云音乐(无法试听的歌下不了):
def wangyi(): songid = re.findall(r\'.*?id=(\d*)\', songurl)[0] audiolink = requests.get(f\'http://music.163.com/song/media/outer/url?id={songid}.mp3\', headers={\'user-agent\': \'\'}).url if audiolink != \'https://music.163.com/404\': audio = requests.get(audiolink).content # 获取信息 res = requests.get(f\'https://music.163.com/api/song/detail/?ids=%5B{songid}%5D\').text text = json.loads(res)[\'songs\'][0] name = text[\'name\'] album = text[\'album\'][\'name\'] artists = [] for artist in text[\'artists\']: artists.append(artist[\'name\']) artists = \'、\'.join(artists) lyric = \'\' lrctext = json.loads(requests.get(f\'https://music.163.com/api/song/lyric?id={songid}&lv=1&tv=-1\').text) if \'nolyric\' not in lrctext: lrc = lrctext[\'lrc\'][\'lyric\'] tlrc = lrctext[\'tlyric\'][\'lyric\'] + \'\n\' for m in re.compile(r\'(\[\d*:\d*.\d*])(.*?)\n\').findall(lrc + \'\n\'): lyric += m[0] + m[1] + \' \' for n in re.compile(r\'(\[\d*:\d*.\d*])(.*?)\n\').findall(tlrc + \'\n\'): if n[0] == m[0] and n[1] != m[1]: lyric += n[1] lyric += \'\n\' # 保存文件 filename = re.sub(r"[\\/:*?\"<>|]", "", artists) + \' - \' + re.sub(r"[\\/:*?\"<>|]", "", name) with open(path + filename + \'.mp3\', \'wb\') as f1: f1.write(audio) f1.close() if len(lyric) != 0: with open(path + filename + \'.lrc\', \'w\', encoding="UTF-8") as f2: f2.write(lyric) f2.close() file = ID3(path + filename + \'.mp3\') file[\'TIT2\'] = TIT2(encoding=3, text=name) file[\'TPE1\'] = TPE1(encoding=3, text=artists) file[\'TALB\'] = TALB(encoding=3, text=album) file.save() return f\'《{name}》下载完成!\' else: return f\'暂不支持下载\'
这里我干了一件有意思的事情,就是在处理歌词这一部分,如果有更好的匹配方法,欢迎留言哦。
最后整理整理,完整代码差不多像这样:
main.py
import requests import re import json from mutagen.id3 import ID3, TIT2, TPE1, TALB import getpass import math import subprocess import os import shutil import sys def kuwo(tempath): ... def wangyi(): ... if __name__ == \'__main__\': path = r\'C:/Users/{}/Music/\'.format(getpass.getuser()) tpath = getattr(sys, \'_MEIPASS\', os.path.dirname(os.path.abspath(__file__))) print(\'欢迎使用...\') songurl = input(\'请输入:\n\') while songurl != \'exit\': if \'music.163.com\' in songurl: print(wangyi()) elif \'kuwo.cn\' in songurl: print(kuwo(tpath)) songurl = input(\'请输入:\n\') shutil.rmtree(tpath) print(\'感谢使用(* ̄▽ ̄*)\')
顺带提一嘴如何使用pyinstaller打包软件,首先生成spec:
pyi-makespec -F -i {ico路径} -n {项目名} main.py
-F是打包成单文件的意思(默认多文件),如果省略-n,第一个脚本的主文件名将作为spec的名字。
然后找到生成的spec(我的在用户文件夹下)修改如下:
... datas=[(\'C:\\Users...\\ffmpeg\', \'ffmpeg\')] ...
第一个是资源文件夹的位置,第二个是生成临时目录的名称。如果和我不一样的注意上面的python代码不能照搬!
最后生成exe:
pyinstaller -F {文件名.spec}