Settings: Filename Format Set

and small changes to follow PEP8 code style

change default README to Chinese
This commit is contained in:
1826013250 2023-06-24 14:01:32 +08:00
parent feb68498dc
commit 91f568e18d
10 changed files with 132 additions and 81 deletions

View File

@ -1,40 +1,39 @@
NeteaseMusicLyricDownloader # NeteaseMusicLyricDownloader
=========================== **简体中文**|[English](https://github.com/1826013250/NeteaseMusicLyricDownloader/README_en.md)
**English**|[简体中文](./README_cn.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? 网易云音乐提供给我们了一个获取歌词的API ~~然后我就做了这个程序(~~
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... ## 安装
首先你需要一个Python环境(要求版本>=3.10,因为使用了3.10python的新特性)
## Installation 然后把整个项目clone下来安装依赖项目
First, you need a python(>=3.10) environment
Second, clone the entire project and install packages with the command below:
```commandline ```commandline
python3 -m pip install -r requirements.txt 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...

View File

@ -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或者分享链接或者已经下好的歌曲路径然后这破玩意就会自动下载歌词
## 后续有啥功能?
_~~我不造,要不你来写罢(~~_
## 其他要说的
这就一简简单单普普通通的程序
我可能也没有太多的精力去写这么个~~破玩意~~...

40
README_en.md Normal file
View File

@ -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...

View File

@ -59,11 +59,16 @@ def get_song_info_raw(types: list, identify: str, bar: CompactBar = None):
return need 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 ``identify`` 提供一个歌曲id
``path`` 提供歌曲下载的路径 ``path`` 提供歌曲下载的路径
``lyric_format`` 提供歌词保存的格式
``allinfo`` 若此项为 True ,则提供的identify格式必须为存储在网易云下载文件中meta_data的格式 ``allinfo`` 若此项为 True ,则提供的identify格式必须为存储在网易云下载文件中meta_data的格式
``bar`` 若获取歌词时下方有进度条, 则应当传入此参数""" ``bar`` 若获取歌词时下方有进度条, 则应当传入此参数"""
if allinfo: if allinfo:
@ -96,7 +101,7 @@ def get_song_lyric(identify: str | int | dict, path: str, allinfo: bool = False,
artists = regular_filename(artists) artists = regular_filename(artists)
bprint(Fore.YELLOW + "\t-> 歌曲:" + Style.RESET_ALL + f"{name} - {artists}", bar) 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: try:
info = post(f"https://music.163.com/api/song/media?id={identify}").json() info = post(f"https://music.163.com/api/song/media?id={identify}").json()

View File

@ -217,7 +217,7 @@ def get_lyric_from_folder(self):
with CompactArrowBar(f"进度: %(index){len(str(len(musics)))}d/%(max)d", with CompactArrowBar(f"进度: %(index){len(str(len(musics)))}d/%(max)d",
suffix="", max=len(musics), color="yellow", width=9999) as bar: suffix="", max=len(musics), color="yellow", width=9999) as bar:
for i in range(0, len(musics)): # 根据索引结果获取歌词 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按回车键继续任务(该任务会被跳过)...") bar.print_onto_bar(Fore.RED + "下载发生错误!可能是连接被拒绝!请检查网络后再试\n按回车键继续任务(该任务会被跳过)...")
input() input()
bar.next() bar.next()

View File

@ -34,7 +34,7 @@ def mdl(self):
with CompactArrowBar(f"进度: %(index){len(str(len(ids)))}d/%(max)d", with CompactArrowBar(f"进度: %(index){len(str(len(ids)))}d/%(max)d",
suffix="", max=len(ids), color="yellow", width=9999) as bar: suffix="", max=len(ids), color="yellow", width=9999) as bar:
for i in range(0, len(ids)): 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": if r == "dl_err_connection":
bar.print_onto_bar(Fore.RED + "下载发生错误!可能是连接被拒绝!请检查网络后再试\n按回车键继续任务(该任务会被跳过)...") bar.print_onto_bar(Fore.RED + "下载发生错误!可能是连接被拒绝!请检查网络后再试\n按回车键继续任务(该任务会被跳过)...")
input() input()

View File

@ -5,7 +5,7 @@ from colorama import Fore
from modules.utils.clear_screen import cls_stay from modules.utils.clear_screen import cls_stay
from modules.utils.inputs import rinput, cinput from modules.utils.inputs import rinput, cinput
from modules.functions.settings.save_load_settings import save_settings 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): def settings_menu(self):
@ -16,7 +16,7 @@ def settings_menu(self):
cls_stay(self, f"[设置菜单] " cls_stay(self, f"[设置菜单] "
f"{Fore.LIGHTCYAN_EX}自动保存: " f"{Fore.LIGHTCYAN_EX}自动保存: "
f"{({True: f'{Fore.GREEN}', False: f'{Fore.RED}'}[self.settings.auto_save])}") f"{({True: f'{Fore.GREEN}', False: f'{Fore.RED}'}[self.settings.auto_save])}")
print_menu({ r = input_menu({
"0": "返回上级菜单", "0": "返回上级菜单",
"1": "歌曲保存路径", "1": "歌曲保存路径",
"2": "清空输出文件夹内的内容", "2": "清空输出文件夹内的内容",
@ -24,7 +24,6 @@ def settings_menu(self):
"4": "部分动态效果", "4": "部分动态效果",
"s": "切换设置自动保存" "s": "切换设置自动保存"
}) })
r = rinput("请选择:")
if r == "0": if r == "0":
return return
elif r == "1": elif r == "1":
@ -32,7 +31,7 @@ def settings_menu(self):
elif r == "2": elif r == "2":
__remove_output_files(self) __remove_output_files(self)
elif r == "3": elif r == "3":
pass __set_lyric_format(self)
elif r == "4": elif r == "4":
pass pass
elif r == "s": elif r == "s":
@ -44,8 +43,12 @@ def settings_menu(self):
def __remove_output_files(self): def __remove_output_files(self):
while True: while True:
cls_stay(self, "[设置菜单 - 删除文件]") cls_stay(self, "[设置菜单 - 删除文件]")
print("[0] 返回上级\n[1] 清除歌词文件\n[2] 清除歌曲文件\n[a] 清除所有文件") r = input_menu({
r = rinput("请选择:") # 选择清除的文件格式 "0": "返回上级",
"1": "清除歌词文件",
"2": "清除歌曲文件",
"a": "清除所有文件",
}) # 选择清除的文件格式
if r == "0": if r == "0":
return return
elif r == "1": elif r == "1":
@ -84,7 +87,7 @@ def __remove_output_files(self):
def __set_lyric_path(self): def __set_lyric_path(self):
cls_stay(self, "[设置菜单 - 保存路径]") cls_stay(self, "[设置菜单 - 保存路径]")
print("允许使用相对路径和绝对路径,默认为\"./out/\"\n请*不要*使用反斜杠来确保通用性\n" print("允许使用相对路径和绝对路径,默认为\"./out/\"\n请*不要*使用反斜杠来确保通用性\n"
"当前值:%s\n请输入新的歌词保存路径:" % self.settings.lyric_path) "当前值:%s\n留空回车取消当前设置\n请输入新的歌词保存路径:" % self.settings.lyric_path)
r = cinput() r = cinput()
if not r: if not r:
input("输入为空!\n按回车继续...") input("输入为空!\n按回车继续...")
@ -107,5 +110,31 @@ def __set_lyric_path(self):
def __set_lyric_format(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

View File

@ -13,8 +13,8 @@ def clear():
os.system("clear") os.system("clear")
def cls_stay(self, custom=""): def cls_stay(self, custom="", *args, **kwargs):
"""保留版本号清除屏幕""" """保留版本号清除屏幕"""
clear() clear()
print(f"{Fore.YELLOW}[{Fore.GREEN}NeteaseMusicLyricDownloader{Fore.YELLOW}] {Fore.LIGHTBLACK_EX}{self.version}") 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)

View File

@ -90,7 +90,8 @@ def load_and_decrypt_from_ncm(file_path, target_dir, out_format) -> dict | str:
# media data # media data
if meta_length: 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"]] [x[0]+"," for x in meta_data["artist"]]
)[:-1]} + "." + meta_data["format"])) )[:-1]} + "." + meta_data["format"]))
else: else:

