基于wx的 python音乐播放机

# -*- coding: utf-8 -*-
"""
Created on Sat Apr 25 18:15:36 2020

@author: Administrator
"""
import requests
import binascii
import json
import datetime
import traceback
from Crypto.Cipher import AES
from tkinter import *

FAKE_HEADERS = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',  # noqa
    'Accept-Charset': 'UTF-8,*;q=0.5',
    'Accept-Encoding': 'gzip,deflate,sdch',
    'Accept-Language': 'en-US,en;q=0.8',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101 Firefox/60.0',  # noqa
    'referer': 'https://www.google.com'
}
def netease_search(keyword) -> list:
    ''' 从网易云音乐搜索 '''
    count = 30
    eparams = {
        'method': 'POST',
        'url': 'http://music.163.com/api/cloudsearch/pc',
        'params': {
            's': keyword,
            'type': 1,
            'offset': 0,
            'limit': count
        }
    }
    data = {'eparams': encode_netease_data(eparams)}

    s = requests.Session()
    s.headers.update(FAKE_HEADERS)
    s.headers.update({
        'referer': 'http://music.163.com/',
    })
 

    r = s.post('http://music.163.com/api/linux/forward', data=data)

   
    j = r.json()


    music_list = []
    ID=0
    try:
        for m in j['result']['songs']:
            if m['privilege']['fl'] == 0:
                # 没有版权
                continue
            # 获得歌手名字
            singers = []
            for singer in m['ar']:
                singers.append(singer['name'])
            # 获得最优音质的文件大小
            if m['privilege']['fl'] >= 320000 and 'h' in m.keys() and m['h']:
                # 有时候即使>=320000,h属性依然为None
                size = m['h']['size']
            elif m['privilege']['fl'] >= 192000 and 'm' in m.keys() and m['m']:
                size = m['m']['size']
            else:
                size = m['l']['size']

            music = {
                'title': m['name'],
                'id': m['id'],
                'duration': str(datetime.timedelta(seconds=int(m['dt']/1000))),
                'singer': ''.join(singers),
                'album': m['al']['name'],
                'size': round(size / 1048576, 2),
                'source': 'netease'
            }
            music=[]
            print(m['name'])
            music.append(ID)
            music.append(m['name'])
            music.append(''.join(singers))
            href="http://music.163.com/song/media/outer/url?id="+str(m['id'])+".mp3"
            print(href)
            music.append(href)
            music.append(m['id'])
            music_list.append(music)
            ID=ID+1
            
    except Exception:
        # 如果是详细模式则输出详细错误信息
#        err = traceback.format_exc() if glovar.get_option('verbose') else str(e)
#        raise DataError(err)
        
        pass

    return music_list





def encode_netease_data(data) -> str:
    data = json.dumps(data)
    key = binascii.unhexlify('7246674226682325323F5E6544673A51')
    encryptor = AES.new(key, AES.MODE_ECB)
    # 补足data长度,使其是16的倍数
    pad = 16 - len(data) % 16
    fix = chr(pad) * pad
    byte_data = (data + fix).encode('utf-8')
    return binascii.hexlify(encryptor.encrypt(byte_data)).upper().decode()

def QQ_search(keyword):
    import urllib.parse as parse
    from urllib.request import urlretrieve
    import requests
    import json
    import os
    import time
    import sys
    w=parse.urlencode({'w':keyword})
    
 
    url='https://c.y.qq.com/soso/fcgi-bin/client_search_cp?ct=24&qqmusic_ver=1298&new_json=1&remoteplace=txt.yqq.song&searchid=63229658163010696&t=0&aggr=1&cr=1&catZhida=1&lossless=0&flag_qc=0&p=1&n=30&%s&g_tk=5381&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0'%(w)
     
    content=requests.get(url=url)
     
    str_1=content.text
     
    dict_1=json.loads(str_1)
     
    song_list=dict_1['data']['song']['list']
     
    str_3='''https://u.y.qq.com/cgi-bin/musicu.fcg?-=getplaysongvkey5559460738919986&g_tk=5381&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0&data={"req":{"module":"CDN.SrfCdnDispatchServer","method":"GetCdnDispatch","param":{"guid":"1825194589","calltype":0,"userip":""}},"req_0":{"module":"vkey.GetVkeyServer","method":"CgiGetVkey","param":{"guid":"1825194589","songmid":["%s"],"songtype":[0],"uin":"0","loginflag":1,"platform":"20"}},"comm":{"uin":0,"format":"json","ct":24,"cv":0}}'''
     
    
    ID=0
    music_list=[]
    url_list=[]
    for i in range(len(song_list)):
        
