python如何实现可下载音乐的音乐播放器

小编给大家分享一下python如何实现可下载音乐的音乐播放器,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

1.确定页面

SongSheet------ 显示歌单MusicCtrl ------显示音乐一些控件(播放,跳转,音量调节)SearchWindows ------搜索栏(搜索歌曲默认显示20条,可下载)

songSheet.py

#!/usr/bin/envpython
#-*-coding:utf-8-*-
#@Author:Minions
#@Date:2019-11-2419:51:16
#@LastModifiedby:Minions
#@LastModifiedtime:2019-12-1710:01:53

importtkinter
importos
fromtkinterimportttk
importtime

classSongSheet(tkinter.Frame):
def__init__(self,master):
self.frame=tkinter.Frame(master,height=230,width=300,bd=1,
bg="SkyBlue")
self.frame.place(x=0,y=0)
self.filePath="C:\Musics"
self.music=""#点击歌曲获得更新的路径
self.count=0#计数,共多少歌曲

defrun(self):
#搜索按钮
searchBtn=tkinter.Button(self.frame,text="更新",bg="SkyBlue",
command=self.showSheet,width=10,
height=1)

searchBtn.place(x=0,y=200)

#显示歌单
defshowSheet(self):
self.count=0
musics=os.listdir(self.filePath)
tree=ttk.Treeview(self.frame)
#定义列
tree["columns"]=("song")
#设置列,列还不显示
tree.column("song",width=95)

#设置表头和上面一一对应
tree.heading("song",text="song")

#添加数据往第0行添加
formusicinmusics:
#去除空格
music="".join(music.split(""))
tree.insert("",0,text=self.count,values=(music))
self.count+=1

#鼠标选中一行回调
defselectTree(event):
foritemintree.selection():
item_text=tree.item(item,"values")
self.music="".join(item_text)
#print(self.music)

#选中行
tree.bind('<>',selectTree)
tree.place(width=300,height=200,x=0,y=0)

#添加滚动条
sy=tkinter.Scrollbar(tree)
sy.pack(side=tkinter.RIGHT,fill=tkinter.Y)
sy.config(command=tree.yview)
tree.config(yscrollcommand=sy.set)

2.写出音乐控件

musicCtrl.py

#!/usr/bin/envpython
#-*-coding:utf-8-*-
#@Author:Minions
#@Date:2019-11-2416:28:18
#@LastModifiedby:Minions
#@LastModifiedtime:2019-12-1710:25:31

importtkinter
fromtkinterimportttk
importos
importtime
importpygame
frommutagen.mp3importMP3
importrandom
fromsongSheetimportSongSheet

classMusicCtrl(object):
def__init__(self,master):
self.frame=tkinter.Frame(master,height=150,width=700,bd=1,
bg="MediumSeaGreen")
self.frame.place(height=150,width=700,x=0,y=250)
self.nowPaly=True#是否正在播放音乐
self.filePath=r"C:\Musics"#从该文件夹读取
self.musicPath=""#用于拼接音乐的路径
self.songSheet=SongSheet(master)
self.songSheet.run()
self.music=os.path.join(self.filePath,self.musicPath)#音乐的路径


#整合功能
defrun(self):
self.playMusic()
self.refreshName()
self.pauseMusic()
self.volume()
try:
self.songPos()
except:
print("暂无歌曲载入!")

#播放音乐按钮
defplayMusic(self):
playBtn=tkinter.Button(self.frame,text="播放",command=self.playFunc,
width=10,height=2)
playBtn.place(x=300,y=10)

#实现播放功能
defplayFunc(self):
pygame.mixer.init()
track=pygame.mixer.music.load(self.music)#载入一个音乐文件用于播放
pygame.mixer.music.play()#开始播放音乐流

#暂停播放按钮
defpauseMusic(self):
pauseBtn=tkinter.Button(self.frame,text="暂停/继续",
command=self.pauseFunc,
width=10,height=2)

pauseBtn.place(x=400,y=10)

#暂停播放功能
defpauseFunc(self):
#pygame.mixer.music.get_busy()#检测是否正在播放音乐
ifself.nowPaly:
pygame.mixer.music.pause()
self.nowPaly=False
else:
pygame.mixer.music.unpause()#恢复音乐播放
self.nowPaly=True

