From 91f568e18d00e75bddff738b87581c360b536f38 Mon Sep 17 00:00:00 2001 From: 1826013250 <1826013250@qq.com> Date: Sat, 24 Jun 2023 14:01:32 +0800 Subject: [PATCH] Settings: Filename Format Set and small changes to follow PEP8 code style change default README to Chinese --- README.md | 49 +++++++++++----------- README_cn.md | 36 ---------------- README_en.md | 40 ++++++++++++++++++ modules/functions/mainly/get_song.py | 9 +++- modules/functions/mainly/load_file_song.py | 2 +- modules/functions/mainly/multi_download.py | 2 +- modules/submenus/settings.py | 47 +++++++++++++++++---- modules/utils/clear_screen.py | 4 +- modules/utils/dump.py | 3 +- modules/utils/prints.py | 21 ++++++++-- 10 files changed, 132 insertions(+), 81 deletions(-) delete mode 100644 README_cn.md create mode 100644 README_en.md diff --git a/README.md b/README.md index 19c60be..d0fea77 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,39 @@ -NeteaseMusicLyricDownloader -=========================== -**English**|[简体中文](./README_cn.md) +# NeteaseMusicLyricDownloader +**简体中文**|[English](https://github.com/1826013250/NeteaseMusicLyricDownloader/README_en.md) -A simple tool to download lyrics in Netease Music +一个下载网易云音乐歌词的简单工具 -_*Caution:* The author is not native English speaker. If there are some grammar mistakes, please ignore them. Thanks!!!!_ +## 原理 +它用了Python中的一个`requests`模块来实现抓取歌词文件的功能 -## How does it work? -It uses the module `requests` to fetch the lyric on music.163.com +网易云音乐提供给我们了一个获取歌词的API ~~然后我就做了这个程序(~~ -Netease Music supply us an api that we can get the lyric of the current song, so I make this program... +## 安装 +首先,你需要一个Python环境(要求版本>=3.10,因为使用了3.10python的新特性) -## Installation -First, you need a python(>=3.10) environment - -Second, clone the entire project and install packages with the command below: +然后,把整个项目clone下来,安装依赖项目: ```commandline python3 -m pip install -r requirements.txt ``` -Last, run the command `python3 main.py` in the project folder. +最后运行下面命令: +```commandline +python3 main.py +``` -## What can it do? -Just download lyrics. +## 功能 -You need to provide the id or the share link of the song, and the program will download the lyrics automatically. +- 通过id下载特定音乐的歌词 +- 使用分享链接下载特定音乐歌词 +- 批量链接下载 +- 从网易云下载的歌曲获取信息并下载 +- 解锁网易云锁定的歌曲文件并下载歌词 -Now it can recognize 163 key in music files that download from Netease Cloudmusic client. +## TODO -- 2022/8/13 Now it has the function from `ncmdump`, and it can decrypt the ncm files and fetch the specific lyric. +完善设置...... -## Todo +## 其他要说的 -Add more functions like searching... +这就一简简单单普普通通的程序 -## Others - -Just a easy program... - -I don't have much time to focus on it... +我可能也没有太多的精力去写这个项目... diff --git a/README_cn.md b/README_cn.md deleted file mode 100644 index ae85b26..0000000 --- a/README_cn.md +++ /dev/null @@ -1,36 +0,0 @@ -# NeteaseMusicLyricDownloader -[English](https://github.com/1826013250/NeteaseMusicLyricDownloader)|**简体中文** - -一个下载网易云音乐歌词的简单工具 - -## 这个玩意原理是啥? -它用了Python中的一个`requests`模块来实现抓取歌词文件的功能 - -网易云音乐提供给我们了一个获取歌词的API ~~然后我就做了这个程序(~~ - -## 爷要安装 -首先,你需要一个Python环境(要求版本>=3.10,因为使用了3.10python的新特性) - -然后,把整个项目薅下来,安装依赖项目: -```commandline -python3 -m pip install -r requirements.txt -``` -最后运行下面命令: -```commandline -python3 main.py -``` - -## 这玩意到底能干啥? -~~nmd~~这玩意就像它的名字一样,下载歌词用的 - -你需要提供歌曲的id或者分享链接,或者已经下好的歌曲路径,然后这破玩意就会自动下载歌词 - -## 后续有啥功能? - -_~~我不造,要不你来写罢(~~_ - -## 其他要说的 - -这就一简简单单普普通通的程序 - -我可能也没有太多的精力去写这么个~~破玩意~~... diff --git a/README_en.md b/README_en.md new file mode 100644 index 0000000..9cdd621 --- /dev/null +++ b/README_en.md @@ -0,0 +1,40 @@ +NeteaseMusicLyricDownloader +=========================== +[简体中文](https://github.com/1826013250/NeteaseMusicLyricDownloader)|**English** + +A simple tool to download lyrics in Netease Music + +_*Caution:* The author is not native English speaker. If there are some grammar mistakes, please ignore them. Thanks!!!!_ + +## How does it work? +It uses the module `requests` to fetch the lyric on music.163.com + +Netease Music supply us an api that we can get the lyric of the current song, so I make this program... + +## Installation +First, you need a python(>=3.10) environment + +Second, clone the entire project and install packages with the command below: +```commandline +python3 -m pip install -r requirements.txt +``` +Last, run the command `python3 main.py` in the project folder. + +## What can it do? +Just download lyrics. + +You need to provide the id or the share link of the song, and the program will download the lyrics automatically. + +Now it can recognize 163 key in music files that download from Netease Cloudmusic client. + +- 2022/8/13 Now it has the function from `ncmdump`, and it can decrypt the ncm files and fetch the specific lyric. + +## Todo + +Add more functions like searching... + +## Others + +Just a easy program... + +I don't have much time to focus on it... diff --git a/modules/functions/mainly/get_song.py b/modules/functions/mainly/get_song.py index 5412c86..6d9b63b 100644 --- a/modules/functions/mainly/get_song.py +++ b/modules/functions/mainly/get_song.py @@ -59,11 +59,16 @@ def get_song_info_raw(types: list, identify: str, bar: CompactBar = None): return need -def get_song_lyric(identify: str | int | dict, path: str, allinfo: bool = False, bar: CompactBar = None): +def get_song_lyric(identify: str | int | dict, + path: str, + lyric_format="%(name)s - %(artists)s", + allinfo: bool = False, + bar: CompactBar = None): """获取歌词 ``identify`` 提供一个歌曲id ``path`` 提供歌曲下载的路径 + ``lyric_format`` 提供歌词保存的格式 ``allinfo`` 若此项为 True ,则提供的identify格式必须为存储在网易云下载文件中meta_data的格式 ``bar`` 若获取歌词时下方有进度条, 则应当传入此参数""" if allinfo: @@ -96,7 +101,7 @@ def get_song_lyric(identify: str | int | dict, path: str, allinfo: bool = False, artists = regular_filename(artists) bprint(Fore.YELLOW + "\t-> 歌曲:" + Style.RESET_ALL + f"{name} - {artists}", bar) - filename = f"{name} - {artists}.lrc" + filename = f"{lyric_format % {'name': name, 'artists': artists}}.lrc" try: info = post(f"https://music.163.com/api/song/media?id={identify}").json() diff --git a/modules/functions/mainly/load_file_song.py b/modules/functions/mainly/load_file_song.py index 6f2b024..cae31d5 100644 --- a/modules/functions/mainly/load_file_song.py +++ b/modules/functions/mainly/load_file_song.py @@ -217,7 +217,7 @@ def get_lyric_from_folder(self): with CompactArrowBar(f"进度: %(index){len(str(len(musics)))}d/%(max)d", suffix="", max=len(musics), color="yellow", width=9999) as bar: for i in range(0, len(musics)): # 根据索引结果获取歌词 - if get_song_lyric(musics[i], lyric_path, allinfo=True, bar=bar) == "dl_err_connection": + if get_song_lyric(musics[i], lyric_path, self.settings.lyric_format, True, bar) == "dl_err_connection": bar.print_onto_bar(Fore.RED + "下载发生错误!可能是连接被拒绝!请检查网络后再试\n按回车键继续任务(该任务会被跳过)...") input() bar.next() diff --git a/modules/functions/mainly/multi_download.py b/modules/functions/mainly/multi_download.py index 27c36a2..92ca3a4 100644 --- a/modules/functions/mainly/multi_download.py +++ b/modules/functions/mainly/multi_download.py @@ -34,7 +34,7 @@ def mdl(self): with CompactArrowBar(f"进度: %(index){len(str(len(ids)))}d/%(max)d", suffix="", max=len(ids), color="yellow", width=9999) as bar: for i in range(0, len(ids)): - r = get_song_lyric(ids[i], self.settings.lyric_path, bar=bar) + r = get_song_lyric(ids[i], self.settings.lyric_path, self.settings.lyric_path, bar=bar) if r == "dl_err_connection": bar.print_onto_bar(Fore.RED + "下载发生错误!可能是连接被拒绝!请检查网络后再试\n按回车键继续任务(该任务会被跳过)...") input() diff --git a/modules/submenus/settings.py b/modules/submenus/settings.py index e397ea5..32bb8ee 100644 --- a/modules/submenus/settings.py +++ b/modules/submenus/settings.py @@ -5,7 +5,7 @@ from colorama import Fore from modules.utils.clear_screen import cls_stay from modules.utils.inputs import rinput, cinput from modules.functions.settings.save_load_settings import save_settings -from modules.utils.prints import print_menu +from modules.utils.prints import input_menu def settings_menu(self): @@ -16,7 +16,7 @@ def settings_menu(self): cls_stay(self, f"[设置菜单] " f"{Fore.LIGHTCYAN_EX}自动保存: " f"{({True: f'{Fore.GREEN}开', False: f'{Fore.RED}关'}[self.settings.auto_save])}") - print_menu({ + r = input_menu({ "0": "返回上级菜单", "1": "歌曲保存路径", "2": "清空输出文件夹内的内容", @@ -24,7 +24,6 @@ def settings_menu(self): "4": "部分动态效果", "s": "切换设置自动保存" }) - r = rinput("请选择:") if r == "0": return elif r == "1": @@ -32,7 +31,7 @@ def settings_menu(self): elif r == "2": __remove_output_files(self) elif r == "3": - pass + __set_lyric_format(self) elif r == "4": pass elif r == "s": @@ -44,8 +43,12 @@ def settings_menu(self): def __remove_output_files(self): while True: cls_stay(self, "[设置菜单 - 删除文件]") - print("[0] 返回上级\n[1] 清除歌词文件\n[2] 清除歌曲文件\n[a] 清除所有文件") - r = rinput("请选择:") # 选择清除的文件格式 + r = input_menu({ + "0": "返回上级", + "1": "清除歌词文件", + "2": "清除歌曲文件", + "a": "清除所有文件", + }) # 选择清除的文件格式 if r == "0": return elif r == "1": @@ -84,7 +87,7 @@ def __remove_output_files(self): def __set_lyric_path(self): cls_stay(self, "[设置菜单 - 保存路径]") print("允许使用相对路径和绝对路径,默认为\"./out/\"\n请*不要*使用反斜杠来确保通用性\n" - "当前值:%s\n请输入新的歌词保存路径:" % self.settings.lyric_path) + "当前值:%s\n留空回车取消当前设置\n请输入新的歌词保存路径:" % self.settings.lyric_path) r = cinput() if not r: input("输入为空!\n按回车继续...") @@ -107,5 +110,31 @@ def __set_lyric_path(self): def __set_lyric_format(self): - pass - + while True: + cls_stay(self, f"[设置菜单 - 文件名格式]\n{Fore.LIGHTCYAN_EX}当前格式: ", end="") + if self.settings.lyric_format == "%(name)s": + print(f"{Fore.GREEN}曲名", end="") + else: + print(Fore.GREEN + self.settings.lyric_format % {"name": "曲名", "artists": "歌手名"}, end="") + print(".xxx") + r = input_menu({ + "0": "返回上级", + "1": "%(name)s - %(artists)s" % {"name": "曲名", "artists": "歌手名"}, + "2": "%(artists)s - %(name)s" % {"name": "曲名", "artists": "歌手名"}, + "3": "%(name)s" % {"name": "曲名", "artists": "歌手名"}, + }) + if r == "0": + return + elif r == "1": + self.settings.lyric_format = "%(name)s - %(artists)s" + break + elif r == "2": + self.settings.lyric_format = "%(artists)s - %(name)s" + break + elif r == "3": + self.settings.lyric_format = "%(name)s" + break + else: + input("输入无效!\n按回车继续...") + input("修改成功! \n按回车返回...") + return diff --git a/modules/utils/clear_screen.py b/modules/utils/clear_screen.py index b9585e6..6b375c7 100644 --- a/modules/utils/clear_screen.py +++ b/modules/utils/clear_screen.py @@ -13,8 +13,8 @@ def clear(): os.system("clear") -def cls_stay(self, custom=""): +def cls_stay(self, custom="", *args, **kwargs): """保留版本号清除屏幕""" clear() print(f"{Fore.YELLOW}[{Fore.GREEN}NeteaseMusicLyricDownloader{Fore.YELLOW}] {Fore.LIGHTBLACK_EX}{self.version}") - print(Fore.LIGHTMAGENTA_EX+custom) + print(Fore.LIGHTMAGENTA_EX+custom, *args, **kwargs) diff --git a/modules/utils/dump.py b/modules/utils/dump.py index 0662e32..95d26f2 100644 --- a/modules/utils/dump.py +++ b/modules/utils/dump.py @@ -90,7 +90,8 @@ def load_and_decrypt_from_ncm(file_path, target_dir, out_format) -> dict | str: # media data if meta_length: - output_path = os.path.join(target_dir, regular_filename(out_format % {"name": meta_data["musicName"], "artists": "".join( + output_path = os.path.join(target_dir, regular_filename(out_format % {"name": meta_data["musicName"], + "artists": "".join( [x[0]+"," for x in meta_data["artist"]] )[:-1]} + "." + meta_data["format"])) else: diff --git a/modules/utils/prints.py b/modules/utils/prints.py index cf0d5ed..b20f03c 100644 --- a/modules/utils/prints.py +++ b/modules/utils/prints.py @@ -1,7 +1,9 @@ -"""该程序的自述信息,调用即输出""" -from modules.utils.clear_screen import clear +"""有关打印的函数""" from colorama import Fore +from modules.utils.clear_screen import clear +from modules.utils.inputs import rinput + def print_info(self): """调用即输出,无返回值""" @@ -25,6 +27,17 @@ def print_info(self): def print_menu(menu: dict): - """传入一个字典, 格式为 {"需要输入的字符": "功能描述", ...}""" + """传入一个字典, 格式为 {"需要输入的字符": "功能描述", ...} + 将会按照以下格式打印: + [字符1] 功能描述1 + [字符2] 功能描述2 + ...""" for k, v in menu.items(): - print(f"{Fore.LIGHTBLUE_EX}[{k}] {Fore.LIGHTWHITE_EX}{v}") \ No newline at end of file + print(f"{Fore.LIGHTBLUE_EX}[{k}] {Fore.RESET}{v}") + + +def input_menu(menu: dict): + """传入一个字典, 格式为 {"需要输入的字符": "功能描述", ...} + 在 print_menu 末尾添加'请选择: '字样并要求输入, 使用rinput获取输入""" + print_menu(menu) + return rinput("请选择: ")