前言
之前做的Python小工具,現在搬出來和大家分享,基於酷狗音樂免費下載付費音樂,並已封裝GUI。
(純屬個人興趣,請大家尊重音樂版權),超喜歡JJ Lin的歌,放圖鎮文
軟件
Python 3.6
Pycharm 2018.03
效果展示
代碼實現
進度條花費了大量精力,最後採用網頁進度條思路,即填充到90%停下,等待請求返回,收到回覆後填充至100%
import requests
import json
from tkinter import ttk,filedialog
from tkinter import *
import tkinter as tk
import os,time
from tkinter import messagebox
import threading
global song_dic
song_dic = {}
def search():
keys = keyin.get()
search_url = 'http://songsearch.kugou.com/song_search_v2?callback=jQuery191034642999175022426_1489023388639&keyword={}&page=1&pagesize=30&userid=-1&clientver=&platform=WebFilter&tag=em&filter=2&iscorrection=1&privilege_filter=0&_=1489023388641'
play_url = 'http://www.kugou.com/yy/index.php?r=play/getdata&hash={}'
search_file = requests.get(search_url.format(keys))
search_html = search_file.content.decode().replace(')', '').replace(
'jQuery191034642999175022426_1489023388639(', '')
views = json.loads(search_html)
global song_dic
song_dic = {}
song_list = []
i=0
fill_line = canvas.create_rectangle(1.5, 1.5, 0, 23, width=0, fill="green")
canvas.coords(fill_line, (0, 0, 646, 60))
# 清空表格
for item in treeview.get_children():
treeview.delete(item)
for view in views['data']['lists']:
root.update()
song_name = view['SongName'].replace('<em>', '').replace('</em>', '')
album_name = view['AlbumName'].replace('<em>', '').replace('</em>', '')
sing_name = view['SingerName'].replace('<em>', '').replace('</em>', '')
file_hash = view['FileHash']
song_info = {
'歌名': song_name,
'演唱者': sing_name,
'專輯': album_name if album_name else None,
'filehash': file_hash,
'mp3url': None
}
mp3_file = requests.get(play_url.format(song_info['filehash'])).content.decode()
mp3_json = json.loads(mp3_file)
real_url = mp3_json['data']['play_url']
song_info['mp3url'] = real_url # 歌曲信息獲取完畢!
song_name = str(song_info['歌名'])+str(song_info['演唱者'])+str(song_info['專輯'])
song_list.append(song_info['演唱者'])
song_list.append(song_info['專輯'])
song_list.append(song_info['mp3url'])
treeview.insert('', i, values=(song_info['歌名'], song_info['演唱者'], song_info['專輯']))
i += 1
song_dic[song_name] = song_list
song_list = []
# 清空進度條
fill_line = canvas.create_rectangle(1.5, 1.5, 0, 23, width=0, fill="white")
x = 300 # 未知變量,可更改
n = 643 / x # 643是矩形填充滿的次數
for t in range(x):
n = n + 643 / x
# 以矩形的長度作爲變量值更新
canvas.coords(fill_line, (0, 0, n, 60))
root.update()
time.sleep(0) # 時間爲0,即飛速清空進度條
def musicsave():
try:
dirsetting = open('resource/settings/songdirsetting.ini', 'r')
dirlast = dirsetting.read()
dirsetting.close()
except:
dirlast='D:' # 默認保存文件夾
for item in treeview.selection():
#item = I001
item_text = treeview.item(item, "values")
song_name1 = item_text[1]+' - '+item_text[0]
songkey = item_text[0]+item_text[1]+item_text[2]
filename = dirlast +'/'+ song_name1 + ".mp3"
with open(filename, "wb")as fp:
global song_dic
real_url = song_dic[songkey][2]
fp.write(requests.get(real_url).content)
messagebox.showinfo('下載完成', '歌曲《'+song_name1+'》已保存至\n'+dirlast+' 文件夾!')
def musicsave2(event):
musicsave()
def search2(event):
two_threading()
def chosedir(): # 選擇保存文件夾
def chose():
default_dir = r"C:\Users\lenovo\Desktop" # 設置默認打開目錄
dname = filedialog.askdirectory(title=u"選擇文件夾",
initialdir=(os.path.expanduser(default_dir)))
dirsetting = open('resource/settings/songdirsetting.ini', 'w')
dirsetting.write(dname)
dirsetting.close()
dirname.set(dname)
chosebox = tk.Toplevel()
chosebox.iconbitmap(r'resource/EC.ico') # 窗口圖標設置
chosebox.title("設置")
chosebox.geometry(('320x100+720+200')) # 寬度x 高度+橫向偏移量(距左邊)+縱向偏移量(距上邊)
chosebox.resizable(0, 0)
tk.Label(chosebox, text="文件保存至: ", bd=1, width=10).place(x=7, y=30)
dirname = tk.StringVar() # 文件絕對地址
try:
dirsetting = open('resource/settings/songdirsetting.ini', 'r')
dirlast = dirsetting.read()
dirname.set(dirlast)
dirsetting.close()
except:
dirname.set('D:') # 默認保存文件夾
showdir = tk.Entry(chosebox, textvariable=dirname, width=26)
showdir.place(x=74, y=30)
ttk.Button(chosebox, text='瀏覽', compound='center', width=5, command=chose).place(x=262, y=27)
# 顯示下載進度
def progress():
# 填充進度條
fill_line = canvas.create_rectangle(1.5, 1.5, 0, 23, width=0, fill="green")
x = 300 # 未知變量,可更改
n = 643 / x # 643是矩形填充滿的次數
for i in range(x):
n = n + 643 / x
canvas.coords(fill_line, (0, 0, n, 60))
root.update()
time.sleep(0.02) # 控制進度條流動的速度
if n>600:
break
canvas.coords(fill_line, (0, 0, 600, 60)) # 90%時停止進度條,等待請求返回
root.update()
def two_threading():
threads = [] #定義線程池
t1 = threading.Thread(target=search)
threads.append(t1)
t2 = threading.Thread(target=progress)
threads.append(t2)
for t in threads:
t.setDaemon(True) # 設置爲守護線程
t.start()
root = tk.Tk()
root.title('歡迎使用本工具')
root.geometry(('700x480+200+100')) # 寬度x 高度+橫向偏移量(距左邊)+縱向偏移量(距上邊)
menuBar = tk.Menu(root)
root.config(menu=menuBar)
setMenu = tk.Menu(menuBar, tearoff=0)
setMenu.add_command(label="保存文件夾", command = chosedir)
menuBar.add_cascade(label="設置", menu=setMenu)
title = Label(root, text='付費音樂破解助手', font=("宋體", 18)) # 設置標題
title.place(x=260, y=10)
keywords = Label(root, text='關鍵詞:', width=6, height=1, bd=2,
font=('微軟雅黑',12))
keywords.place(x=150, y=56)
keyshow = StringVar()
keyin = Entry(root, textvariable=keyshow, width=35,bg="#c7edcc",font=('微軟雅黑',10)) # 關鍵詞輸入框
keyin.place(x=220, y=60)
keyin.bind("<Return>", search2) # 綁定回車鍵搜索
btphoto = tk.PhotoImage(file='resource/image/bt.png')
bt3 = tk.Button(root, image = btphoto,bd =0, command=two_threading)
bt3.place(x=500, y=58)
# 設置下載進度條
canvas = tk.Canvas(root, width=643, height=5, bg="white")
canvas.place(x=28, y=88)
#bt4 = ttk.Button(root, text='下載',width=5, command=musicsave)
#bt4.place(x=630, y=57)
columns = ("歌名", "演唱者","專輯")
treeview = ttk.Treeview(root, height=16, show="headings", columns=columns) # 表格
treeview.column("歌名", width=200, anchor='center') # 表示列,不顯示
treeview.column("演唱者", width=200, anchor='center')
treeview.column("專輯", width=240, anchor='center')
treeview.heading("歌名", text="歌名") # 顯示錶頭
treeview.heading("演唱者", text="演唱者")
treeview.heading("專輯", text="專輯")
treeview.place(x=30,y=96)
def treeview_sort_column(tv, col, reverse): # Treeview、列名、排列方式
l = [(tv.set(k, col), k) for k in tv.get_children('')]
l.sort(reverse=reverse) # 排序方式
# rearrange items in sorted positions
for index, (val, k) in enumerate(l): # 根據排序後索引移動
tv.move(k, '', index)
tv.heading(col, command=lambda: treeview_sort_column(tv, col, not reverse)) # 重寫標題,使之成爲再點倒序的標題
for col in columns: # 綁定函數,使表頭可排序
treeview.heading(col, text=col, command=lambda _col=col: treeview_sort_column(treeview, _col, False))
menu = Menu(treeview, tearoff=0)
menu.add_command(label="下載", command=musicsave)
def popupmenu(event):
menu.post(event.x_root, event.y_root)
treeview.bind("<Button-3>", popupmenu)
treeview.bind('<Double-1>', musicsave2)
tk.Label(root, text="左鍵雙擊或右鍵下載歌曲", width=19).place(x=30,y=450)
root.iconbitmap(r'resource/EC.ico') # 窗口圖標設置
root.mainloop()
相關文件下載(包括ico圖片、無需Python也可直接運行的exe文件)
百度網盤鏈接:點擊這裏
參考鏈接: