23 Commits

Author SHA1 Message Date
240f380026 refactor(NFLmusic): 重构音乐搜索和播放功能
- 移除酷我音乐、酷狗音乐和聚合搜索支持
- 更新网易云音乐API接口和数据结构
- 更新QQ音乐歌词获取方式
- 修改API请求参数和响应数据解析逻辑
- 统一错误处理和异常捕获机制
- 更新版本号从4.3.5到4.3.6
2026-01-31 21:15:50 +08:00
4e55f0521f fix(core): 修复音乐搜索结果为空的问题
- 更新版本号从 v4.3.5 到 v4.3.6
- 修复了音乐搜索功能返回空结果的问题
- 更新了最新更新日志的时间戳
2026-01-31 21:15:38 +08:00
f95335e39f refactor(ifm_json): 更新音乐API配置和音质选项
- 替换了QQ音乐API端点从sdkapi.hhlqilongzhu.cn到oiapi.net
- 替换了网易云音乐API端点从sdkapi.hhlqilongzhu.cn到oiapi.net
- 移除了酷我、酷狗和聚合音乐API支持
- 更新了音质选项名称,使用更诗意的中文描述
- 简化了音质等级配置,统一了API数据结构
- 移除了不再使用的音质选项配置项
2026-01-31 21:15:28 +08:00
3ac2c59dcd chore(version): 更新版本号至4.3.6并修改下载链接
- 将版本号从4.3.5更新为4.3.6
- 更新安装包下载链接地址
- 保持更新检查接口URL不变
2026-01-31 21:15:15 +08:00
5189898b6b feat(test): 实现音频文件下载功能
- 替换 os 模块为 requests 库
- 添加音频文件 URL 和请求头配置
- 实现获取文件总长度的功能
- 移除本地音频文件路径和系统调用
- 添加网络请求相关依赖和参数设置
2025-12-20 20:31:22 +08:00
76392863ad fix(download): 修复音乐下载功能并更新版本号
- 移除未使用的total_ordering导入
- 添加全局headers变量声明
- 在requests.get中添加headers参数
- 更新应用版本号从4.3.4到4.3.5
- 添加HTTP请求头信息以改善兼容性
2025-12-20 20:31:13 +08:00
64bba311ae chore(ide): 更新IDE模块配置排除文件夹
- 在IDEA模块配置中添加 .venv1 文件夹排除规则
- 保持与现有虚拟环境文件夹排除配置一致
- 避免IDE索引不必要的虚拟环境文件
2025-12-20 20:31:00 +08:00
d94318b3b9 fix(kuwo): 修复酷我音乐源下载空文件问题
- 解决了从酷我音乐源下载的音乐文件为空的问题
- 优化了下载逻辑以确保文件完整性
- 添加了对下载失败情况的日志记录
- 更新了相关测试用例以覆盖此场景
2025-12-20 20:30:49 +08:00
dad7043db7 chore(version): 更新版本号和下载链接
- 将版本号从 4.3.4 更新为 4.3.5
- 更新主程序下载链接至 v4.3.5 版本
- 更新安装包下载链接至 v4.3.5 版本
2025-12-20 20:30:40 +08:00
bbe244e125 fix(NFLmusic):优化歌词时间戳格式转换与异常处理
- 新增正则表达式匹配并转换 [mm:ss] 时间戳为 [mm:ss.0] 格式
- 在下载酷狗歌词时增加时间戳标准化处理逻辑
- 打印原始歌词内容以便调试
- 修改异常捕获方式,明确打印异常类型和信息- 更新版本号从4.3.3 到4.3.4
2025-10-03 17:07:50 +08:00
12a8b3714c style(lyrics): 移除多余的空行
- 删除解析歌词时不必要的空行- 保持代码整洁一致的格式
2025-10-03 17:07:35 +08:00
5ede789385 fix(download):修复聚合搜索下载的歌词无法读取问题
- 修复了聚合音乐搜索下载源的歌词解析错误
- 确保歌词文件能被正常读取和显示
-优化了下载流程中的数据处理逻辑
2025-10-03 17:07:23 +08:00
d8a03ce0e7 fix(version): 更新音乐播放器下载链接
-修正了版本信息文件中的音乐播放器下载地址
- 将旧的下载链接替换为新的直链地址
- 确保用户能够正常下载最新版本的音乐播放器
2025-10-03 17:07:15 +08:00
2967b66bf8 fix(version): 更新音乐播放器下载链接
-修正了版本信息文件中的音乐播放器下载地址
- 将旧的下载链接替换为新的直链地址
- 确保用户能够正常下载最新版本的音乐播放器
2025-10-03 16:35:13 +08:00
9a1b04d3d5 fix(NFLmusic):修复聚合搜索接口参数及数据解析问题
- 移除歌曲名中的空格替换逻辑,保留原始输入
- 增强JSON数据解析的健壮性,避免因数据结构异常导致的程序崩溃- 确保搜索目标正确传递至后续处理流程
2025-10-03 16:33:46 +08:00
99857387dc feat(music): 新增聚合音乐搜索下载源
- 添加了酷狗音乐下载源
-修复了部分已知问题- 提升了音乐搜索的准确性和下载速度
-优化了用户界面的交互体验- 增强了对不同音频格式的支持
- 改进了错误处理机制,提高稳定性
2025-10-03 16:18:49 +08:00
d1aac65f25 chore(version): 更新版本信息至4.3.3
- 将版本号从4.3.2更新到4.3.3
- 更新了主程序更新包的下载链接
- 更新了完整安装包的下载链接至新版本
2025-10-03 16:18:38 +08:00
08da529d84 feat(NFLmusic): 添加聚合搜索功能支持- 新增 JUHE 搜索选项,支持通过聚合接口获取音乐数据
- 调整歌词下载逻辑以适配新接口返回结构
- 修改歌曲列表展示逻辑,兼容不同平台的数据字段
- 更新版本号至4.3.3
- 在搜索菜单中增加“聚合搜索”入口并映射为 JUHE 标识
2025-10-03 16:16:23 +08:00
a47c00e991 chore(env): 更新Python SDK配置
- 调整项目模块配置中的Python SDK引用名称
- 移除虚拟环境目录的重复排除配置
- 统一Python运行环境的命名规范
2025-10-03 16:16:13 +08:00
8aae403c86 chore(project): 更新项目JDK配置- 将项目JDK名称从"Python 3.6 (NFLmusic)"简化为"Python3.6"- 保持JDK类型为"Python SDK"不变
- 确保项目根管理器版本号仍为2
2025-10-03 16:16:00 +08:00
938f63a073 feat(config): 更新音乐源配置并调整默认选择
- 添加聚合音乐源及其默认音质配置
- 将默认音乐源从酷我调整为QQ音乐
- 更新音乐源配置结构以支持新选项
2025-10-03 16:15:52 +08:00
84ece943ee fix(KUGOU): 修复酷狗音乐搜索时的空格问题
- 在发送请求前,移除歌曲名称中的空格
- 提高了酷狗音乐搜索的准确性
2025-09-06 22:28:40 +08:00
5a6e7651ed fix(version_info): 更新 NFLmusic v4.3.2 版本下载链接
- 修改了版本信息文件中的下载链接地址
-从旧链接 http://pan.nanfengling.cn/f/pvdsV/NFLmusicv4.3.2.exe
- 更新为新链接 http://pan.nanfengling.cn/f/gj0UE/NFLmusicv4.3.2.exe
2025-09-06 22:28:32 +08:00
8 changed files with 78 additions and 117 deletions