View File

@ -1,7 +1,9 @@
"""该程序的自述信息,调用即输出""" """有关打印的函数"""
from modules.utils.clear_screen import clear
from colorama import Fore from colorama import Fore
from modules.utils.clear_screen import clear
from modules.utils.inputs import rinput
def print_info(self): def print_info(self):
"""调用即输出,无返回值""" """调用即输出,无返回值"""
@ -25,6 +27,17 @@ def print_info(self):
def print_menu(menu: dict): def print_menu(menu: dict):
"""传入一个字典, 格式为 {"需要输入的字符": "功能描述", ...}""" """传入一个字典, 格式为 {"需要输入的字符": "功能描述", ...}
将会按照以下格式打印:
[字符1] 功能描述1
[字符2] 功能描述2
..."""
for k, v in menu.items(): for k, v in menu.items():
print(f"{Fore.LIGHTBLUE_EX}[{k}] {Fore.LIGHTWHITE_EX}{v}") print(f"{Fore.LIGHTBLUE_EX}[{k}] {Fore.RESET}{v}")
def input_menu(menu: dict):
"""传入一个字典, 格式为 {"需要输入的字符": "功能描述", ...}
print_menu 末尾添加'请选择: '字样并要求输入, 使用rinput获取输入"""
print_menu(menu)
return rinput("请选择: ")