#显示歌曲名称以及歌手
defshowName(self):
songName=tkinter.Label(self.frame,
fg="white",font=("华文行楷",10),bg="MediumSeaGreen",
width=25,height=1)
songName['text']=self.songSheet.music.split('.')[0]
songName.place(x=35,y=15)
self.music=os.path.join(self.filePath,self.songSheet.music)

#更换音乐后应该继续播放,并且更换音乐时长
self.playFunc()
self.songPos()

#音量调节
defvolume(self):
volumeNum=tkinter.Label(self.frame,text="volume",fg="Aquamarine",
font=("华文行楷",10),bg="MediumSeaGreen",
width=5,height=1)

volumeNum.place(x=500,y=70)

volume=tkinter.Scale(self.frame,from_=0,to=100,
orient=tkinter.HORIZONTAL)
volume.place(x=550,y=50)

defshowNum():
pygame.mixer.music.set_volume(volume.get()*0.01)#参数值范围为0.0~1.0

tkinter.Button(self.frame,text="设置",command=showNum,bg="Aqua").place(
x=550,y=100)

#音乐绝对定位
defsongPos(self):
#print(self.music.info.length)
pos=tkinter.Scale(self.frame,from_=0,to=round(
MP3(self.music).info.length),
orient=tkinter.HORIZONTAL,tickinterval=50,length=300)

pos.place(x=180,y=60)
defshowNum():
#为了对一个MP3文件的进行绝对定位,建议首先调用rewind()函数,不然会一直往后走
pygame.mixer.music.rewind()
ifpygame.mixer.music.get_busy():
self.curDuration=pos.get()
pygame.mixer.music.set_pos(self.curDuration)
else:
print("请先播放音乐!")

tkinter.Button(self.frame,text="设置",command=showNum,bg="Aqua").place(
x=490,y=90)

#点击歌单的歌更新名称
defrefreshName(self):
refreshNameBtn=tkinter.Button(self.frame,text="update",command=self.showName,
width=10,height=2)

refreshNameBtn.place(x=45,y=50)

3.核心爬取音乐

music.py

#-*-coding:utf-8-*-
importrequests,hashlib,sys,click,re,base64,binascii,json,os
fromCryptodome.CipherimportAES
fromhttpimportcookiejar

classEncrypyed():
"""
解密算法
"""

def__init__(self):
self.modulus='00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'
self.nonce='0CoJUm6Qyw8W8jud'
self.pub_key='010001'

#登录加密算法,基于https://github.com/stkevintan/nw_musicbox脚本实现
defencrypted_request(self,text):
text=json.dumps(text)
sec_key=self.create_secret_key(16)
enc_text=self.aes_encrypt(self.aes_encrypt(text,self.nonce),sec_key.decode('utf-8'))
enc_sec_key=self.rsa_encrpt(sec_key,self.pub_key,self.modulus)
data={'params':enc_text,'encSecKey':enc_sec_key}
returndata

defaes_encrypt(self,text,secKey):
pad=16-len(text)%16
text=text+chr(pad)*pad
encryptor=AES.new(secKey.encode('utf-8'),AES.MODE_CBC,b'0102030405060708')
ciphertext=encryptor.encrypt(text.encode('utf-8'))
ciphertext=base64.b64encode(ciphertext).decode('utf-8')
returnciphertext

defrsa_encrpt(self,text,pubKey,modulus):
text=text[::-1]
rs=pow(int(binascii.hexlify(text),16),int(pubKey,16),int(modulus,16))
returnformat(rs,'x').zfill(256)

defcreate_secret_key(self,size):
returnbinascii.hexlify(os.urandom(size))[:16]


classSong():
"""
歌曲对象,用于存储歌曲的信息
"""

def__init__(self,song_id,song_name,song_num,picUrl,singer_name,
song_url=None):
self.song_id=song_id
self.song_name=song_name
self.song_num=song_num
self.singer_name=singer_name
self.picUrl=picUrl
self.song_url=''ifsong_urlisNoneelsesong_url


classCrawler():
"""
网易云爬取API
"""

def__init__(self,timeout=60,cookie_path='.'):
self.headers={
'Accept':'*/*',
'Accept-Encoding':'gzip,deflate,sdch',
'Accept-Language':'zh-CN,zh;q=0.8,gl;q=0.6,zh-TW;q=0.4',
'Connection':'keep-alive',
'Content-Type':'application/x-www-form-urlencoded',
'Host':'music.163.com',
'Referer':'http://music.163.com/search/',
'User-Agent':'Mozilla/5.0(WindowsNT10.0;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/63.0.3239.132Safari/537.36'
}
self.session=requests.Session()
self.session.headers.update(self.headers)
self.session.cookies=cookiejar.LWPCookieJar(cookie_path)
self.download_session=requests.Session()
self.timeout=timeout
self.ep=Encrypyed()
self.result=[]

