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