commit 9d9b913f3a0fa6e2e779afdc746a32288b933d94 Author: Your Name Date: Sat Jun 12 23:17:23 2021 +0800 first diff --git a/icon/fly b/icon/fly new file mode 100644 index 0000000..bae6ce8 Binary files /dev/null and b/icon/fly differ diff --git a/icon/media-skip-backward.png b/icon/media-skip-backward.png new file mode 100644 index 0000000..69206f5 Binary files /dev/null and b/icon/media-skip-backward.png differ diff --git a/icon/media-skip-forward.png b/icon/media-skip-forward.png new file mode 100644 index 0000000..126edbd Binary files /dev/null and b/icon/media-skip-forward.png differ diff --git a/icon/tiny-pause.png b/icon/tiny-pause.png new file mode 100644 index 0000000..c8e7199 Binary files /dev/null and b/icon/tiny-pause.png differ diff --git a/icon/tiny-start.png b/icon/tiny-start.png new file mode 100644 index 0000000..18b6b98 Binary files /dev/null and b/icon/tiny-start.png differ diff --git a/main.py b/main.py new file mode 100644 index 0000000..16e10b0 --- /dev/null +++ b/main.py @@ -0,0 +1,878 @@ +import os +import re +import threading +import time + +import wx +import wx.adv +import wx.lib.mixins.listctrl +from pygame import mixer + +import ruijia + +user_music_folder = os.path.expanduser(r'~\Music') +DEFAULT_SETTING = { # 默认设置 + # 用户可设置 + 'bg_color': '#88fefe', + 'font_size': 13, + 'text_color': '#000000', + 'lyrics_fg_color': '#ff1122', + 'lyrics_bg_color': '#000000', + 'volume': 0.3, # 自动保存 + 'font': '宋体', + 'underline': False, + 'music_folder_type': 0, # 0表示默认目录,1表示用户音乐路径,2表示自定义路径 + 'music_folder_list': ['music_folder', user_music_folder, ''], + # 用户不可设置 + 'max_music_name_len': 30, + 'app_title': 'music_player', + } +FONT_LIST = ['黑体', '楷体', '宋体', '仿宋', 'Arial', '等线', '华文琥珀', '华文行楷', '华文新魏'] # 字体列表 +FONT_LIST = [font for font in FONT_LIST if wx.Font().SetFaceName(font)] # 字体可能会不存在 + + +def get_lyrics(lyric_path: str) -> list: + """ + 从歌词文件中读取歌词返回列表 + :param lyric_path:歌词路径str + :return:歌词列表(时间,文字)元组 + """ + lyric_row_reg = '\[[0-9]{2}:[0-9]{2}.[0-9]{2,}\]' + if os.path.exists(lyric_path): + with open(lyric_path, 'r', encoding="utf-8") as f: + content_list = [line.strip() for line in f.readlines()] # 去除每行的\n + lyrics_list = [] + for content in content_list: + while re.match(lyric_row_reg, content): # 一句歌词可能有多个时间 + lyric_time = float(content[1:3]) * 60 + float(content[4:6]) + float(content[7:9]) / 100 + lyric = content[content.rindex(']') + 1:] + lyrics_list.append((lyric_time, lyric)) + content = content[content.index(']') + 1:] + lyrics_list.sort(key=lambda x: x[0]) # 按时间排序 + return lyrics_list + else: + return [(0, '纯音乐或无歌词')] + + +def get_setting() -> dict: + """ + 从设置文件中读取设置,如不存在则使用默认设置 + :return: 设置项目的字典 + """ + if os.path.exists('setting.txt'): + with open('setting.txt', 'r', encoding='utf-8') as f: + setting_dic = eval(f.read()) + else: + setting_dic = DEFAULT_SETTING + return setting_dic + + +class RankListNotebook(wx.Notebook): + + def __init__(self, parent): + wx.Notebook.__init__(self, parent) + self.SetFont(parent.user_font) + self.text_color = parent.setting_dic['text_color'] + url_dic = { + '酷狗飙升榜': 'http://www.kugou.com/yy/rank/home/{}-6666.html', + '酷狗TOP500': 'http://www.kugou.com/yy/rank/home/{}-8888.html', + '华语新歌榜': 'http://www.kugou.com/yy/rank/home/{}-31308.html', + '酷狗雷达榜': 'https://www.kugou.com/yy/rank/home/{}-37361.html' + } + + # 进度dialog初始化 + max_ = 200*len(url_dic) + dlg = wx.ProgressDialog("处理中", "获取数据中", maximum=max_, parent=self, + style=wx.PD_AUTO_HIDE | wx.PD_CAN_ABORT | wx.PD_APP_MODAL) + count = 0 + + for name in url_dic: # 每个排行榜为一页 + page = wx.ScrolledWindow(self) + self.AddPage(page, name) # TODO 页面描述文字不可设置字体颜色 + page.SetScrollbars(10, 10, 1, 1) + + sizer = wx.BoxSizer(wx.HORIZONTAL) + page.SetSizer(sizer) + sizer.Add((200, -1), 0) # 设置榜单左方空白区域 + + column_sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(column_sizer, proportion=1) + column_sizer.Add((0, 50), 0) # 榜单上方空白 + + for i in range(50): # 进度条更新 + dlg.Update(count := count + 1) + if dlg.WasCancelled(): # 当dialog取消时退出循环 + break + + ranking_list = ruijia.main(url_dic[name]) # 从ruijia.py获取榜单 + for line in range(100): + song = str(line+1) + ranking_list[line]['song'] # 排名加上歌名——歌手 + st = wx.StaticText(page, -1, song) + st.SetFont(parent.user_font) + st.SetForegroundColour(self.text_color) + column_sizer.Add(st, 1, flag=wx.TOP, border=5) + dlg.Update(count := count + 1) # 进度条更新 + + column_sizer.Add((0, 50), 0) # 榜单下方空白 + for i in range(50): # 进度条更新 + dlg.Update(count := count + 1) + if dlg.WasCancelled(): # 当dialog取消时退出循环 + break + + dlg.Destroy() + + +class SettingPanel(wx.Panel): + + def __init__(self, parent): + wx.Panel.__init__(self, parent) + self.parent = parent + self.present_setting = parent.setting_dic # 当前(未修改)的设置 + self.unsaved_setting = parent.unsaved_setting # 修改后未保存的设置 + self.bg_color = self.present_setting['bg_color'] + self.text_color = self.present_setting['text_color'] + + # 使设置panel居中显示 + setting_sizer = wx.BoxSizer(wx.HORIZONTAL) + self.SetSizer(setting_sizer) + setting_sizer.AddStretchSpacer(1) + + self.main_panel = wx.Panel(self, size=(800, 550)) + self.main_panel.SetFont(parent.user_font) + self.main_panel.SetForegroundColour(self.text_color) + setting_sizer.Add(self.main_panel, 0, wx.ALIGN_CENTRE) + + # 标题---------------------------------------------------------------------------------------------------------- + title = wx.StaticText(self.main_panel, -1, '设置(重启后生效)') + title.SetFont(wx.Font(pointSize=23, family=wx.FONTFAMILY_DEFAULT, style=wx.FONTSTYLE_NORMAL, + weight=wx.FONTWEIGHT_NORMAL, faceName='黑体')) # title字体及颜色不可更改 + title.SetForegroundColour('#000') + # 重置按钮 + reset_button = wx.Button(self.main_panel, -1, '重置', pos=(300, 5)) + reset_button.SetForegroundColour(self.text_color) + reset_button.SetBackgroundColour(self.bg_color) + reset_button.Bind(wx.EVT_LEFT_DOWN, self.reset) + + # 歌词前景背景颜色 ------------------------------------------------------------------------------------------------ + self.box1 = wx.StaticBox(self.main_panel, -1, "歌词设置", pos=(50, 50), size=(700, 70)) + + # 歌词前景色文字及按钮 + text1 = f"歌词前景色:{self.present_setting['lyrics_fg_color']}" + self.lyrics_fg_color_text = wx.StaticText(self.box1, -1, text1, pos=(30, 30)) + self.lyrics_fg_color_text.SetForegroundColour(self.present_setting['lyrics_fg_color']) + self.lyrics_fg_color_button = wx.Button(self.box1, -1, '修改', pos=(230, 25)) + self.lyrics_fg_color_button.SetForegroundColour(self.text_color) + self.lyrics_fg_color_button.SetBackgroundColour(self.bg_color) + self.lyrics_fg_color_button.Bind(wx.EVT_LEFT_DOWN, self.change_lyrics_fg_color) + + # 歌词背景色文字及按钮 + text2 = f"歌词背景色:{self.present_setting['lyrics_bg_color']}" + self.lyrics_bg_color_text = wx.StaticText(self.box1, -1, text2, pos=(400, 30)) + self.lyrics_bg_color_text.SetForegroundColour(self.present_setting['lyrics_bg_color']) + self.lyrics_bg_color_button = wx.Button(self.box1, -1, '修改', pos=(600, 25)) + self.lyrics_bg_color_button.SetForegroundColour(self.text_color) + self.lyrics_bg_color_button.SetBackgroundColour(self.bg_color) + self.lyrics_bg_color_button.Bind(wx.EVT_LEFT_DOWN, self.change_lyrics_bg_color) + + # 界面颜色,字体设置 ---------------------------------------------------------------------------------------------- + self.box2 = wx.StaticBox(self.main_panel, -1, "界面设置", pos=(50, 145), size=(700, 150)) + + # 页面背景颜色文字及按钮 + text3 = f"页面背景色:{self.bg_color}" + self.bg_color_text = wx.StaticText(self.box2, -1, text3, pos=(30, 30)) + self.bg_color_text.SetForegroundColour(self.text_color) + self.bg_color_button = wx.Button(self.box2, -1, '修改', pos=(230, 25)) + self.bg_color_button.SetForegroundColour(self.text_color) + self.bg_color_button.SetBackgroundColour(self.bg_color) + self.bg_color_button.Bind(wx.EVT_LEFT_DOWN, self.change_bg_color) + + # 文字颜色文字及按钮 + text4 = f" 文字颜色 :{self.text_color}" + self.text_color_text = wx.StaticText(self.box2, -1, text4, pos=(400, 30)) + self.text_color_text.SetForegroundColour(self.text_color) + self.text_color_button = wx.Button(self.box2, -1, '修改', pos=(600, 25)) + self.text_color_button.SetForegroundColour(self.text_color) + self.text_color_button.SetBackgroundColour(self.bg_color) + self.text_color_button.Bind(wx.EVT_LEFT_DOWN, self.change_text_color) + + # 文字大小文字及text ctrl和spin button + self.font_size_text = wx.StaticText(self.box2, -1, '文字大小:', pos=(30, 90)) + font_size = self.present_setting['font_size'] + self.font_size = wx.TextCtrl(self.box2, -1, str(font_size), pos=(120, 85), + size=(40, -1), style=wx.TE_READONLY | wx.TE_CENTRE) + self.font_size.SetBackgroundColour(self.bg_color) + self.font_size.SetForegroundColour(self.text_color) + font_size_width = self.font_size.GetSize()[1] + self.font_size_spin = wx.SpinButton(self.box2, -1, pos=(160, 85), size=(15, font_size_width)) + self.font_size_spin.SetRange(9, 15) + self.font_size_spin.SetValue(font_size) + self.font_size_spin.Bind(wx.EVT_SPIN, self.change_font_size) + + # 文字字体combobox + self.font_name_text = wx.StaticText(self.box2, -1, '当前字体:', pos=(280, 90)) + self.font_choice = wx.ComboBox(self.box2, -1, pos=(380, 85), + size=(150, -1), choices=FONT_LIST) + self.font_choice.SetBackgroundColour(self.bg_color) + self.font_choice.SetForegroundColour(self.text_color) + self.font_choice.SetSelection(FONT_LIST.index(self.present_setting['font'])) + self.font_choice.Bind(wx.EVT_TEXT, self.change_font) + + # 是否显示下划线的checkbox + self.underline = wx.CheckBox(self.box2, -1, '下划线', pos=(600, 88)) + self.underline.SetValue(self.present_setting['underline']) + self.underline.Bind(wx.EVT_CHECKBOX, self.is_underline) + + # 播放路径设置 --------------------------------------------------------------------------------------------------- + folder_type = self.present_setting['music_folder_type'] + self.box3_text = f"歌曲路径选择({['默认路径','用户音乐目录','自定义路径'][folder_type]})" + self.box3 = wx.StaticBox(self.main_panel, -1, self.box3_text, + pos=(50, 320), size=(700, 100)) + wx.StaticText(self.box3, -1, '当前路径:', pos=(10, 70)) + + # 路径textctrl + path = os.path.abspath(self.present_setting['music_folder_list'][folder_type]) + self.path_text_ctrl = wx.TextCtrl(self.box3, -1, path, pos=(100, 65), size=(480, -1)) + self.path_text_ctrl.SetBackgroundColour(self.bg_color) + self.path_text_ctrl.SetForegroundColour(self.text_color) + + # 默认路径按钮 + self.folder_button1 = wx.Button(self.box3, -1, label="默认路径", pos=(100, 27)) + self.folder_button1.SetBackgroundColour(self.bg_color) + self.folder_button1.SetForegroundColour(self.text_color) + self.folder_button1.Bind(wx.EVT_LEFT_DOWN, self.select_path_type1) + + # 用户音乐目录按钮 + self.folder_button2 = wx.Button(self.box3, -1, label="用户音乐目录", pos=(233, 27)) + self.folder_button2.SetBackgroundColour(self.bg_color) + self.folder_button2.SetForegroundColour(self.text_color) + self.folder_button2.Bind(wx.EVT_LEFT_DOWN, self.select_path_type2) + + # 自定义路径按钮 + self.button3 = wx.Button(self.box3, -1, label="自定义路径", pos=(400, 27)) + self.button3.SetBackgroundColour(self.bg_color) + self.button3.SetForegroundColour(self.text_color) + self.button3.Bind(wx.EVT_LEFT_DOWN, self.select_path_type3) + + # 路径选择按钮(自定义路径时显示) + self.path_select_button = wx.Button(self.box3, label="选择路径", pos=(580, 27)) + self.path_select_button.SetBackgroundColour(self.bg_color) + self.path_select_button.SetForegroundColour(self.text_color) + self.path_select_button.Bind(wx.EVT_LEFT_DOWN, self.select_path) + + # 确认路径按钮(自定义路径时显示) + self.folder_confirm_button = wx.Button(self.box3, label="确认", pos=(607, 65)) + self.folder_confirm_button.SetBackgroundColour(self.bg_color) + self.folder_confirm_button.SetForegroundColour(self.text_color) + self.folder_confirm_button.Bind(wx.EVT_LEFT_DOWN, self.folder_confirm) + self.hide_show_button(folder_type == 2) # 是否显示路径选择按钮和确认路径按钮 + + setting_sizer.AddStretchSpacer(1) + + def reset(self, evt): + """ + 重置为默认设置 + """ + for i in DEFAULT_SETTING: + self.unsaved_setting[i] = DEFAULT_SETTING[i] + dlg = wx.MessageDialog(self, r'成功重置所有设置,重启后生效', '成功', wx.OK) + dlg.ShowModal() + dlg.Destroy() + + def change_lyrics_fg_color(self, evt): + """ + 修改歌词前景色 + """ + dlg = wx.ColourDialog(self) + if dlg.ShowModal() == wx.ID_OK: + color = dlg.GetColourData().GetColour().GetAsString(flags=wx.C2S_HTML_SYNTAX) + self.unsaved_setting['lyrics_fg_color'] = color + self.lyrics_fg_color_text.SetForegroundColour(color) + self.lyrics_fg_color_text.SetLabel(f'歌词前景色:{color}') + dlg.Destroy() + + def change_lyrics_bg_color(self, evt): + """ + 修改歌词背景色 + """ + dlg = wx.ColourDialog(self) + if dlg.ShowModal() == wx.ID_OK: + color = dlg.GetColourData().GetColour().GetAsString(flags=wx.C2S_HTML_SYNTAX) + self.unsaved_setting['lyrics_bg_color'] = color + self.lyrics_bg_color_text.SetForegroundColour(color) + self.lyrics_bg_color_text.SetLabel(f'歌词背景色:{color}') + dlg.Destroy() + + def change_bg_color(self, evt): + """ + 修改界面背景色 + """ + dlg = wx.ColourDialog(self) + if dlg.ShowModal() == wx.ID_OK: + color = dlg.GetColourData().GetColour().GetAsString(flags=wx.C2S_HTML_SYNTAX) + self.unsaved_setting['bg_color'] = color + self.bg_color_text.SetBackgroundColour(color) + self.bg_color_text.SetLabel(f'页面背景色:{color}') + dlg.Destroy() + + def change_text_color(self, evt): + """ + 修改文字颜色(不包括歌词) + """ + dlg = wx.ColourDialog(self) + if dlg.ShowModal() == wx.ID_OK: + color = dlg.GetColourData().GetColour().GetAsString(flags=wx.C2S_HTML_SYNTAX) + self.unsaved_setting['text_color'] = color + self.text_color_text.SetForegroundColour(color) + self.text_color_text.SetLabel(f' 文字颜色 :{color}') + dlg.Destroy() + + def change_font_size(self, evt): + """ + 修改文字大小 + """ + size = self.font_size_spin.GetValue() + self.font_size.SetLabel(str(size)) + self.unsaved_setting['font_size'] = size + + def change_font(self, evt): + """ + 修改文字字体 + """ + font_name = evt.GetEventObject().GetValue() + if font_name in FONT_LIST: + self.unsaved_setting['font'] = font_name + # font = self.parent.user_font 此方式会在后续设置中更改父类中的原字体 + font = wx.Font(self.parent.user_font) + font.SetFaceName(font_name) + self.font_name_text.SetFont(font) + self.font_choice.SetFont(font) + + def is_underline(self, evt): + """ + 修改是否显示下划线 + """ + underline = self.underline.GetValue() + # font = self.parent.user_font 此方式会在后续设置中更改父类中的原字体 + font = wx.Font(self.parent.user_font) + font.SetUnderlined(underline) + self.underline.SetFont(font) + self.unsaved_setting['underline'] = underline + + def select_path_type1(self, evt): + """ + 修改路径类型(默认路径) + """ + self.hide_show_button(0) + self.box3.SetLabel('歌曲路径选择(默认路径)') + self.box3.Refresh() + self.unsaved_setting['music_folder_type'] = 0 + folder_path = os.path.abspath('music_folder') + self.path_text_ctrl.SetLabel(folder_path) + dlg = wx.MessageDialog(self, r'成功设置路径:默认路径(.\music_folder)', '成功', wx.OK) + dlg.ShowModal() + dlg.Destroy() + + def select_path_type2(self, evt): + """ + 修改路径类型(用户音乐目录) + """ + self.hide_show_button(0) + self.box3.SetLabel('歌曲路径选择(用户音乐目录)') + self.box3.Refresh() + self.unsaved_setting['music_folder_type'] = 1 + folder_path = os.path.expanduser('~\Music') + self.path_text_ctrl.SetLabel(folder_path) + dlg = wx.MessageDialog(self, rf'成功设置路径:用户音乐目录({folder_path})', '成功', wx.OK) + dlg.ShowModal() + dlg.Destroy() + + def select_path_type3(self, evt): + """ + 修改路径类型(自定义路径)并显示选择路径及确认按钮 + """ + self.hide_show_button(1) + self.box3.SetLabel('歌曲路径选择(自定义路径)') + self.box3.Refresh() + + def hide_show_button(self, op: int): + """ + 是否显示选择路径及确认按钮及路径textctrl是否可修改 + """ + if op == 0: + self.path_select_button.Hide() + self.folder_confirm_button.Hide() + self.path_text_ctrl.SetEditable(False) + elif op == 1: + self.path_select_button.Show() + self.folder_confirm_button.Show() + self.path_text_ctrl.SetEditable(True) + + def select_path(self, evt): + """ + 选择路径将其显示在路径textctrl中 + """ + dlg = wx.DirDialog(self, "选择音乐文件夹", defaultPath=os.getcwd(), style=wx.DD_DEFAULT_STYLE) + if dlg.ShowModal() == wx.ID_OK: + path = dlg.GetPath() + self.path_text_ctrl.SetLabel(path) + dlg.Destroy() + + def folder_confirm(self, evt): + """ + 确认路径 + """ + path = self.path_text_ctrl.GetValue() + if path == 'fly': # fly + dlg = wx.Dialog(self, size=(333, 280), title='fly') + wx.adv.AnimationCtrl(dlg, -1, wx.adv.Animation(r'icon\fly')).Play() + elif os.path.exists(path): # 路径存在 + self.unsaved_setting['music_folder_list'][2] = path + dlg = wx.MessageDialog(self, '成功设置路径:'+path, '成功', wx.OK) + self.unsaved_setting['music_folder_type'] = 2 + else: # 路径不存在 + dlg = wx.MessageDialog(self, '请输入正确的路径', '错误', wx.OK | wx.ICON_ERROR) + dlg.ShowModal() + dlg.Destroy() + + +class AutoWidthListCtrl(wx.ListCtrl, wx.lib.mixins.listctrl.ListCtrlAutoWidthMixin): + + def __init__(self, parent, *args, **kw): + # 设置歌曲列表list ctrl的列随sizer的改变而自动改变宽度 + wx.ListCtrl.__init__(self, parent, *args, **kw) + wx.lib.mixins.listctrl.ListCtrlAutoWidthMixin.__init__(self) + + +class MainFrame(wx.Frame): + + def __init__(self): + self.setting_dic = get_setting() + wx.Frame.__init__(self, None, -1, self.setting_dic['app_title'], pos=(50, 50)) + self.SetSize(1280, 720) + self.SetSizeHints((1080, 600)) # 设置页面最小大小 + + self.bg_color = self.setting_dic['bg_color'] + self.font_size = self.setting_dic['font_size'] + self.SetBackgroundColour(self.bg_color) + self.play_png = wx.Image("icon/tiny-start.png", wx.BITMAP_TYPE_PNG).\ + Rescale(30, 30).ConvertToBitmap() + self.stop_png = wx.Image("icon/tiny-pause.png", wx.BITMAP_TYPE_PNG).\ + Rescale(30, 30).ConvertToBitmap() + + # 字体设置 + self.user_font = wx.Font(pointSize=self.font_size, family=wx.FONTFAMILY_DEFAULT, + style=wx.FONTSTYLE_NORMAL, weight=wx.FONTWEIGHT_NORMAL) + self.user_font.SetFaceName(self.setting_dic['font']) + self.user_font.SetUnderlined(self.setting_dic['underline']) + + # 绑定窗口关闭事件 + self.is_running = True + self.Bind(wx.EVT_CLOSE, self.close_window) + + # 从设置中读取歌曲路径并读取歌曲 + folder_type = self.setting_dic['music_folder_type'] + self.local_music_folder = self.setting_dic['music_folder_list'][folder_type] + self.local_music_name_list = [] + self.get_local_music_list() + self.lyrics_static_text_list = [] + + # 音乐播放初始化 + mixer.init() + self.volume = self.setting_dic['volume'] + self.music = mixer.music + self.music.set_volume(self.volume) + self.current_music_state = 0 # 0表示未播放,1表示播放中,2表示暂停中 + self.current_music_index = 0 + + # base_sizer将界面分为左右两部分,左侧为导航栏sizer,右侧初始为主界面 + self.base_sizer = wx.BoxSizer(wx.HORIZONTAL) + self.unsaved_setting = self.setting_dic.copy() + navi_sizer = self.draw_navigator() + self.base_sizer.Add(navi_sizer, 0, wx.EXPAND) + + self.main_interface_panel = None + self.music_list_ctrl = None + self.lyrics_panel = None + self.setting_panel = None + self.ranking_notebook = None + self.draw_main_interface() + + self.SetSizer(self.base_sizer) + self.Show() + + def draw_navigator(self): + """ + 绘制导航栏,按钮切换界面 + :return: 导航栏sizer + """ + navi_sizer = wx.BoxSizer(wx.VERTICAL) + + local_music_button = wx.Button(self, label="本地音乐", size=(200, 100)) + navi_sizer.Add(local_music_button) + local_music_button.SetFont(self.user_font) + local_music_button.SetForegroundColour(self.setting_dic['text_color']) + local_music_button.SetBackgroundColour(self.bg_color) + local_music_button.Bind(wx.EVT_LEFT_DOWN, self.main_interface_button_evt) + + navi_sizer.Add((0, 0), 1) + + ranking_button = wx.Button(self, label="排行榜", size=(200, 100)) + navi_sizer.Add(ranking_button) + ranking_button.SetFont(self.user_font) + ranking_button.SetForegroundColour(self.setting_dic['text_color']) + ranking_button.SetBackgroundColour(self.bg_color) + ranking_button.Bind(wx.EVT_LEFT_DOWN, self.ranking_button_evt) + + navi_sizer.Add((0, 0), 1) + + setting_button = wx.Button(self, label="设置", size=(200, 100)) + navi_sizer.Add(setting_button) + setting_button.SetFont(self.user_font) + setting_button.SetForegroundColour(self.setting_dic['text_color']) + setting_button.SetBackgroundColour(self.bg_color) + setting_button.Bind(wx.EVT_LEFT_DOWN, self.setting_button_evt) + + navi_sizer.Add((0, 0), 3) + return navi_sizer + + def main_interface_button_evt(self, evt): + """ + 当设置界面或排行榜界面存在时将其隐藏,在主界面未显示时显示主界面 + """ + if self.setting_panel and self.setting_panel.IsShown(): + self.setting_panel.Hide() + if self.ranking_notebook and self.ranking_notebook.IsShown(): + self.ranking_notebook.Hide() + if not self.main_interface_panel.IsShown(): + self.main_interface_panel.Show() + + def draw_main_interface(self): + """ + 绘制主界面 + """ + # 主界面panel设置了main_interface_sizer,main_interface_sizer将主界面分为上下两部分,下面部分为控制区域, + # 高度始终不变;上面部分为sizer1,大小可变,包含歌曲列表及歌词面板部分。 + self.main_interface_panel = wx.Panel(self) + self.base_sizer.Add(self.main_interface_panel, 1, wx.EXPAND) + main_interface_sizer = wx.BoxSizer(wx.VERTICAL) + self.main_interface_panel.SetSizer(main_interface_sizer) + + sizer1 = wx.BoxSizer(wx.HORIZONTAL) + main_interface_sizer.Add(sizer1, 1, wx.EXPAND) + self.get_local_music_list() + + # 歌曲列表list ctrl---------------------------------------------------------------------------------------------- + self.music_list_ctrl = AutoWidthListCtrl(self.main_interface_panel, -1, + style=wx.LC_REPORT + # | wx.LC_NO_HEADER + ) + self.music_list_ctrl.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.list_ctrl_evt) + self.music_list_ctrl.SetBackgroundColour(self.bg_color) + self.music_list_ctrl.SetFont(self.user_font) + self.music_list_ctrl.SetForegroundColour(self.setting_dic['text_color']) + # TODO: header背景颜色无法设置,若使用no header的风格则list ctrl宽度有问题 + self.music_list_ctrl.InsertColumn(0, '歌曲列表') + self.music_list_ctrl.SetHeaderAttr(wx.ItemAttr(self.setting_dic['text_color'], None, self.user_font)) + sizer1.Add(self.music_list_ctrl, 2, wx.EXPAND) + for music in self.local_music_name_list: + music_full_name = music.replace(".mp3", "") # 删除后缀 + self.music_list_ctrl.InsertItem(0, music_full_name, 0) + + # 歌词面板------------------------------------------------------------------------------------------------------- + self.lyrics_panel = wx.Panel(self.main_interface_panel) + sizer1.Add(self.lyrics_panel, 9, wx.EXPAND) + + # 控制区域------------------------------------------------------------------------------------------------------- + control_panel = wx.Panel(self.main_interface_panel) + control_sizer = wx.BoxSizer(wx.HORIZONTAL) + control_panel.SetSizer(control_sizer) + control_panel.Fit() + main_interface_sizer.Add(control_panel, 0, wx.EXPAND) + + # 上一首按钮 + last_music_png = wx.Image("icon/media-skip-backward.png", wx.BITMAP_TYPE_PNG).ConvertToBitmap() + next_music_png = wx.Image("icon/media-skip-forward.png", wx.BITMAP_TYPE_PNG).ConvertToBitmap() + last_button = wx.BitmapButton(control_panel, -1, last_music_png, size=(30, 30)) + last_button.SetToolTip('上一首音乐') + last_button.Bind(wx.EVT_LEFT_DOWN, self.play_last_music) + + # 播放暂停按钮 + if self.current_music_state == 1: + current_png = self.stop_png + else: + current_png = self.play_png + self.play_stop_button = wx.BitmapButton(control_panel, -1, current_png, size=(30, 30)) + self.play_stop_button.SetToolTip('播放/暂停音乐') + self.play_stop_button.Bind(wx.EVT_LEFT_DOWN, self.play_stop_music) + + # 下一首按钮 + next_button = wx.BitmapButton(control_panel, -1, next_music_png, size=(30, 30)) + next_button.SetToolTip('下一首音乐') + next_button.Bind(wx.EVT_LEFT_DOWN, self.play_next_music) + + control_sizer.Add(last_button, 0, wx.EXPAND | wx.ALL, border=10) + control_sizer.Add(self.play_stop_button, 0, wx.EXPAND | wx.ALL, border=10) + control_sizer.Add(next_button, 0, wx.EXPAND | wx.ALL, border=10) + + # 正在播放的歌曲名 + self.current_music_static_text = wx.StaticText(control_panel, -1, '未选择') + self.current_music_static_text.SetFont(self.user_font) + self.current_music_static_text.SetForegroundColour(self.setting_dic['text_color']) + control_sizer.Add(self.current_music_static_text, 0, wx.ALIGN_CENTER_VERTICAL, border=10) + + control_sizer.Add(0, 1, wx.EXPAND) # 增加空白 + + # 音量滑动条及当前音量大小文字 + volume_slider = wx.Slider(control_panel, -1, int(self.volume * 100), 0, 100) + volume_slider.Bind(wx.EVT_SLIDER, self.change_volume) + self.volume_text = wx.StaticText(control_panel, -1, f'音量{int(self.volume * 100)}%') + self.volume_text.SetFont(self.user_font) + self.volume_text.SetForegroundColour(self.setting_dic['text_color']) + control_sizer.Add(self.volume_text, 0, wx.ALIGN_CENTER_VERTICAL, border=10) + control_sizer.Add(volume_slider, 0, wx.EXPAND | wx.ALL, border=10) + + self.base_sizer.Layout() + + def get_local_music_list(self): + """ + 获取歌词列表 + """ + self.local_music_name_list.clear() + for local_music_file_name in os.listdir(self.local_music_folder): + if local_music_file_name.endswith(".mp3"): + self.local_music_name_list.append(local_music_file_name) + + def list_ctrl_evt(self, evt): + """ + 在歌曲列表双击时播放歌曲 + """ + self.current_music_name = evt.GetItem().GetText() + self.play_music() + + def play_stop_music(self, evt): + """ + 播放暂停按钮事件 + """ + if 1 == self.current_music_state: + self.music.pause() + self.current_music_state = 2 + self.play_stop_button.SetBitmap(self.play_png) + elif 2 == self.current_music_state: + self.music.unpause() + self.current_music_state = 1 + self.play_stop_button.SetBitmap(self.stop_png) + elif 0 == self.current_music_state: + self.current_music_name = self.local_music_name_list[0].replace('.mp3', '') + self.play_music() + + def play_music(self): + """ + 播放歌曲 + """ + self.lyrics_panel.DestroyChildren() + full_path = os.path.join(self.local_music_folder, self.current_music_name) + '.mp3' + self.music.load(full_path) + self.music.play() + self.current_music_state = 1 + self.current_music_index = self.local_music_name_list.index(self.current_music_name + '.mp3') + self.play_stop_button.SetBitmap(self.stop_png) + lyric_path = os.path.join(self.local_music_folder, self.current_music_name) + '.lrc' + self.lyrics_list = get_lyrics(lyric_path) + self.draw_music_lyrics_panel() + + # 歌词刷新线程 + lyric_refresh_thread = threading.Thread(target=self.refresh_lyrics) + lyric_refresh_thread.start() + + # 当前播放音乐名(控制区域) + current_music_name = self.local_music_name_list[self.current_music_index].replace(".mp3", "") + max_music_name_len = self.setting_dic['max_music_name_len'] + if len(current_music_name) > max_music_name_len: + current_music_name = self.current_music_name[0:max_music_name_len] + "..." + self.current_music_static_text.SetLabelText('正在播放:' + current_music_name) + self.current_music_static_text.SetToolTip(self.current_music_name) + + def draw_music_lyrics_panel(self): + """ + 绘制歌词面板 + """ + # 清空歌词static text列表 + self.lyrics_static_text_list.clear() + length, width = self.lyrics_panel.GetSize() + total_lyrics_row = int(1080 / 30) # 页面最多歌词行数(仅支持1080p及以下屏幕) + max_lyrics_row = int(width / 30) + for lyric_index in range(total_lyrics_row): + if lyric_index < max_lyrics_row and lyric_index < len(self.lyrics_list): + time_lyric_tuple = self.lyrics_list[lyric_index] + else: + time_lyric_tuple = (-1, '') # 时间为-1表示空行 + lyric_row = wx.StaticText(self.lyrics_panel, -1, time_lyric_tuple[1], + pos=(int((length - 400) * 0.8 / 2), 30 * lyric_index + 10), + size=(400, 30), style=wx.ALIGN_CENTER_HORIZONTAL) + lyric_row.SetForegroundColour(self.setting_dic['lyrics_bg_color']) + lyric_row.SetFont(self.user_font) + self.lyrics_static_text_list.append((time_lyric_tuple[0], lyric_row)) + + def refresh_lyrics(self): + """ + 刷新歌词线程 + """ + music_index = self.current_music_index + length, width = self.lyrics_panel.GetSize() + # 当前显示的歌词行数 + current_shown_lyrics_num = len(list(filter(lambda x: x != '', + (i[1].GetLabel() for i in self.lyrics_static_text_list)))) + current_start_lyrics_index = 0 + while music_index == self.current_music_index and self.is_running: + + # 刷新歌词颜色 + lyrics_fg_color = self.setting_dic['lyrics_fg_color'] + for lyric_time, lyric_row in self.lyrics_static_text_list: + # 当歌词时间大于0(-1为空行)小于当前时间,且颜色不为前景色时将其设置为前景色 + if 0 <= lyric_time <= self.music.get_pos()/1000 and \ + lyric_row.ForegroundColour != wx.Colour(lyrics_fg_color): + lyric_row.SetForegroundColour(lyrics_fg_color) + lyric_row.Refresh() + + # 刷新歌词位置 + if length != self.lyrics_panel.GetSize()[0]: + length = self.lyrics_panel.GetSize()[0] + for ind, (_, row) in enumerate(self.lyrics_static_text_list): + row.SetPosition((int((length - 400) * 0.8 / 2), 30 * ind + 10)) + + # 刷新歌词行数 + if width != self.lyrics_panel.GetSize()[1]: + width = self.lyrics_panel.GetSize()[1] + max_lyrics_row = int(width / 30) + # 可显示行数小于已显示行数,将多余行设为空行 + if max_lyrics_row < current_shown_lyrics_num: + for ind, (_, lyric_row) in enumerate(self.lyrics_static_text_list[max_lyrics_row:]): + lyric_row.SetLabel('') + self.lyrics_static_text_list[max_lyrics_row + ind] = (-1, lyric_row) + # 可显示行数大于已显示行数,显示不足行 + else: + lst = self.lyrics_static_text_list[current_shown_lyrics_num:max_lyrics_row] # 需增加的歌词 + for ind, (_, lyric_row) in enumerate(lst): + start_index = current_start_lyrics_index + current_shown_lyrics_num # 需增加的歌词在歌词列表中的起始位置 + if start_index + ind < len(self.lyrics_list): + lyric_time, lyric_text = self.lyrics_list[start_index + ind] + lyric_row.SetLabel(lyric_text) + # 当设置完歌曲最后一行歌词后将其余行设置为空 + else: + lyric_time = -1 + lyric_row.SetLabel('') + self.lyrics_static_text_list[current_shown_lyrics_num+ind] = (lyric_time, lyric_row) + current_shown_lyrics_num = max_lyrics_row # 当前显示的歌词行数 + + # 歌词到底后刷新下一页 + new_page_index = int(width / 30) + current_start_lyrics_index # 下一页起始索引 + # 当下一页起始歌词索引小于歌词总行数,且离下一页第一句歌词时间小于0.5s时绘制下一页 + if new_page_index < len(self.lyrics_list) and \ + abs(self.lyrics_list[new_page_index][0] - self.music.get_pos()/1000) < 0.5: + current_start_lyrics_index = new_page_index + max_lyrics_row = int(width / 30) + for ind, (_, lyric_row) in enumerate(self.lyrics_static_text_list): + lyric_row.SetForegroundColour(self.setting_dic['lyrics_bg_color']) + if ind < max_lyrics_row and new_page_index + ind < len(self.lyrics_list): + lyric_time, lyric_text = self.lyrics_list[new_page_index + ind] + else: + lyric_time, lyric_text = (-1, '') + lyric_row.SetLabel(lyric_text) + self.lyrics_static_text_list[ind] = (lyric_time, lyric_row) + + time.sleep(0.5) + + def play_last_music(self, evt): + """ + 上一首按钮事件 + """ + if self.current_music_state == 0: # 未开始播放时按钮无效 + return + elif self.current_music_index > 1: + self.current_music_index -= 1 + else: + self.current_music_index = len(self.local_music_name_list) - 1 + self.current_music_name = self.local_music_name_list[self.current_music_index].replace('.mp3', '') + self.play_music() + + def play_next_music(self, evt): + """ + 下一首按钮事件 + """ + if self.current_music_state == 0: # 未开始播放时按钮无效 + return + elif self.current_music_index < len(self.local_music_name_list) - 1: + self.current_music_index += 1 + else: + self.current_music_index = 0 + self.current_music_name = self.local_music_name_list[self.current_music_index].replace('.mp3', '') + self.play_music() + + def change_volume(self, evt): + """ + 音量滑动条事件 + """ + obj = evt.GetEventObject() + val = obj.GetValue() + self.volume = float(val / 100) + self.music.set_volume(self.volume) + self.volume_text.SetLabel(f'音量{int(self.volume * 100)}%') + self.unsaved_setting['volume'] = self.volume + + def setting_button_evt(self, evt): + """ + 当主界面或排行榜界面显示时将其隐藏,在设置界面不存在时绘制界面,存在时显示设置界面 + """ + if self.main_interface_panel.IsShown(): + self.main_interface_panel.Hide() + if self.ranking_notebook and self.ranking_notebook.IsShown(): + self.ranking_notebook.Hide() + if not self.setting_panel: + self.draw_setting_interface() + if not self.setting_panel.IsShown(): + self.setting_panel.Show() + + def ranking_button_evt(self, evt): + """ + 当主界面或设置界面显示时将其隐藏,在排行榜界面不存在时绘制界面,存在时显示排行榜界面 + """ + if self.main_interface_panel.IsShown(): + self.main_interface_panel.Hide() + if self.setting_panel and self.setting_panel.IsShown(): + self.setting_panel.Hide() + if not self.ranking_notebook: + self.draw_ranking_notebook() + if not self.ranking_notebook.IsShown(): + self.ranking_notebook.Show() + + def draw_setting_interface(self): + """ + 绘制设置界面 + """ + self.setting_panel = SettingPanel(self) + self.base_sizer.Add(self.setting_panel, 1, wx.EXPAND) + self.base_sizer.Layout() + + def draw_ranking_notebook(self): + """ + 绘制排行榜界面 + """ + self.ranking_notebook = RankListNotebook(self) + self.base_sizer.Add(self.ranking_notebook, 1, wx.EXPAND) + self.base_sizer.Layout() + + def close_window(self, evt): + """ + 关闭界面事件 + """ + self.is_running = False # 刷新歌词线程终止的条件之一 + # 退出时保存设置 + with open('setting.txt', 'w', encoding='utf-8') as f: + f.writelines(str(self.unsaved_setting)) + evt.Skip() # 继续关闭事件 + + +if __name__ == "__main__": + app = wx.App() + frame = MainFrame() + app.MainLoop() diff --git a/music_folder/a占位歌曲,无内容 (1).mp3 b/music_folder/a占位歌曲,无内容 (1).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (1).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (10).mp3 b/music_folder/a占位歌曲,无内容 (10).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (10).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (11).mp3 b/music_folder/a占位歌曲,无内容 (11).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (11).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (12).mp3 b/music_folder/a占位歌曲,无内容 (12).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (12).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (13).mp3 b/music_folder/a占位歌曲,无内容 (13).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (13).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (14).mp3 b/music_folder/a占位歌曲,无内容 (14).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (14).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (15).mp3 b/music_folder/a占位歌曲,无内容 (15).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (15).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (16).mp3 b/music_folder/a占位歌曲,无内容 (16).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (16).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (17).mp3 b/music_folder/a占位歌曲,无内容 (17).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (17).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (18).mp3 b/music_folder/a占位歌曲,无内容 (18).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (18).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (19).mp3 b/music_folder/a占位歌曲,无内容 (19).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (19).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (2).mp3 b/music_folder/a占位歌曲,无内容 (2).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (2).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (20).mp3 b/music_folder/a占位歌曲,无内容 (20).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (20).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (21).mp3 b/music_folder/a占位歌曲,无内容 (21).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (21).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (22).mp3 b/music_folder/a占位歌曲,无内容 (22).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (22).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (23).mp3 b/music_folder/a占位歌曲,无内容 (23).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (23).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (24).mp3 b/music_folder/a占位歌曲,无内容 (24).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (24).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (25).mp3 b/music_folder/a占位歌曲,无内容 (25).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (25).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (26).mp3 b/music_folder/a占位歌曲,无内容 (26).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (26).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (27).mp3 b/music_folder/a占位歌曲,无内容 (27).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (27).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (28).mp3 b/music_folder/a占位歌曲,无内容 (28).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (28).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (29).mp3 b/music_folder/a占位歌曲,无内容 (29).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (29).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (3).mp3 b/music_folder/a占位歌曲,无内容 (3).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (3).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (30).mp3 b/music_folder/a占位歌曲,无内容 (30).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (30).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (31).mp3 b/music_folder/a占位歌曲,无内容 (31).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (31).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (32).mp3 b/music_folder/a占位歌曲,无内容 (32).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (32).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (33).mp3 b/music_folder/a占位歌曲,无内容 (33).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (33).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (34).mp3 b/music_folder/a占位歌曲,无内容 (34).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (34).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (35).mp3 b/music_folder/a占位歌曲,无内容 (35).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (35).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (36).mp3 b/music_folder/a占位歌曲,无内容 (36).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (36).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (37).mp3 b/music_folder/a占位歌曲,无内容 (37).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (37).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (38).mp3 b/music_folder/a占位歌曲,无内容 (38).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (38).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (39).mp3 b/music_folder/a占位歌曲,无内容 (39).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (39).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (4).mp3 b/music_folder/a占位歌曲,无内容 (4).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (4).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (40).mp3 b/music_folder/a占位歌曲,无内容 (40).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (40).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (5).mp3 b/music_folder/a占位歌曲,无内容 (5).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (5).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (6).mp3 b/music_folder/a占位歌曲,无内容 (6).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (6).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (7).mp3 b/music_folder/a占位歌曲,无内容 (7).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (7).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (8).mp3 b/music_folder/a占位歌曲,无内容 (8).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (8).mp3 differ diff --git a/music_folder/a占位歌曲,无内容 (9).mp3 b/music_folder/a占位歌曲,无内容 (9).mp3 new file mode 100644 index 0000000..ef543bf Binary files /dev/null and b/music_folder/a占位歌曲,无内容 (9).mp3 differ diff --git a/music_folder/你被写在我的歌里 - 苏打绿 _ Ella陈嘉桦.lrc b/music_folder/你被写在我的歌里 - 苏打绿 _ Ella陈嘉桦.lrc new file mode 100644 index 0000000..29eabae --- /dev/null +++ b/music_folder/你被写在我的歌里 - 苏打绿 _ Ella陈嘉桦.lrc @@ -0,0 +1,24 @@ +[ti:你被写在我的歌里] +[ar:苏打绿] +[al:你在烦恼什么] + +[00:00.18]苏打绿 - 你被写在我的歌里 +[00:07.80]作词:吴青峰 作曲:吴青峰 +[01:44.08][00:22.18]走过的路 是一阵魔术 +[01:49.14][00:26.65]把所有的 好的坏的 变成我的 +[01:54.07][00:31.77]心里的苦 就算不记得 +[01:58.38][00:36.02]都化作这目光 吟唱成一首歌 +[02:04.41][00:41.90]而你像 流进诗里的嘈嘈水声 +[02:08.39][00:46.24]敲进我心门 拥抱了所有的恨 +[02:13.28][00:50.97]滋养了干涸 相信我能是你的 +[03:18.54][02:18.16][00:55.99]彷佛还看见昨日那张悲伤的脸庞 +[03:23.67][02:22.62][01:00.15]快乐有时候竟然辣得像一记耳光 +[03:28.50][02:27.21][01:05.20]是你提醒我 别怕去幻想 +[03:33.41][02:32.26][01:09.78]想我内心躲避惯的渴望 +[03:37.90][02:36.90][01:14.32]彷佛能看见明日两串脚印的走廊 +[03:42.53][02:41.44][01:19.05]忧伤有时候竟被你调味得像颗糖 +[03:47.52][02:46.25][01:24.02]是你抓紧我 往前去张望 +[03:52.20][02:51.03][01:28.69]望我内心夹岸群花盛放 +[03:56.58][02:55.46][01:33.02]我被写在你的眼睛里眨呀 +[04:01.11]你被写在我的歌里面唱呀 +[04:06.11]我们被写在彼此心里爱呀 \ No newline at end of file diff --git a/music_folder/你被写在我的歌里 - 苏打绿 _ Ella陈嘉桦.mp3 b/music_folder/你被写在我的歌里 - 苏打绿 _ Ella陈嘉桦.mp3 new file mode 100644 index 0000000..e5102c0 Binary files /dev/null and b/music_folder/你被写在我的歌里 - 苏打绿 _ Ella陈嘉桦.mp3 differ diff --git a/music_folder/打上花火 - DAOKO (ダヲコ) _ 米津玄師 (よねづ けんし).lrc b/music_folder/打上花火 - DAOKO (ダヲコ) _ 米津玄師 (よねづ けんし).lrc new file mode 100644 index 0000000..a3e1ca6 --- /dev/null +++ b/music_folder/打上花火 - DAOKO (ダヲコ) _ 米津玄師 (よねづ けんし).lrc @@ -0,0 +1,63 @@ +[00:00.000] 作词 : 米津玄師 +[00:00.528] 作曲 : 米津玄師 +[00:01.56] +[00:19.69]あの日見渡した渚を +[00:24.62]今も思い出すんだ +[00:29.52]砂の上に刻んだ言葉 +[00:34.39]君の後ろ姿 +[00:39.52] +[00:39.89]寄り返す波が +[00:42.89]足元をよぎり何かを攫う +[00:49.55]夕凪の中 +[00:52.87]日暮れだけが通り過ぎて行く +[00:57.33] +[00:59.55]パッと光って咲いた +[01:01.78]花火を見ていた +[01:04.34]きっとまだ +[01:05.52]終わらない夏が +[01:09.26]曖昧な心を +[01:11.76]解かして繋いだ +[01:14.28]この夜が +[01:15.76]続いて欲しかった +[01:18.74] +[01:29.97]「あと何度君と同じ花火を見られるかな」って +[01:34.52]笑う顔に何ができるだろうか +[01:39.90]傷つくこと喜ぶこと +[01:42.32]繰り返す波と情動 +[01:44.61]焦燥最終列車の音 +[01:48.42] +[01:50.06]何度でも +[01:51.91]言葉にして君を呼ぶよ +[01:54.88]波間を選びもう一度 +[01:59.85]もう二度と悲しまずに済むように +[02:08.52] +[02:17.12]はっと息を飲めば +[02:19.38]消えちゃいそうな光が +[02:21.88]きっとまだ +[02:23.29]胸に住んでいた +[02:26.82]手を伸ばせば触れた +[02:29.38]あったかい未来は +[02:32.09]ひそかに二人を見ていた +[02:35.62] +[02:38.08]パッと花火が +[02:40.58]夜に咲いた +[02:43.85]夜に咲いて +[02:46.20]静かに消えた +[02:48.25]離さないで +[02:50.70]もう少しだけ +[02:53.40]もう少しだけ +[02:54.46]このままで +[02:56.77] +[03:07.43]あの日見渡した渚を +[03:12.27]今も思い出すんだ +[03:17.04]砂の上に刻んだ言葉 +[03:22.22]君の後ろ姿 +[03:25.02] +[03:27.17]パッと光って咲いた +[03:29.33]花火を見ていた +[03:31.78]きっとまだ +[03:33.20]終わらない夏が +[03:36.74]曖昧な心を +[03:39.24]解かして繋いだ +[03:41.69]この夜が +[03:42.97]続いて欲しかった \ No newline at end of file diff --git a/music_folder/打上花火 - DAOKO (ダヲコ) _ 米津玄師 (よねづ けんし).mp3 b/music_folder/打上花火 - DAOKO (ダヲコ) _ 米津玄師 (よねづ けんし).mp3 new file mode 100644 index 0000000..dca314f Binary files /dev/null and b/music_folder/打上花火 - DAOKO (ダヲコ) _ 米津玄師 (よねづ けんし).mp3 differ diff --git a/music_folder/陈奕迅 - 浮夸.mp3 b/music_folder/陈奕迅 - 浮夸.mp3 new file mode 100644 index 0000000..7daf1d1 Binary files /dev/null and b/music_folder/陈奕迅 - 浮夸.mp3 differ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..21e049c --- /dev/null +++ b/requirements.txt @@ -0,0 +1,14 @@ +beautifulsoup4==4.9.3 +bs4==0.0.1 +certifi==2021.5.30 +chardet==4.0.0 +idna==2.10 +numpy==1.20.3 +pefile==2021.5.13 +Pillow==8.2.0 +pygame==2.0.1 +requests==2.25.1 +six==1.16.0 +soupsieve==2.2.1 +urllib3==1.26.5 +wxPython==4.1.1 diff --git a/ruijia.py b/ruijia.py new file mode 100644 index 0000000..c55e4a9 --- /dev/null +++ b/ruijia.py @@ -0,0 +1,35 @@ +import requests +from bs4 import BeautifulSoup + +headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' + '(KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36' +} + + +def get_data(url_): + data = requests.get(url=url_, headers=headers) + soup = BeautifulSoup(data.text, "html.parser") + ranks = soup.select('span.pc_temp_num') # 排名 + titles = soup.select('div.pc_temp_songlist > ul > li > a') # 歌手名和歌曲名 + ls = [] + for rank, title in zip(ranks, titles): + rank = rank.get_text().strip() + song = title.get_text().split('-')[::-1] + data = {'rank': rank, 'song': '-'.join(song)} + ls.append(data) + return ls + + +def main(url_): + ls = [] + urls_ = [url_.format(str(i)) for i in range(1, 6)] + for u in urls_: + ls.extend(get_data(u)) + return ls + + +if __name__ == '__main__': + urls = ['http://www.kugou.com/yy/rank/home/{}-31308.html'.format(str(i)) for i in range(1, 20)] + for url in urls: + print(get_data(url))