3
.idea/NFLmusic.iml generated
View File

@ -4,8 +4,9 @@
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.venv" /> <excludeFolder url="file://$MODULE_DIR$/.venv" />
<excludeFolder url="file://$MODULE_DIR$/venv" /> <excludeFolder url="file://$MODULE_DIR$/venv" />
<excludeFolder url="file://$MODULE_DIR$/.venv1" />
</content> </content>
<orderEntry type="jdk" jdkName="Python 3.6 (NFLmusic)" jdkType="Python SDK" /> <orderEntry type="jdk" jdkName="Python 3.6" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
</component> </component>
</module> </module>

2
.idea/misc.xml generated
View File

@ -3,5 +3,5 @@
<component name="Black"> <component name="Black">
<option name="sdkName" value="Python 3.6 (NFLmusic)" /> <option name="sdkName" value="Python 3.6 (NFLmusic)" />
</component> </component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6 (NFLmusic)" project-jdk-type="Python SDK" /> <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6" project-jdk-type="Python SDK" />
</project> </project>

View File

@ -1,5 +1,4 @@
import time import time
from functools import total_ordering
from tkinter import * from tkinter import *
import threading import threading
import pygame import pygame
@ -126,7 +125,7 @@ def download_check(*value):
def download_music(song_name, choose): def download_music(song_name, choose):
global progressbar, downloading global progressbar, downloading, headers
def update_progressbar(): def update_progressbar():
while True: while True:
@ -141,68 +140,38 @@ def download_music(song_name, choose):
style='success.Striped.Horizontal.TProgressbar') style='success.Striped.Horizontal.TProgressbar')
progressbar.place(x=10, y=300) progressbar.place(x=10, y=300)
br = br_dict[var.get()] br = br_dict[var.get()]
if choice == "KUWO": if choice == "WANGYIYUN":
resp = requests.get(f"{url}?msg={song_name}&n={choose}&br={br}&num=60&type=json&key=Dragon5B887C2DC41AD03C93F06BAF4B7888C3") resp = requests.get(f"{url}?name={song_name}&n={choose}&br={br}&limit=60&type=json&key=oiapi-e3329f47-ccbc-2279-14b6-eabd4c7286ac")
resp.close() resp.close()
id = resp.json()["link"].rsplit("/", 1)[1] songid = resp.json()["data"]["id"]
try: try:
resp_lrc = requests.get(f"http://m.kuwo.cn/newh5/singles/songinfoandlrc?musicId={id}") resp_lrc = requests.get(f"https://music.163.com/api/song/lyric?id={songid}&lv=-1&kv=-1&tv=-1")
resp_lrc.close()
lrc = ""
lrclist = resp_lrc.json()["data"]["lrclist"]
for i in lrclist:
total_time = i["time"]
min = float(total_time) // 60
sec = float(total_time) % 60
lrc += f'[{int(min)}:{sec}]{i["lineLyric"]}\n'
except Exception as e:
print(f"download_kw_lrc: {e}")
lrc = ""
music_name = resp.json()["song_name"]
singer = resp.json()["song_singer"]
music_url = resp.json()["flac_url"]
elif choice == "WANGYIYUN":
resp = requests.get(f"{url}?gm={song_name}&n={choose}&br={br}&num=60&type=json&key=Dragon5B887C2DC41AD03C93F06BAF4B7888C3")
resp.close()
id = resp.json()["link"].rsplit("=", 1)[1]
try:
resp_lrc = requests.get(f"https://music.163.com/api/song/lyric?id={id}&lv=-1&kv=-1&tv=-1")
resp_lrc.close() resp_lrc.close()
lrc = resp_lrc.json()["lrc"]["lyric"] lrc = resp_lrc.json()["lrc"]["lyric"]
except Exception as e: except Exception as e:
print(f"download_wyy_lrc: {e}") print(f"download_wyy_lrc: {e}")
lrc = "" lrc = ""
music_name = resp.json()["title"] music_name = resp.json()["data"]["name"]
singer = resp.json()["singer"] singer = resp.json()["data"]["singers"][0]["name"]
music_url = resp.json()["music_url"] music_url = resp.json()["data"]["url"]
elif choice == "QQ": elif choice == "QQ":
resp = requests.get(f"{url}?msg={song_name}&n={choose}&num=60&type=json&br={br}&key=Dragon5B887C2DC41AD03C93F06BAF4B7888C3") resp = requests.get(f"{url}?msg={song_name}&n={choose}&limit=60&type=json&br={br}&key=oiapi-e3329f47-ccbc-2279-14b6-eabd4c7286ac")
resp.close() resp.close()
songid = resp.json()["data"]["songid"]
resp1 = requests.get(f"https://oiapi.net/api/QQMusicLyric?id={songid}")
try: try:
lrc = resp.json()["data"]["lyric"] lrc = resp1.json()["message"]
except Exception as e: except Exception as e:
print(f"download_qq_lrc: {e}") print(f"download_qq_lrc: {e}")
lrc = "" lrc = ""
music_name = resp.json()["data"]["song_name"] music_name = resp.json()["data"]["song"]
singer = resp.json()["data"]["song_singer"] singer = resp.json()["data"]["singer"]
music_url = resp.json()["data"]["music_url"] music_url = resp.json()["data"]["music"]
elif choice == "KUGOU":
song_name = song_name.replace(" ", "")
resp = requests.get(f"{url}?msg={song_name}&n={choose}&num=60&type=json&br={br}&key=Dragon5B887C2DC41AD03C93F06BAF4B7888C3")
resp.close()
try:
lrc = resp.json()["lyrics"]
except Exception as e:
print(f"download_kg_lrc: {e}")
lrc = ""
music_name = resp.json()["title"]
singer = resp.json()["singer"]
music_url = resp.json()["music_url"]
else: else:
lrc = "" lrc = ""
lrc = lrc.replace("\\n", "\n") lrc = lrc.replace("\\n", "\n")
print("请求api:", url) print("请求api:", url)
response = requests.get(music_url, stream=True) response = requests.get(music_url, stream=True, headers=headers)
print("下载直链:", music_url) print("下载直链:", music_url)
formated = music_url.split("?")[0].rsplit(".", 1)[1] formated = music_url.split("?")[0].rsplit(".", 1)[1]
if formated not in ["m4a", "mp3", "ogg", "flac"]: if formated not in ["m4a", "mp3", "ogg", "flac"]:
@ -261,7 +230,8 @@ def download_music(song_name, choose):
{"_singer_": f"{singer}", "_music_": f"{music_name}"})) {"_singer_": f"{singer}", "_music_": f"{music_name}"}))
downloading = False downloading = False
except KeyError: except KeyError as e:
print(e, type(e))
downloading = False downloading = False
progressbar.destroy() progressbar.destroy()
if song_name == "": if song_name == "":
@ -304,35 +274,23 @@ def get_data_without_blocking(song_name):
try: try:
button0["state"] = "disabled" button0["state"] = "disabled"
songlist.delete(*songlist.get_children()) songlist.delete(*songlist.get_children())
if choice == "KUWO": if choice == "WANGYIYUN":
url1 = f"{url}?msg={song_name}&num=60&type=json&key=Dragon5B887C2DC41AD03C93F06BAF4B7888C3" url1 = f"{url}?name={song_name}&limit=60&type=json&key=oiapi-e3329f47-ccbc-2279-14b6-eabd4c7286ac"
elif choice == "WANGYIYUN":
url1 = f"{url}?gm={song_name}&num=60&type=json&key=Dragon5B887C2DC41AD03C93F06BAF4B7888C3"
elif choice == "QQ": elif choice == "QQ":
url1 = f"{url}?msg={song_name}&num=60&type=json&key=Dragon5B887C2DC41AD03C93F06BAF4B7888C3" url1 = f"{url}?msg={song_name}&limit=60&type=json&key=oiapi-e3329f47-ccbc-2279-14b6-eabd4c7286ac"
elif choice == "KUGOU":
url1 = f"{url}?msg={song_name}&num=60&type=json&key=Dragon5B887C2DC41AD03C93F06BAF4B7888C3"
resp = requests.get(url1) resp = requests.get(url1)
jsondata = resp.json()["data"] jsondata = resp.json()
resp.close() resp.close()
last_search_target = song_name last_search_target = song_name
for index in range(len(jsondata)): for index in range(len(jsondata["data"] if isinstance(jsondata, dict) else jsondata)):
if choice == "KUWO": if choice == "WANGYIYUN":
full_name = jsondata[index]["songname"] full_name = jsondata["data"][index]["name"]
artist = jsondata[index]["singer"] artist = jsondata["data"][index]["singers"][0]["name"]
album = jsondata[index]["song_rid"] album = jsondata["data"][index]["id"]
elif choice == "WANGYIYUN":
full_name = jsondata[index]["title"]
artist = jsondata[index]["singer"]
album = jsondata[index]["songid"]
elif choice == "QQ": elif choice == "QQ":
full_name = jsondata[index]["song_title"] full_name = jsondata["data"][index]["song"]
artist = jsondata[index]["song_singer"] artist = jsondata["data"][index]["singer"]
album = "" album = jsondata["data"][index]["songid"]
elif choice == "KUGOU":
full_name = jsondata[index]["title"]
artist = jsondata[index]["singer"]
album = ""
songlist.insert("", "end", values=(full_name, artist, album)) songlist.insert("", "end", values=(full_name, artist, album))
except requests.exceptions.JSONDecodeError: except requests.exceptions.JSONDecodeError:
resp_text = resp.text resp_text = resp.text
@ -465,8 +423,8 @@ def playsound(*event):
playmusic(abs_path) playmusic(abs_path)
try: try:
lyric = lyrics.load_lyrics(f"{path}/{music_file_without_endswith}.lrc") lyric = lyrics.load_lyrics(f"{path}/{music_file_without_endswith}.lrc")
except: except Exception as e:
pass print(type(e), e)
def playmusic(music_path): def playmusic(music_path):
@ -1296,7 +1254,7 @@ def search_local_song():
time.sleep(1) time.sleep(1)
version = "4.3.2" version = "4.3.6"
poem = "" poem = ""
appdata = os.getenv("APPDATA") appdata = os.getenv("APPDATA")
make_resource() make_resource()
@ -1401,6 +1359,14 @@ playingmode_dict = {
1: "rand", 1: "rand",
2: "sequ" 2: "sequ"
} }
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5',
'Accept-Encoding': 'gzip, deflate',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
}
if path == "./music": if path == "./music":
if os.path.exists("./music"): if os.path.exists("./music"):
@ -1657,10 +1623,8 @@ themeLabel.place(x=10, y=25)
# 基本设置 # 基本设置
repo_dict = { repo_dict = {
"酷我音乐": "KUWO",
"QQ音乐": "QQ", "QQ音乐": "QQ",
"网易云音乐": "WANGYIYUN", "网易云音乐": "WANGYIYUN",
"酷狗音乐": "KUGOU",
} }
repo_dict_reverse = {} repo_dict_reverse = {}
for repo in repo_dict: for repo in repo_dict:

