该篇文章编写的GUI界面爬虫,代码复制下来即可使用;如要查看爬虫分析原理请转到 python爬虫爬取音乐-JS逆向爬虫
from tkinter import Tk, Label, scrolledtext, Entry, Button, END, filedialog, messagebox, FLAT
import requests,time,hashlib
class UI:
#参数定义项
searchContent = ""
folderPath = ""
pageNo = 1
pageSize = 20
musicTotal = 0
downloadMusicList = {}
searchUrl = "https://music.91q.com/v1/search"
musicInfoUrl = "https://music.91q.com/v1/song/tracklink"
secret = "0b50b02fd0d73a9c4c8c3a781c30845f"
appid = 16073360
def __init__(self):
self.main()
#tkinter容器主运行程序
def main(self):
global root
root = Tk()
self.args()
self.lable()
self.text()
self.button()
root.mainloop()
#tkinter界面配置
def args(self):
root.title("music download")
root.geometry("1200x700+350+200")
root.resizable(width=False, height=False)
root.configure(bg="#faebd7")
#界面标签
def lable(self):
lab1 = Label(root, text="请先选择保存路径后再下载!!!", font=("宋体", 15), bg="#faebd7", fg="red")
lab1.place(x="500", y="5")
lab2 = Label(root, text="请输入歌曲前方序号:", font=("宋体", 12), bg="#faebd7", fg="blue")
lab2.place(x="480", y="105")
#文本框
def text(self):
global musicListText, msgOutputText, searchText, downloadNumText, pageNoText
musicListText = scrolledtext.ScrolledText(root, font=("宋体", 15), relief=FLAT, fg="green")
musicListText.place(height="500", width="450", x="100", y="150")
msgOutputText = scrolledtext.ScrolledText(root, font=("宋体", 15), relief=FLAT, fg="green")
msgOutputText.place(height="500", width="450", x="650", y="150")
searchText = Entry(root, font=("宋体", 15), relief=FLAT, fg="green")
searchText.place(height="30", width="300", x="400", y="50")
downloadNumText = Entry(root, font=("宋体", 15), relief=FLAT, fg="green")
downloadNumText.place(height="30", width="60", x="640", y="100")
pageNoText = Entry(root, font=("宋体", 15), relief=FLAT, fg="black", bg="#faebd7")
pageNoText.place(height="30", width="50", x="845", y="100")
#按钮
def button(self):
global searchButton, choosePathButton, downloadAllButton, downloadSingeButton, lastPageButton, nextPageButton, deleteMegButton
searchButton = Button(root, text="搜索", bg="orchid" ,command =lambda : self.get_music())
searchButton.place(height="30", width="40", x="710", y="50")
choosePathButton = Button(root, text="保存路径", bg="orchid",command =lambda : self.path())
choosePathButton.place(height="30", width="60", x="760", y="50")
downloadAllButton = Button(root, text="全部下载", bg="orchid" , command = lambda: self.downloadMusic("all"))
downloadAllButton.place(height="30", width="60", x="830", y="50")
downloadSingeButton = Button(root, text="单曲下载", bg="orchid",command = lambda: self.downloadMusic("singe"))
downloadSingeButton.place(height="30", width="60", x="710", y="100")
lastPageButton = Button(root, text="上一页", bg="orchid", command=lambda: self.last_page())
lastPageButton.place(height="30", width="60", x="780", y="100")
nextPageButton = Button(root, text="下一页", bg="orchid", command=lambda : self.next_page())
nextPageButton.place(height="30", width="60", x="900", y="100")
deleteMegButton = Button(root, text="清除信息", bg="orchid", command=self.delete_message)
deleteMegButton.place(height="30", width="60", x="900", y="50")
#禁用或启用按钮
def disableButton(self,state):
if state == "disabled":
searchButton.configure(state="disabled")
choosePathButton.configure(state="disabled")
downloadAllButton.configure(state="disabled")
downloadSingeButton.configure(state="disabled")
lastPageButton.configure(state="disabled")
nextPageButton.configure(state="disabled")
deleteMegButton.configure(state="disabled")
else:
searchButton.configure(state="normal")
choosePathButton.configure(state="normal")
downloadAllButton.configure(state="normal")
downloadSingeButton.configure(state="normal")
lastPageButton.configure(state="normal")
nextPageButton.configure(state="normal")
deleteMegButton.configure(state="normal")
# 获取搜索的音乐
def get_music(self):
self.pageNo = 1
self.searchContent = ""
self.searchContent = searchText.get()
msgOutputText.delete(0.0, END)
self.searchMusic()
# 保存路径
def path(self):
self.folderPath = ""
self.folderPath = filedialog.askdirectory()
msgOutputText.insert(0.0, " 音乐已保存在: " + self.folderPath + "\n")
# 提示框
def alert(self):
messagebox.showinfo(title="提示", message="请选择保存路径后在下载!!!")
self.path()
# 清除信息
def delete_message(self):
msgOutputText.delete(0.0, END)
# 下一页
def next_page(self):
if self.pageNo <= self.musicTotal/self.pageSize:
self.pageNo += 1
self.searchMusic()
# 上一页
def last_page(self):
if self.pageNo > 1:
self.pageNo -= 1
self.searchMusic()
#md5加密
def md5Encode(self,str):
md5 = hashlib.md5()
md5.update(str.encode('utf-8'))
return md5.hexdigest()
#获取时间戳
def getTimeStamp(self):
return int(time.time())
#音乐搜索函数
def searchMusic(self):
self.disableButton("disabled")
timeStamp = self.getTimeStamp()
args = {
"sign": "",
"word": self.searchContent,
"type": 1,
"pageNo": self.pageNo,
"pageSize": self.pageSize,
"appid": self.appid,
"timestamp": timeStamp
}
signParam = "appid={0}&pageNo={1}&pageSize={2}×tamp={3}&type=1&word={4}{5}".format(self.appid,self.pageNo,self.pageSize,timeStamp,self.searchContent,self.secret)
args["sign"] = self.md5Encode(signParam)
res = requests.get(url=self.searchUrl,params=args).json()
self.musicTotal = res["data"]["total"]
musicId = 1 #音乐id,用于单曲下载是使用该id找到相关音乐
musicListText.delete(0.0,END) #清空音乐列表
pageNoText.delete(0,END) #删除分页序号
pageNoText.insert(0,"第{}页".format(self.pageNo)) #插入分页序号
self.downloadMusicList.clear() #清空待下载音乐列表;每次分页后都会清空
if len(res["data"]["typeTrack"]) !=0:
for item in res["data"]["typeTrack"]:
info = "{}. {} -- {}\n".format(musicId,item["title"],item["artist"][0]["name"])
self.getMusicUrl(item,musicId,item["title"])
musicListText.insert(END,info)
musicListText.update()
musicId += 1
else:
messagebox.showinfo(title="提示", message="暂无搜索到相关歌曲!")
self.disableButton("normal")
# 获取音乐详细信息
def getMusicInfo(self,TSID):
timeStamp = self.getTimeStamp()
args = {
"sign": "",
"appid": self.appid,
"TSID": TSID,
"timestamp": timeStamp
}
signParam = "TSID={0}&appid={1}×tamp={2}{3}".format(TSID,self.appid,timeStamp,self.secret)
args["sign"] = self.md5Encode(signParam)
res = requests.get(url=self.musicInfoUrl,params=args)
return res.json()
# 处理音乐详细信息后获得音乐数据链接
def getMusicUrl(self,Info,count,title):
global musicInfo
try:
musicInfo = self.getMusicInfo(Info["assetId"])
self.downloadMusicList[count] = {"url":musicInfo["data"]["path"],"artist":title}
except: #处理不同字段下的数据
self.downloadMusicList[count] = {"url":musicInfo["data"]["trail_audio_info"]["path"],"artist":title}
time.sleep(0.1) #进行爬取时最好加上休眠时间,有些请求做了反爬处理,如果同一ip在1s内处理达到阈值会封ip
#下载音乐
def downloadMusic(self,type):
downloadNum = downloadNumText.get()
if type == "all":
for key,value in self.downloadMusicList.items():
self.download(value["url"],value["artist"])
else:
if downloadNum == "":
messagebox.showinfo(title="提示", message="请输入下载序号!!!")
else:
data = self.downloadMusicList.get(int(downloadNum))
self.download(data["url"], data["artist"])
#下载
def download(self,url,title):
if self.folderPath == "":
self.alert()
else:
path = "{0}\{1}.mp3".format(self.folderPath,title)
mess=requests.get(url)
with open(path,'wb') as f:
f.write(mess.content)
msgOutputText.insert(END,title + 5*" " + "已下载成功!" + "\n")
msgOutputText.update()
if __name__ == "__main__":
UI()