当前位置:首页 > python > 正文

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


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

这篇文章主要为大家详细介绍了python实现可下载音乐的音乐播放器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了tkinter+pygame+spider实现音乐播放器,供大家参考,具体内容如下

1.确定页面

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

songSheet.py

  #!/usr/bin/env python  # -*- coding:utf-8 -*-  # @Author: Minions  # @Date: 2019-11-24 19:51:16  # @Last Modified by: Minions  # @Last Modified time: 2019-12-17 10:01:53    import tkinter  import os  from tkinter import ttk  import time    class SongSheet(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 # 计数,共多少歌曲     def run(self):   # 搜索按钮   searchBtn = tkinter.Button(self.frame, text="更新", bg="SkyBlue",       command=self.showSheet, width=10,       height=1)     searchBtn.place(x=0, y=200)     # 显示歌单   def showSheet(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行添加   for music in musics:    # 去除空格    music = "".join(music.split(" "))    tree.insert("", 0, text=self.count, values=(music))    self.count += 1     # 鼠标选中一行回调   def selectTree(event):    for item in tree.selection():    item_text = tree.item(item, "values")    self.music = "".join(item_text)    # print(self.music)     # 选中行   tree.bind('<<TreeviewSelect>>', 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)

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

2.写出音乐控件

musicCtrl.py

  #!/usr/bin/env python  # -*- coding:utf-8 -*-  # @Author: Minions  # @Date: 2019-11-24 16:28:18  # @Last Modified by: Minions  # @Last Modified time: 2019-12-17 10:25:31    import tkinter  from tkinter import ttk  import os  import time  import pygame  from mutagen.mp3 import MP3  import random  from songSheet import SongSheet    class MusicCtrl(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) # 音乐的路径       # 整合功能   def run(self):   self.playMusic()   self.refreshName()   self.pauseMusic()   self.volume()   try:    self.songPos()   except:    print("暂无歌曲载入!")     # 播放音乐按钮   def playMusic(self):   playBtn = tkinter.Button(self.frame, text="播放", command=self.playFunc,       width=10,height=2)   playBtn.place(x=300,y=10)     # 实现播放功能   def playFunc(self):   pygame.mixer.init()   track = pygame.mixer.music.load(self.music) # 载入一个音乐文件用于播放   pygame.mixer.music.play() # 开始播放音乐流     # 暂停播放按钮   def pauseMusic(self):   pauseBtn = tkinter.Button(self.frame, text="暂停/继续",       command=self.pauseFunc,       width=10, height=2)     pauseBtn.place(x=400, y=10)     # 暂停播放功能   def pauseFunc(self):   # pygame.mixer.music.get_busy() # 检测是否正在播放音乐   if self.nowPaly:    pygame.mixer.music.pause()    self.nowPaly = False   else:    pygame.mixer.music.unpause() # 恢复音乐播放    self.nowPaly = True     # 显示歌曲名称以及歌手   def showName(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()     # 音量调节   def volume(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)     def showNum():    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)     # 音乐绝对定位   def songPos(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)   def showNum():    # 为了对一个 MP3 文件的进行绝对定位,建议首先调用 rewind()函数,不然会一直往后走    pygame.mixer.music.rewind()    if pygame.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)     # 点击歌单的歌更新名称   def refreshName(self):   refreshNameBtn = tkinter.Button(self.frame, text="update",command=self.showName,       width=10, height=2)     refreshNameBtn.place(x=45, y=50)

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

3.核心爬取音乐