#        music_name.append(song_list[i]['name']+'-'+song_list[i]['singer'][0]['name'])
     
    #    print('{}.{}-{}'.format(i+1,song_list[i]['name'],song_list[i]['singer'][0]['name']))
        url_list.append(str_3 % (song_list[i]['mid']))
    #    
#        print(url_list[id-1])


        music=[]
#        print(m['songname'])
        music.append(ID)
        music.append(song_list[i]['name'])
        music.append(song_list[i]['singer'][0]['name'])
        content_json=requests.get(url=url_list[ID])
 
        dict_2=json.loads(content_json.text)
         
        url_ip=dict_2['req']['data']['freeflowsip'][1]
         
        purl=dict_2['req_0']['data']['midurlinfo'][0]['purl']
         
        href=url_ip+purl
        music.append(href)
        music.append(song_list[i]['mid'])
        music_list.append(music)
        ID=ID+1

        

    return music_list

import wx  
import time



    

def music_play(arr):
    print("双击函数已启动")
#    必须加上全局变量,否则不唱歌
    
    global mp3
    import mp3play
    path="http://m10.music.126.net/20200414222927/e509cfbb086d358e701e6bb5cfedfeaa/ymusic/0759/030f/540b/039ace5c004ebd382de4ca163145cf9b.mp3"
    path=arr[3]
    print("path:-->"+path)
    mp3 = mp3play.load(path)
    mp3.play()
def music_pyplay(arr):
    import os
    import time
    import pygame
    
    source_file_path=arr[3]
    pygame.mixer.init()
    pygame.mixer.music.load(source_file_path)
    pygame.mixer.music.set_volume(0.5) 
    pygame.mixer.music.play(-1)
    
    
class MyFrame(wx.Frame):  
    def __init__(self):  
        wx.Frame.__init__(self, None, -1, 'Button Example',   
                size=(1300, 700),pos=(-10,0))  
        panel = wx.Panel(self, -1)  
        panel.SetSize(1300,700)
        panel.SetBackgroundColour("#D2B48C")
        
       
        
        
        self.sousuotxt = wx.TextCtrl(panel,pos=(0,0),size = (100,30)) 
        lblList = ['网易', 'QQ', '酷狗'] 
          
        self.rbox = wx.RadioBox(panel, label = '', pos = (100,-15),size = (100,30), choices = lblList,majorDimension = 1, style = wx.RA_SPECIFY_ROWS) 
        self.rbox.Bind(wx.EVT_RADIOBOX,self.onRadioBox) 
        
        self.button = wx.Button(panel, -1, "搜索", pos=(350, 0))  
        self.Bind(wx.EVT_BUTTON, self.OnClick, self.button)  
        
        self.mylove = wx.Button(panel, -1, "同步我喜欢的音乐", pos=(500, 0))  
        self.Bind(wx.EVT_BUTTON, self.Dmylove, self.mylove)  
        
        
        languages = [] 
        for i in range(1000):
            languages.append(str(i))
        
        self.choice = wx.Choice(panel,choices = languages,pos=(0,30))
        self.choice.SetStringSelection("0")
        
        
        self.button5 = wx.Button(panel, -1, "本地文件", pos=(50, 30))  
        self.Bind(wx.EVT_BUTTON, self.OnButton, self.button5)  
        
        self.button1 = wx.Button(panel, -1, "播放", pos=(150, 30))  
        self.Bind(wx.EVT_BUTTON, self.OnClick1, self.button1)  
        
        self.button2 = wx.Button(panel, -1, "暂停", pos=(250, 30))  
        self.Bind(wx.EVT_BUTTON, self.OnClick2, self.button2)  
        
        self.button3 = wx.Button(panel, -1, "下载", pos=(350, 30))  
        self.Bind(wx.EVT_BUTTON, self.OnClick3, self.button3)  
        
        
        font = wx.Font(15, wx.DEFAULT, wx.FONTSTYLE_NORMAL, wx.NORMAL) 

        self.music_ID = wx.StaticText(panel, label = "ID", pos = (0,100),size=(30,500),style=wx.ALIGN_CENTER) 
        self.music_ID.SetBackgroundColour("#D2B48C")
        self.music_ID.SetFont(font)

        self.music_name = wx.StaticText(panel, label = "歌名", pos = (30,100),size=(400,500),style=wx.ALIGN_CENTER) 
        self.music_name.SetBackgroundColour("#D2B48C")
        self.music_name.SetFont(font)                                   
        
                       
        
        
        languages = [] 
        for i in range(1,100):
            languages.append(""+str(i)+"")
        
        self.pagenum = wx.Choice(panel,choices = languages,pos=(50,600)) 
        self.pagenum.SetStringSelection("第1页")
        self.button4 = wx.Button(panel, -1, "跳转", pos=(150, 600))  
        self.Bind(wx.EVT_BUTTON, self.OnClick4, self.button4) 
        
        self.prepage = wx.Button(panel, -1, "上一页", pos=(250, 600))  
        self.Bind(wx.EVT_BUTTON, self.PrePage, self.prepage) 
        
        self.nextpage = wx.Button(panel, -1, "下一页", pos=(350, 600))  
        self.Bind(wx.EVT_BUTTON, self.NextPage, self.nextpage) 
        
        
        
        
        self.path="D://downmusic/歌曲"
        self.music_arr=[]
        
        self.getfile()
        self.setData()
        
        
        self.key1="本地音乐"
    def onRadioBox(self,event):
        