defpost_request(self,url,params):
"""
Post请求
:return:字典
"""

data=self.ep.encrypted_request(params)
resp=self.session.post(url,data=data,timeout=self.timeout)
result=resp.json()
ifresult['code']!=200:
click.echo('post_requesterror')
else:
returnresult

defsearch(self,search_content,search_type,limit=9):
"""
搜索API
:paramssearch_content:搜索内容
:paramssearch_type:搜索类型
:paramslimit:返回结果数量
:return:字典.
"""

url='http://music.163.com/weapi/cloudsearch/get/web?csrf_token='
params={'s':search_content,'type':search_type,'offset':0,'sub':'false','limit':limit}
result=self.post_request(url,params)
#print(result['result']['songs'][3]['ar'][0]['name'])

returnresult

defsearch_song(self,song_name,song_num,quiet=True,limit=20):
"""
根据音乐名搜索
:paramssong_name:音乐名
:paramssong_num:下载的歌曲数
:paramsquiet:自动选择匹配最优结果
:paramslimit:返回结果数量
:return:Song独享
"""

result=self.search(song_name,search_type=1,limit=limit)

ifresult['result']['songCount']<=0:
click.echo('Song{}notexisted.'.format(song_name))
else:
songs=result['result']['songs']
ifquiet:
self.result=[]#更新result
forsonginsongs:
singers=[]
#"""
picUrl=song['al']['picUrl']
#"""
fornameinsong['ar']:
singers.append(name['name'])
song_id,song_name=song['id'],song['name']
singer_name="_".join(singers)
song=Song(song_id=song_id,song_name=song_name,
song_num=song_num,singer_name=singer_name,picUrl=picUrl)
self.result.append(song)
picUrl=songs[0]['al']['picUrl']
#"""
song_id,song_name=songs[0]['id'],songs[0]['name']
song=Song(song_id=song_id,song_name=song_name,
song_num=song_num,singer_name=self.result[0].singer_name,
picUrl=picUrl)
returnsong

defget_song_url(self,song_id,bit_rate=320000):
"""
获得歌曲的下载地址
:paramssong_id:音乐ID.
:paramsbit_rate:{'MD128k':128000,'HD320k':320000}
:return:歌曲下载地址
"""

url='http://music.163.com/weapi/song/enhance/player/url?csrf_token='
csrf=''
params={'ids':[song_id],'br':bit_rate,'csrf_token':csrf}
result=self.post_request(url,params)
#歌曲下载地址
song_url=result['data'][0]['url']

#歌曲不存在
ifsong_urlisNone:
click.echo('Song{}isnotavailableduetocopyrightissue.'.format(song_id))
else:
returnsong_url

defget_song_by_url(self,song_url,song_name,song_num,singer_name,
folder):
"""
下载歌曲到本地
:paramssong_url:歌曲下载地址
:paramssong_name:歌曲名字
:paramssong_num:下载的歌曲数
:paramsfolder:保存路径
"""
#forresinself.result:
#print(res.song_name,res.song_id,res.singer_name)
#print("--------")
#print(song_url,song_name,singer_name)


classNetease():
"""
网易云音乐下载
"""

def__init__(self,timeout,folder,quiet,cookie_path):
self.crawler=Crawler(timeout,cookie_path)
self.folder='.'iffolderisNoneelsefolder
self.quiet=quiet
self.url=''
self.pic=''

defdownload_song_by_search(self,song_name):
"""
根据歌曲名进行搜索
:paramssong_name:歌曲名字
:paramssong_num:下载的歌曲数
"""

try:
song=self.crawler.search_song(song_name,self.quiet)
except:
click.echo('download_song_by_seracherror')
#如果找到了音乐,则下载
ifsong!=None:
self.download_song_by_id(song.song_id,song.song_name,
song.song_num,song.singer_name,self.folder)
self.pic=song.picUrl

defdownload_song_by_id(self,song_id,song_name,song_num,singer_name,
folder='.'):
"""
通过歌曲的ID下载
:paramssong_id:歌曲ID
:paramssong_name:歌曲名
:paramssong_num:下载的歌曲数
:paramsfolder:保存地址
"""
try:
url=self.crawler.get_song_url(song_id)
#去掉非法字符
song_name=song_name.replace('/','')
song_name=song_name.replace('.','')
self.crawler.get_song_by_url(url,song_name,song_num,
singer_name,folder)

