Settings: Filename Format Set
and small changes to follow PEP8 code style change default README to Chinese
This commit is contained in:
parent
feb68498dc
commit
91f568e18d
49
README.md
49
README.md
@ -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...
|
|
||||||
|
36
README_cn.md
36
README_cn.md
@ -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
40
README_en.md
Normal 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...
|
@ -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()
|
||||||
|
@ -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()
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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:
|
||||||
|
@ -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("请选择: ")
|
||||||
|
Loading…
Reference in New Issue
Block a user