View File

@ -3,47 +3,33 @@ usercache = {
"theme": "sandstone", "theme": "sandstone",
"path": "./music", "path": "./music",
"br": { "br": {
"QQ": "HQ高音质", "QQ": "余韵绕梁",
"KUWO": "高品音质", "WANGYIYUN": "默认音质",
"WANGYIYUN": "极高音质",
"KUGOU": "高品音质"
}, },
"choice": "KUWO", "choice": "QQ",
"auto_update": True, "auto_update": True,
"playing_mode": 0, "playing_mode": 0,
"auto_play": False "auto_play": False
} }
api_data = { api_data = {
"QQ": ["https://sdkapi.hhlqilongzhu.cn/api/QQmusic/", "QQ": ["https://oiapi.net/api/QQ_Music",
{ {
"SQ无损": 1, "天籁浑成": 1,
"HQ高音质": 2, "珠玉清华": 3,
"标准音质": 10 "余韵绕梁": 4,
"清越穿云": 2,
"幽微入化": 5,
"淳和致厚": 6,
"浊滞暗哑": 7,
"呕哑嘲哳": 8
} }
], ],
"KUWO": ["https://sdkapi.hhlqilongzhu.cn/api/dgMusic_kuwo/", "WANGYIYUN": ["https://oiapi.net/api/Music_163",
{
"无损音质": 1,
"高品音质": 2
}
],
"WANGYIYUN": ["https://sdkapi.hhlqilongzhu.cn/api/dgMusic_wyy",
{ {
"标准音质": 1, "默认音质": 1
"极高音质": 2,
"无损音质": 3,
"Hi-Res音质": 4,
"高清环绕声" :5,
"沉浸环绕声": 6,
"超清母带": 7
} }
], ]
"KUGOU": ["https://sdkapi.hhlqilongzhu.cn/api/dgMusic_kugou/",
{
"高品音质": 1
}
]
} }