except:
click.echo('download_song_by_iderror')

4.将爬取音乐搜索栏整合

searchWindows.py

#!/usr/bin/envpython
#-*-coding:utf-8-*-
#@Author:Minions
#@Date:2019-11-2510:31:56
#@LastModifiedby:Minions
#@LastModifiedtime:2019-12-1712:40:31

importtkinter
fromtkinterimportttk
importos
fromurllibimportrequest
frommusicimportNetease,Crawler
importrequests

classSearchWindows(tkinter.Frame):
def__init__(self,master):
self.frame=tkinter.Frame(master,height=240,width=500,bd=1,
bg="Purple")

self.songs=None#搜索到的所有歌曲(20)的信息
self.frame.place(x=300,y=0)
self.info=None#当前歌曲的信息
self.fileName="C:\Musics\\"

timeout=60
output='Musics'
quiet=True
cookie_path='Cookie'
self.netease=Netease(timeout,output,quiet,cookie_path)

defrun(self):
self.searchBar()
self.download()

#搜索框
defsearchBar(self):
entry=tkinter.Entry(self.frame)
entry.place(width=200,height=30,x=50,y=10)

defgetValue():
self.netease.download_song_by_search(entry.get())
self.songs=self.netease.crawler.result
self.showSong()

searchBtn=tkinter.Button(self.frame,text="搜索",bg="DarkOrchid",
command=getValue,width=10,height=1)

searchBtn.place(x=270,y=10)

#显示搜索到的歌曲
defshowSong(self):
tree=ttk.Treeview(self.frame)
#定义列
tree["columns"]=("song","singer","url")

#设置列,列还不显示
tree.column("song",width=50)
tree.column("singer",width=50)
tree.column("url",width=50)

#设置表头和上面一一对应
tree.heading("song",text="song")
tree.heading("singer",text="singer")
tree.heading("url",text="url")

count=len(self.songs)
forsonginreversed(self.songs):
url=self.netease.crawler.get_song_url(song.song_id)
tree.insert("",0,text=count,values=(song.song_name,
song.singer_name,url))
count-=1

#鼠标选中一行回调
defselectTree(event):
foritemintree.selection():
item_text=tree.item(item,"values")
self.info=item_text

#滚动条
sy=tkinter.Scrollbar(tree)
sy.pack(side=tkinter.RIGHT,fill=tkinter.Y)
sy.config(command=tree.yview)
tree.config(yscrollcommand=sy.set)

#选中行
tree.bind('<>',selectTree)
tree.place(width=300,height=200,x=50,y=50)

#下载选中的歌曲
defdownload(self):

defdownloadSong():
ifself.infoisNone:
print("该歌曲下载失败")
else:
request.urlretrieve(self.info[2],
self.fileName+self.info[1]+'-'+self.info[0]+'.mp3')
print("%s-%s下载成功"%(self.info[1],self.info[0]))

#下载按钮
downloadBtn=tkinter.Button(self.frame,text="下载",bg="DarkOrchid",
command=downloadSong,width=6,height=1)

downloadBtn.place(x=345,y=200)

5.整合所有部分

main.py

#!/usr/bin/envpython
#-*-coding:utf-8-*-
#@Author:Minions
#@Date:2019-11-2420:10:15
#@LastModifiedby:Minions
#@LastModifiedtime:2019-12-179:55:31

importtkinter
fromsearchWindowsimportSearchWindows
frommusicCtrlimportMusicCtrl
fromsongSheetimportSongSheet
importos

win=tkinter.Tk()
win.title("Minions音乐播放器")
win.geometry("700x400")
ifos.path.exists("C:/Musics"):
print("xxx")
else:
os.mkdir("C:/Musics")

searchWin=SearchWindows(win)
searchWin.run()

songSheetWin=SongSheet(win)
songSheetWin.run()

musicWin=MusicCtrl(win)
musicWin.run()

win.mainloop()

以上是“python如何实现可下载音乐的音乐播放器”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注恰卡编程网行业资讯频道!

发布于 2021-03-24 01:21:06
分享
海报
164
上一篇:python如何实现堆排序 下一篇:如何使用python实现人脸识别经典算法
目录

    推荐阅读

    忘记密码?

    图形验证码