Add new function!!!

This commit is contained in:
1826013250 2022-07-20 13:15:39 +08:00 committed by GitHub
parent 9336133002
commit 8cabe1a58a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 149 additions and 48 deletions

View File

@ -50,59 +50,71 @@ def get_song_info_raw(types: list, id: str):
return need return need
def get_song_lyric(id: str | int, path: str): def get_song_lyric(id: str | int | dict, path: str, allinfo: bool = False):
"""获取歌词 """获取歌词
``id`` 提供一个歌曲id ``id`` 提供一个歌曲id
``path`` 提供歌曲下载的路径""" ``path`` 提供歌曲下载的路径
sinfo = get_song_info_raw(["name", "artists"], id) ``allinfo`` 若此项为 True ,则提供的id格式必须为 {"id": int | str, "name": str, "artists": [[str, ...], ...]} (dict)"""
if sinfo == "dl_err_connection": # 处理各式各样的事件 if allinfo:
return "dl_err_connection" sinfo = id
elif sinfo == "song_nf": id = id["id"]
return "song_nf" else:
else: # 整理歌曲数据,获取歌词 sinfo = get_song_info_raw(["name", "artists"], id)
artists = "" if sinfo == "dl_err_connection": # 处理各式各样的事件
return "dl_err_connection"
elif sinfo == "song_nf":
return "song_nf"
# 整理歌曲数据,获取歌词
artists = ""
if allinfo:
for i in sinfo["artists"]:
artists += f"{i[0]},"
else:
for i in sinfo["artists"]: for i in sinfo["artists"]:
artists += f"{i['name']}," artists += f"{i['name']},"
artists = artists[:-1] artists = artists[:-1]
name = sinfo["name"] name = sinfo["name"]
replaces = { # 处理非法字符所用的替换字典(根据网易云下载的文件分析得到) replaces = { # 处理非法字符所用的替换字典(根据网易云下载的文件分析得到)
"|": "", "|": "",
":": "", ":": "",
"<": "", "<": "",
">": "", ">": "",
"?": "", "?": "",
"/": "", "/": "",
"\\": "", "\\": "",
"*": "", "*": "",
'"': "" '"': ""
} }
for k, v in replaces.items(): for k, v in replaces.items():
name = name.replace(k, v) name = name.replace(k, v)
print(f"歌曲:{name} - {artists}") print(f"歌曲:{name} - {artists}")
filename = f"{name} - {artists}.lrc" filename = f"{name} - {artists}.lrc"
try: try:
response = post(f"http://music.163.com/api/song/media?id={id}") response = post(f"http://music.163.com/api/song/media?id={id}")
except ConnectionError: except ConnectionError:
return "dl_err_connection" return "dl_err_connection"
else: else:
info = loads(response.text) info = loads(response.text)
if info["code"] == 406: # 此处与上方一样,防止因为请求限制而跳过下载 if info["code"] == 406: # 此处与上方一样,防止因为请求限制而跳过下载
result = wait_retry() result = wait_retry()
if result == "continue": if result == "continue":
pass pass
elif result == "dl_err_connection": elif result == "dl_err_connection":
return "dl_err_connection" return "dl_err_connection"
else: else:
raise Exception("Unknown exception...") raise Exception("Unknown exception...")
tmp = loads(response.text) tmp = loads(response.text)
if tmp.get("nolyric") or not tmp.get('lyric'): if tmp.get("nolyric") or not tmp.get('lyric'):
print("这首歌没有歌词,跳过...") print("这首歌没有歌词,跳过...")
else: return
with open(f"{path}{filename}", "w", encoding="utf-8") as f: else:
f.write(tmp["lyric"]) with open(f"{path}{filename}", "w", encoding="utf-8") as f:
print(f"歌词下载完成!被保存在{path}{filename}") f.write(tmp["lyric"])
print(f"歌词下载完成!被保存在{path}{filename}")
return

View File

@ -21,7 +21,7 @@ def mdl(path: str):
except ValueError: except ValueError:
tmp = re.search("song\?id=[0-9]*", r) tmp = re.search(r"song\?id=[0-9]*", r)
if tmp: if tmp:
r = tmp.group()[8:] r = tmp.group()[8:]
else: else:

89
modules/readmp3.py Normal file
View File

@ -0,0 +1,89 @@
import json
import os
import re
from tinytag import TinyTag
from requests import post
from modules.get_song import get_song_lyric
from modules.clear_screen import clear
def load_information_from_mp3(path):
"""从音乐文件中的 Comment 字段获取 163 key 并解密返回歌曲信息"""
file = TinyTag.get(path) # 使用 TinyTag 获取歌曲信息
if file.comment:
if file.comment[:7] == "163 key":
ciphertext = file.comment[22:]
else:
return "not_support"
else:
return "not_support"
data = {
"data": ciphertext,
"type": "aes_decrypt",
"encode": "base64",
"key": "#14ljk_!\\]&0U<'(", # 感谢大佬 chenjunyu19 在 MorFans Dev 上提供的密文密钥
"digit": 128,
"mode": "ECB",
"pad": "Pkcs5Padding"
}
try:
r = post("https://www.mklab.cn/utils/handle", data=data).text[17:-2].replace("\\\"", "\"") # 十分感谢 MKLAB 网站提供的解密接口!!
except ConnectionError:
return "dl_err_connection"
if r:
return json.loads(r)
else:
return "decrypt_failed"
def get_lyric_from_folder(lyric_path: str):
clear()
path = input("请输入歌曲的保存文件夹(绝对路径):").strip().replace("\\", "/")
if not os.path.exists(path):
input("路径不存在,请检查输入...")
return
if path[-1] != "/":
path += "/"
print("正在遍历目录,请稍后...")
musics = []
fails = 0
for i in os.listdir(path): # 遍历目录,查找目标文件
match = re.match(r".*\.((mp3)|(flac))$", i)
if match:
result = load_information_from_mp3(path+match.group())
if result == "not_support":
fails += 1
print(f"文件 \"{i}\" 未包含 163 key ,跳过")
elif result == "decrypt_failed":
fails += 1
print(f"文件 \"{i}\" 内 163 key 解密失败,跳过")
elif result == "dl_err_connection":
input("获取解密结果失败!请检查网络连接是否正常,若确信自身没有问题请向作者反馈是否解密接口出现问题!")
return
else:
musics.append({"id": result['musicId'], "name": result["musicName"], "artists": result["artist"]})
# 汇报索引结果
print(f"\n索引完毕!共找到{fails+len(musics)}个目标文件\n{len(musics)}个文件已载入\n{fails}个文件失败\n")
while True:
r = input("你希望如何保存这些歌曲的歌词?\n[1]保存到刚刚输入的绝对路径中\n[2]保存到程序设定的下载路径中\n请选择: ").strip().lower()
if r == "1":
break
elif r == "2":
path = lyric_path
break
else:
try:
input("无效选择, 若取消请按 ^C ,继续请按回车")
clear()
except KeyboardInterrupt:
return
clear()
for i in range(0, len(musics)): # 根据索引结果获取歌词
print("\n进度: %d/%d" % (i + 1, len(musics)))
if get_song_lyric(musics[i], path, allinfo=True) == "dl_err_connection":
input("下载发生错误!可能是连接被拒绝!请检查网络后再试\n按回车键继续任务(该任务会被跳过)...")
input("按回车键返回...")
return