music.py

  # -*- coding:utf-8 -*-  import requests, hashlib, sys, click, re, base64, binascii, json, os  from Cryptodome.Cipher import AES  from http import cookiejar    class Encrypyed():   """   解密算法   """     def __init__(self):   self.modulus = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'   self.nonce = '0CoJUm6Qyw8W8jud'   self.pub_key = '010001'     # 登录加密算法, 基于https://github.com/stkevintan/nw_musicbox脚本实现   def encrypted_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}   return data     def aes_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')   return ciphertext     def rsa_encrpt(self, text, pubKey, modulus):   text = text[::-1]   rs = pow(int(binascii.hexlify(text), 16), int(pubKey, 16), int(modulus, 16))   return format(rs, 'x').zfill(256)     def create_secret_key(self, size):   return binascii.hexlify(os.urandom(size))[:16]      class Song():   """   歌曲对象,用于存储歌曲的信息   """     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 = '' if song_url is None else song_url      class Crawler():   """   网易云爬取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 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/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 =[]     def post_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()   if result['code'] != 200:    click.echo('post_request error')   else:    return result     def search(self, search_content, search_type, limit=9):   """   搜索API   :params search_content: 搜索内容   :params search_type: 搜索类型   :params limit: 返回结果数量   :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'])     return result     def search_song(self, song_name, song_num, quiet=True, limit=20):   """   根据音乐名搜索   :params song_name: 音乐名   :params song_num: 下载的歌曲数   :params quiet: 自动选择匹配最优结果   :params limit: 返回结果数量   :return: Song独享   """     result = self.search(song_name, search_type=1, limit=limit)     if result['result']['songCount'] <= 0:    click.echo('Song {} not existed.'.format(song_name))   else:    songs = result['result']['songs']    if quiet:    self.result = [] # 更新result    for song in songs:     singers = []     # """     picUrl = song['al']['picUrl']     # """     for name in song['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)    return song     def get_song_url(self, song_id, bit_rate=320000):   """   获得歌曲的下载地址   :params song_id: 音乐ID<int>.   :params bit_rate: {'MD 128k': 128000, 'HD 320k': 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']     # 歌曲不存在   if song_url is None:    click.echo('Song {} is not available due to copyright issue.'.format(song_id))   else:    return song_url     def get_song_by_url(self, song_url, song_name, song_num, singer_name,     folder):   """   下载歌曲到本地   :params song_url: 歌曲下载地址   :params song_name: 歌曲名字   :params song_num: 下载的歌曲数   :params folder: 保存路径   """   # for res in self.result:   # print(res.song_name, res.song_id, res.singer_name)   # print("--------")   # print(song_url, song_name, singer_name)      class Netease():   """   网易云音乐下载   """     def __init__(self, timeout, folder, quiet, cookie_path):   self.crawler = Crawler(timeout, cookie_path)   self.folder = '.' if folder is None else folder   self.quiet = quiet   self.url = ''   self.pic = ''     def download_song_by_search(self, song_name):   """   根据歌曲名进行搜索   :params song_name: 歌曲名字   :params song_num: 下载的歌曲数   """     try:    song = self.crawler.search_song(song_name, self.quiet)   except:    click.echo('download_song_by_serach error')   # 如果找到了音乐, 则下载   if song != None:    self.download_song_by_id(song.song_id, song.song_name,      song.song_num, song.singer_name, self.folder)    self.pic = song.picUrl     def download_song_by_id(self, song_id, song_name, song_num, singer_name,      folder='.'):   """   通过歌曲的ID下载   :params song_id: 歌曲ID   :params song_name: 歌曲名   :params song_num: 下载的歌曲数   :params folder: 保存地址   """   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_id error')

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

searchWindows.py

  #!/usr/bin/env python  # -*- coding:utf-8 -*-  # @Author: Minions  # @Date: 2019-11-25 10:31:56  # @Last Modified by: Minions  # @Last Modified time: 2019-12-17 12:40:31    import tkinter  from tkinter import ttk  import os  from urllib import request  from music import Netease,Crawler  import requests    class SearchWindows(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)     def run(self):   self.searchBar()   self.download()     # 搜索框   def searchBar(self):   entry = tkinter.Entry(self.frame)   entry.place(width=200, height=30, x=50, y=10)     def getValue():    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)     # 显示搜索到的歌曲   def showSong(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)   for song in reversed(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     # 鼠标选中一行回调   def selectTree(event):    for item in tree.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('<<TreeviewSelect>>', selectTree)   tree.place(width=300, height=200, x=50, y=50)     # 下载选中的歌曲   def download(self):     def downloadSong():    if self.info is None:    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)

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

5.整合所有部分

main.py

  #!/usr/bin/env python  # -*- coding:utf-8 -*-  # @Author: Minions  # @Date: 2019-11-24 20:10:15  # @Last Modified by: Minions  # @Last Modified time: 2019-12-17 9:55:31    import tkinter  from searchWindows import SearchWindows  from musicCtrl import MusicCtrl  from songSheet import SongSheet  import os    win = tkinter.Tk()  win.title("Minions音乐播放器")  win.geometry("700x400")  if os.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实现可下载音乐的音乐播放器

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

标签:
上一篇: 下一篇:

暂无评论

发表评论

不理你。 不要啊! 吃饭。 吃惊。 吃西瓜。 飞吻! 恭喜! Hi 纠结! 膜拜! OK 抛媚眼。 泡泡糖。 抛钱。 忍! 生闷气! 调皮。 偷看。 委屈。 献花。 疑问? 抓狂!

小提示:Ctrl+Enter快速提交助您一臂之力~
2021-05-01 06:40:32
加载中……