1+ import os
2+ import tkinter as tk
3+ import webbrowser
4+ import requests
5+ import tkinter .messagebox as mes_box
6+ import PySimpleGUI as sg
7+ from tkinter import ttk
8+ from retrying import retry
9+
10+
11+ class SetUI (object ):
12+ """
13+ 音乐弹框界面
14+ """
15+
16+ def __init__ (self , weight = 1000 , height = 600 ):
17+ self .ui_weight = weight
18+ self .ui_height = height
19+ self .title = " 音乐破解软件"
20+ self .ui_root = tk .Tk (className = self .title )
21+ self .ui_url = tk .StringVar ()
22+ self .ui_var = tk .IntVar ()
23+ self .ui_var .set (1 )
24+ self .show_result = None
25+ self .song_num = None
26+ self .response_data = None
27+ self .song_url = None
28+ self .song_name = None
29+ self .song_author = None
30+
31+ def set_ui (self ):
32+ """
33+ 设置简易UI界面
34+ :return:
35+ """
36+ # Frame空间
37+ frame_1 = tk .Frame (self .ui_root )
38+ frame_2 = tk .Frame (self .ui_root )
39+ frame_3 = tk .Frame (self .ui_root )
40+ frame_4 = tk .Frame (self .ui_root )
41+
42+ # ui界面中菜单设计
43+ ui_menu = tk .Menu (self .ui_root )
44+ self .ui_root .config (menu = ui_menu )
45+ file_menu = tk .Menu (ui_menu , tearoff = 0 )
46+ ui_menu .add_cascade (label = '菜单' , menu = file_menu )
47+ file_menu .add_command (label = '使用说明' , command = lambda : webbrowser .open ('www.baidu.com' ))
48+ file_menu .add_command (label = '关于作者' , command = lambda : webbrowser .open ('www.baidu.com' ))
49+ file_menu .add_command (label = '退出' , command = self .ui_root .quit )
50+
51+ # 控件内容设置
52+ choice_passageway = tk .Label (frame_1 , text = '请选择音乐搜索通道:' , padx = 10 , pady = 10 )
53+ passageway_button_1 = tk .Radiobutton (frame_1 , text = '酷我' , variable = self .ui_var , value = 1 , width = 10 , height = 3 )
54+ passageway_button_2 = tk .Radiobutton (frame_1 , text = '网易云' , variable = self .ui_var , value = 2 , width = 10 , height = 3 )
55+ passageway_button_3 = tk .Radiobutton (frame_1 , text = 'QQ音乐' , variable = self .ui_var , value = 3 , width = 10 , height = 3 )
56+ passageway_button_4 = tk .Radiobutton (frame_1 , text = '酷狗' , variable = self .ui_var , value = 4 , width = 10 , height = 3 )
57+ input_link = tk .Label (frame_2 , text = "请输入歌曲名或歌手:" )
58+ entry_style = tk .Entry (frame_2 , textvariable = self .ui_url , highlightcolor = 'Fuchsia' , highlightthickness = 1 ,
59+ width = 35 )
60+ label2 = tk .Label (frame_2 , text = " " )
61+ play_button = tk .Button (frame_2 , text = "搜索" , font = ('楷体' , 11 ), fg = 'Purple' , width = 2 , height = 1 ,
62+ command = self .get_KuWoMusic )
63+ label3 = tk .Label (frame_2 , text = " " )
64+ # 表格样式
65+ columns = ("序号" , "歌手" , "歌曲" , "专辑" )
66+ self .show_result = ttk .Treeview (frame_3 , height = 20 , show = "headings" , columns = columns )
67+ # 下载
68+ download_button = tk .Button (frame_4 , text = "下载" , font = ('楷体' , 11 ), fg = 'Purple' , width = 6 , height = 1 , padx = 5 ,
69+ pady = 5 , command = self .download_music )
70+
71+ # 控件布局
72+ frame_1 .pack ()
73+ frame_2 .pack ()
74+ frame_3 .pack ()
75+ frame_4 .pack ()
76+ choice_passageway .grid (row = 0 , column = 0 )
77+ passageway_button_1 .grid (row = 0 , column = 1 )
78+ passageway_button_2 .grid (row = 0 , column = 2 )
79+ passageway_button_3 .grid (row = 0 , column = 3 )
80+ passageway_button_4 .grid (row = 0 , column = 4 )
81+ input_link .grid (row = 0 , column = 0 )
82+ entry_style .grid (row = 0 , column = 1 )
83+ label2 .grid (row = 0 , column = 2 )
84+ play_button .grid (row = 0 , column = 3 , ipadx = 10 , ipady = 10 )
85+ label3 .grid (row = 0 , column = 4 )
86+ self .show_result .grid (row = 0 , column = 4 )
87+ download_button .grid (row = 0 , column = 5 )
88+
89+ # 设置表头
90+ self .show_result .heading ("序号" , text = "序号" )
91+ self .show_result .heading ("歌手" , text = "歌手" )
92+ self .show_result .heading ("歌曲" , text = "歌曲" )
93+ self .show_result .heading ("专辑" , text = "专辑" )
94+ # 设置列
95+ self .show_result .column ("序号" , width = 100 , anchor = 'center' )
96+ self .show_result .column ("歌手" , width = 200 , anchor = 'center' )
97+ self .show_result .column ("歌曲" , width = 200 , anchor = 'center' )
98+ self .show_result .column ("专辑" , width = 300 , anchor = 'center' )
99+
100+ # 鼠标点击
101+ self .show_result .bind ('<ButtonRelease-1>' , self .get_song_url )
102+
103+ @retry (stop_max_attempt_number = 5 )
104+ def get_KuWoMusic (self ):
105+ """
106+ 获取qq音乐
107+ :return:
108+ """
109+ # 清空treeview表格数据
110+ for item in self .show_result .get_children ():
111+ self .show_result .delete (item )
112+ headers = {
113+ 'accept' : 'application/json, text/plain, */*' ,
114+ 'accept - encoding' : 'gzip, deflate' ,
115+ 'accept - language' : 'zh - CN, zh;q = 0.9' ,
116+ 'cache - control' : 'no - cache' ,
117+ 'Connection' : 'keep-alive' ,
118+ 'csrf' : 'HH3GHIQ0RYM' ,
119+ 'Referer' : 'http://www.kuwo.cn/search/list?key=%E5%91%A8%E6%9D%B0%E4%BC%A6' ,
120+ 'User-agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
121+ 'Chrome/99.0.4844.51 Safari/537.36' ,
122+ 'Cookie' : '_ga=GA1.2.218753071.1648798611; _gid=GA1.2.144187149.1648798611; _gat=1; '
123+ 'Hm_lvt_cdb524f42f0ce19b169a8071123a4797=1648798611; '
124+ 'Hm_lpvt_cdb524f42f0ce19b169a8071123a4797=1648798611; kw_token=HH3GHIQ0RYM'
125+ }
126+ search_input = self .ui_url .get ()
127+ if len (search_input ) > 0 :
128+ search_url = 'http://www.kuwo.cn/api/www/search/searchMusicBykeyWord?'
129+ search_data = {
130+ 'key' : search_input ,
131+ 'pn' : '1' ,
132+ 'rn' : '80' ,
133+ 'httpsStatus' : '1' ,
134+ 'reqId' : '858597c1-b18e-11ec-83e4-9d53d2ff08ff'
135+ }
136+ try :
137+ self .response_data = requests .get (search_url , params = search_data , headers = headers , timeout = 20 ).json ()
138+ songs_data = self .response_data ['data' ]['list' ]
139+ if int (self .response_data ['data' ]['total' ]) <= 0 :
140+ mes_box .showerror (title = '错误' , message = '搜索: {} 不存在.' .format (search_input ))
141+ else :
142+ for i in range (len (songs_data )):
143+ self .show_result .insert ('' , i , values = (i + 1 , songs_data [i ]['artist' ], songs_data [i ]['name' ],
144+ songs_data [i ]['album' ]))
145+ except TimeoutError :
146+ mes_box .showerror (title = '错误' , message = '搜索超时,请重新输入后再搜索!' )
147+ else :
148+ mes_box .showerror (title = '错误' , message = '未输入需查询的歌曲或歌手,请输入后搜索!' )
149+
150+ def get_song_url (self , event ):
151+ """
152+ 获取下载歌曲的地址
153+ :return:
154+ """
155+ # treeview中的左键单击
156+
157+ for item in self .show_result .selection ():
158+ item_text = self .show_result .item (item , "values" )
159+ # 获取
160+ print (1 , item_text )
161+ self .song_num = int (item_text [0 ])
162+ # 获取下载歌曲的地址
163+ if self .song_num is not None :
164+ songs_data = self .response_data ['data' ]['list' ]
165+ songs_req_id = self .response_data ['reqId' ]
166+ song_rid = songs_data [self .song_num - 1 ]['rid' ]
167+ music_url = 'http://www.kuwo.cn/api/v1/www/music/playUrl?mid={}&type=convert_url3' \
168+ '&httpsStatus=1&reqId={}' \
169+ .format (song_rid , songs_req_id )
170+ response_data = requests .get (music_url ).json ()
171+ self .song_url = response_data ['data' ].get ('url' )
172+ self .song_name = songs_data [self .song_num - 1 ]['name' ]
173+ self .song_author = songs_data [self .song_num - 1 ]['artist' ]
174+ else :
175+ mes_box .showerror (title = '错误' , message = '未选择要下载的歌曲,请选择' )
176+
177+ def download_music (self ):
178+ """
179+ 下载音乐
180+ :return:
181+ """
182+ if not os .path .exists ('./wangYiYun' ):
183+ os .mkdir ("./wangYiYun/" )
184+ if self .song_num is not None :
185+ song_name = self .song_name + '--' + self .song_author + ".mp3"
186+ try :
187+ save_path = os .path .join ('./wangYiYun/{}' .format (song_name )) \
188+ .replace ('\\ ' , '/' )
189+ true_path = os .path .abspath (save_path )
190+ resp = requests .get (self .song_url )
191+ with open (save_path , 'wb' ) as file :
192+ file .write (resp .content )
193+ mes_box .showinfo (title = '下载成功' , message = '歌曲:%s,保存地址为%s' % (self .song_name , true_path ))
194+ except Exception :
195+ mes_box .showerror (title = '错误' , message = '未找到存放歌曲的文件夹' )
196+ else :
197+ mes_box .showerror (title = '错误' , message = '未选择要下载的歌曲,请选择后下载' )
198+
199+ def progress_bar (self , file_size ):
200+ """
201+ 任务加载进度条
202+ :return:
203+ """
204+ layout = [[sg .Text ('任务完成进度' )],
205+ [sg .ProgressBar (file_size , orientation = 'h' , size = (40 , 20 ), key = 'progressbar' )],
206+ [sg .Cancel ()]]
207+
208+ # window只需将自定义的布局加载出来即可 第一个参数是窗口标题。
209+ window = sg .Window ('机器人执行进度' , layout )
210+ # 根据key值获取到进度条
211+ _progress_bar = window ['progressbar' ]
212+ for i in range (file_size ): # 循环
213+ event , values = window .read (timeout = 10 )
214+ if event == 'Cancel' or event is None :
215+ break
216+ _progress_bar .UpdateBar (i + 1 )
217+
218+ def ui_center (self ):
219+ """
220+ UI界面窗口设置:居中
221+ """
222+ ws = self .ui_root .winfo_screenwidth ()
223+ hs = self .ui_root .winfo_screenheight ()
224+ x = int ((ws / 2 ) - (self .ui_weight / 2 ))
225+ y = int ((hs / 2 ) - (self .ui_height / 2 ))
226+ self .ui_root .geometry ('{}x{}+{}+{}' .format (self .ui_weight , self .ui_height , x , y ))
227+
228+ def loop (self ):
229+ """
230+ 函数说明:loop等待用户事件
231+ """
232+ self .ui_root .resizable (False , False ) # 禁止修改窗口大小
233+ self .ui_center () # 窗口居中
234+ self .set_ui ()
235+ self .ui_root .mainloop ()
236+
237+
238+ if __name__ == '__main__' :
239+ a = SetUI ()
240+ a .loop ()
0 commit comments