#      print (self.rbox.GetStringSelection(),' is clicked from Radio Box' )
       
        pass
    def OnClick(self, event):  
        self.rbox.GetStringSelection()
        print(self.rbox.GetStringSelection())
        rboxtext=self.rbox.GetStringSelection()
        if rboxtext=="网易":
            s=self.sousuotxt.GetValue()
            self.music_arr=netease_search(s)
            print(self.music_arr)
            self.setData()
            print("搜索")
            self.key1="在线音乐"
        elif rboxtext=="QQ":
            s=self.sousuotxt.GetValue()
            self.music_arr=QQ_search(s)
            print(self.music_arr)
            self.setData()
            print("搜索")
            self.key1="在线音乐"
        else:
            pass
        
        
            
            
            
        
            
            
        
        
    
        
        
        
#播放
    def OnClick1(self, event):  
#        self.button1.SetLabel("Clicked") 
        print("播放")
        
        y=self.choice.GetStringSelection()
        for i in self.music_arr:
            if y==str(i[0]):
                if self.key1=="在线音乐":
                
                    music_play(i)
                    
                else:
                    self.music_pyplay(i)
                    
                    
    def music_pyplay(self,arr):
        import os
        import time
        import pygame
        
        source_file_path=arr[3]
        pygame.mixer.init()
        pygame.mixer.music.load(source_file_path)
        pygame.mixer.music.set_volume(0.5) 
        pygame.mixer.music.play(-1)
        
        import os
        path="D://downmusic/歌词/"        
        import pygame
        import time
        import os
        f_url=""
        if arr[2]=="sen":
            
            f_url=path+str(arr[1])+".lrc"
        else:
            f_url=path+str(arr[1])+"-"+str(arr[2])+".lrc"
        
            
        f=open(f_url)
        s=""
        for i in f.readlines():
            if i[1]!="0":
                pass
            else:
                s=s+i
            
        print(s)
        f.close()
        strLrc=s
        
        f.close()
        dictLrc = {}
        # 对歌词进行按行切割
        lineListLrc = strLrc.splitlines()
        # 遍历每一行歌词
        geci=""
        for lineLrc in lineListLrc:
            # 时间和歌词分开
            listLrc = lineLrc.split("]")
            timeLrc = listLrc[0][1:].split(':')
            # 转换时间格式
            times = float(timeLrc[0]) * 60 + float(timeLrc[1])
            # 把时间当做key,歌词当做value存放在字典中
            dictLrc[times] = listLrc[1]
            geci=geci+listLrc[1]+"\n"
        tempTime = 0
        # 音频初始化
        
        
        root = Tk() # 初始化Tk()
        root.overrideredirect(True)#隐藏标题栏
        root.title("label-test")    # 设置窗口标题
        root.geometry("1300x800+0+0")    # 设置窗口大小 注意:是x 不是*
        root.resizable(width=True, height=True) # 设置窗口是否可以变化长/宽,False不可变,True可变,默认为True
        l = Label(root, text="label", bg="pink", font=("Arial",60), width=300, height=800)
        l["text"]="wusen"
        
        # 加载音频文件路径 (路径必须真实存在,音频文件格式支持mp3/ogg等格式)
        for key in dictLrc.keys():
            tempTime = key - tempTime
            # 判断是否在播放音乐
            if not pygame.mixer.music.get_busy():
                pygame.mixer.music.play()
            # 歌词显示的时间
            time.sleep(tempTime)
            # 显示歌词
            print(dictLrc[key])
            
            tempTime = key
            import time
        #    time.sleep(1)
        #    music_IRC.SetLabel(time.strftime("%H:%M:%S",time.localtime(time.time())))   
            print(time.strftime("%H:%M:%S",time.localtime(time.time())))