View File

@ -13,7 +13,6 @@ def load_lyrics(file):
timestamp = f'{minutes:02}:{seconds:02}' timestamp = f'{minutes:02}:{seconds:02}'
text = match.group(3) text = match.group(3)
lyrics[timestamp] = text lyrics[timestamp] = text
return lyrics return lyrics

18
test.py
View File

@ -1,4 +1,16 @@
import os import requests
audio_file = "C:/Users/Administrator/Music/国风堂#哦漏 - 知我.mp3" url = "https://er-sycdn.kuwo.cn/5a1fdd7e1178a867af57c6b0ba576889/69468dc3/resource/30106/trackmedia/F000000bYDlc2XxKLs.flac"
os.startfile(audio_file)
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5',
'Accept-Encoding': 'gzip, deflate',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
}
total_length = int(requests.get(url, stream=True, headers=headers).headers.get('content-length'))
print(total_length)

View File

@ -1,3 +1,3 @@
4.3.2 4.3.6
http://pan.nanfengling.cn/f/4Qc2/update.exe http://pan.nanfengling.cn/f/4Qc2/update.exe
http://pan.nanfengling.cn/f/pvdsV/NFLmusicv4.3.2.exe http://pan.nanfengling.cn/f/qVZTK/NFLmusicv4.3.6.exe

View File

@ -1,6 +1,5 @@
v4.3.2 - 2025.9.6 v4.3.6 - 2025.01.31
新增酷狗音乐下载源 修复了音乐搜索结果为空的问题
修复部分已知问题
本产品是南凤科技旗下的音乐下载器 本产品是南凤科技旗下的音乐下载器
旨在提升用户体验, 旨在提升用户体验,