#            l["text"]=time.strftime("%H:%M:%S",time.localtime(time.time()))
            l["text"]=dictLrc[key]
            
            l.pack(side=TOP)
            l.update()
        root.destroy()
#       print(s)
    
#       暂停         
    def OnClick2(self, event):  
#        self.button2.SetLabel("Clicked") 
        print("暂停")
#        下载
    def OnClick3(self, event):  
        
        y=self.choice.GetStringSelection()
#        self.button3.SetLabel("Clicked") 
        print("下载")
        print(y)
        
        for i in self.music_arr:
            if y==str(i[0]):
                self.down_music(i)
#        跳转
    def down_music(self,arr):
    
        self.rbox.GetStringSelection()
        print(self.rbox.GetStringSelection())
        rboxtext=self.rbox.GetStringSelection()
        if rboxtext=="网易":
            headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36'}
    
            import requests
            url=arr[3]
            name=str(arr[1])+"-"+str(arr[2])
            res=requests.get(url,headers=headers)
            print(res)
            m=res.content
            mv=open("D://downmusic/歌曲/"+name+".mp3","wb")
            mv.write(m)
            mv.close()
            #    下载歌词
            import requests
            import json
            import os
            url = 'http://music.163.com/api/song/lyric?'+ 'id=' + str(arr[4])+ '&lv=1&kv=1&tv=-1'
            r = requests.get(url,headers=headers)
            json_obj = r.text
            print(r.text)
            print(url)
            j = json.loads(json_obj)
            print(j['lrc']['lyric'])
            f=open("D://downmusic/歌词/"+name+".lrc","w")
            f.write(j['lrc']['lyric'])
            f.close()
        elif rboxtext=="QQ":
            headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36'}
    
            import requests
            url=arr[3]
            name=str(arr[1])+"-"+str(arr[2])
            res=requests.get(url,headers=headers)
            print(res)
            m=res.content
            QQmusicpath="D://downmusic/歌曲/"+name+".mp3"
            mv=open(QQmusicpath,"wb")
            mv.write(m)
            mv.close()
                
                
                
            import os
            s="e://python/ffmpeg-20200403-52523b6-win64-static/bin/ffmpeg  -i  D://downmusic/歌曲/a.mp3  "+QQmusicpath
            os.system(s)
            os.remove("D://downmusic/歌曲/a.mp3")
            #    下载歌词
            pass
        else:
            pass
    def OnClick4(self, event):  
            
        self.setData()
        
    
        
#刷新页面赋值内容
    def setData(self):
        y=self.pagenum.GetStringSelection()
#        self.button4.SetLabel("Clicked") 
        print("跳转")
        print(y)
        ID=""
        name=""
        singer=""
        
        for i in self.music_arr[(int(y[1:-1])-1)*10:(int(y[1:-1])-1)*10+10]:
            ID=ID+str(i[0])+"\n"+"----\n"
            name=name+str(i[1])+"-"+str(i[2])+"\n"+"------------------------------------------------------------------------------------------\n"
#            singer=singer+str(i[2])+"\n"+"----------\n"
            
        self.music_ID.SetLabel(ID)
        self.music_name.SetLabel(name)
#        self.music_singer.SetLabel(singer)

    def getfile(self):
        self.music_arr.clear()
        import os
        
        local_url=self.path+"/"
    
        if os.path.isdir(local_url):
            pass
        else:
            os.mkdir(local_url)
            print("路径已创建")
        file = os.listdir(self.path)
        
        j=0
        for i in file:
            
            k=[]
            music_name=i[:-4].split("-", 1)[0]
            try:
                
                music_singer=i[:-4].split("-", 1)[1]
            except:
                music_singer="sen"
            music_ID="0"
            music_edition="本地歌曲"
            music_url=self.path+"/"+i
            k.append(j)
            k.append(music_name)
            k.append(music_singer)
            k.append(music_url)
            k.append(music_edition)
            print(j)
            print(music_name)
            print(music_singer)
            print(music_url)
            print(music_edition)
            print("----------")
            self.music_arr.append(k)
            j=j+1
        self.key1="本地音乐"
#        选择本地文件
    def OnButton(self, event):
        """"""
        dlg = wx.DirDialog(self,u"选择文件夹",style=wx.DD_DEFAULT_STYLE)
        if dlg.ShowModal() == wx.ID_OK:
            print(dlg.GetPath()) #文件夹路径
            self.path=dlg.GetPath()
        dlg.Destroy()
        
        self.getfile()
        self.setData()
#        下一页
    def NextPage(self,event):
        y=self.pagenum.GetStringSelection()
        self.pagenum.SetStringSelection(""+str(int(y[1:-1])+1)+"")
        self.setData()
#        上一页
    def PrePage(self,event):
        y=self.pagenum.GetStringSelection()
        self.pagenum.SetStringSelection(""+str(int(y[1:-1])-1)+"")
        self.setData()
        
        
    def Dmylove(self,event):
#        同步网易云音乐
        
        import requests
        from bs4 import BeautifulSoup
        import urllib.request
        from lxml import html
        etree = html.etree
        #这里是设置请求头
        headers = {
            'Referer': 'http://music.163.com/',
            'Host': 'music.163.com',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
        }
         
        # 歌单的url地址这里改id
        play_url = 'http://music.163.com/playlist?id=587771511'
        s = requests.session()
        response = s.get(play_url, headers=headers).content
        # 使用bs4匹配出对应的歌曲名称和地址
        s = BeautifulSoup(response, 'lxml')
        main = s.find('ul', {'class': 'f-hide'})
        #print(main.find_all('a'))
        lists = []
        for music in main.find_all('a'):
            list = []
            # print('{} : {}'.format(music.text, music['href']))
            musicUrl = 'http://music.163.com/song/media/outer/url' + music['href'][5:] + '.mp3'
            musicName = music.text
            # 单首歌曲的名字和地址放在list列表中
            list.append(musicName)
            list.append(musicUrl)
            
            list.append(music['href'][9:])
            # 全部歌曲信息放在lists列表中
            lists.append(list)
        # 下载列表中的全部歌曲,并以歌曲名命名下载后的文件,文件位置为当前文件夹
        for i in lists:
            url = i[1]
            name = i[0]
            try:
                import os
                if os.path.exists("d:/downmusic/歌曲/"+name+".mp3"):
                    pass
                else:
                    
                
                    print('正在下载', name)
                    #这里修改路径,随便指定盘符,但是得存在
                    urllib.request.urlretrieve(url, 'd:/downmusic/歌曲/%s.mp3' % name)
                    import requests
                    import json
                    
                    
                    url = 'http://music.163.com/api/song/lyric?'+ 'id=' + str(i[2])+ '&lv=1&kv=1&tv=-1'
                    r = requests.get(url,headers=headers)
                    json_obj = r.text
                    print(r.text)
                    print(url)
                    j = json.loads(json_obj)
                    print(j['lrc']['lyric'])
                    f=open("d://downmusic/歌词/"+name+".lrc","w")
                    f.write(j['lrc']['lyric'])
                    f.close()
                    print('下载成功')
            except:
                print('下载失败')
if __name__ == '__main__':  
    app = wx.PySimpleApp()  
    frame = MyFrame()  
    
    frame.Show() 
    
    
    app.MainLoop() 
    
    
    
    
    

    

    
    

#
#pyinstaller -D -w WX音乐播放器.py  -p D:/anaconda/Lib/site-packages
#    pyinstaller -D  WX音乐播放器.py  -p D:/anaconda/Lib/site-packages
#    
#pyinstaller -D WX音乐播放器.py 
View Code

 

posted @ 2020-10-10 20:36    阅读(131)  评论(0编辑  收藏  举报