一起用python做个炫酷音乐播放器,想听啥随便搜!【V2

50 阅读9分钟
self.tab5 = QWidget()
self.tab5.setObjectName("tab5")
self.tab5_layout = QGridLayout()
self.tab5.setLayout(self.tab5_layout)
self.listwidget5 = QListWidget(self.tab5)
self.listwidget5.doubleClicked.connect(lambda: self.change(self.listwidget5))
self.listwidget5.setContextMenuPolicy(Qt.CustomContextMenu)
self.listwidget5.customContextMenuRequested[QPoint].connect(self.myListWidgetContext5)
self.button_12351 = QPushButton(icon('fa.download', color='#D0D0D0', font=24), "添加目录")
self.button_12351.clicked.connect(self.add)
self.button_12351.setStyleSheet(
    '''QPushButton{background:#222225;border-radius:5px;}QPushButton:hover{background:#303030;}''')
self.tab5_layout.addWidget(self.button_12351, 0, 2, 1, 1)

self.button_12361 = QPushButton(icon('fa.trash-o', color='#D0D0D0', font=24), "清空列表")
self.button_12361.clicked.connect(self.dellocal)
self.button_12361.setStyleSheet(
    '''QPushButton{background:#222225;border-radius:5px;}QPushButton:hover{background:#303030;}''')
self.tab5_layout.addWidget(self.button_12361, 0, 3, 1, 1)
self.listwidget5.setStyleSheet(self.css)
self.listwidget5.setObjectName("listWidget5")
self.tab5_layout.addWidget(self.listwidget5, 1, 0, 1, 4)
self.tabWidget.addTab(self.tab5, " 本地歌曲 ")
self.right_layout.addWidget(self.tabWidget, 3, 0, 100, 90)

UI界面布局实现效果如下:  
 ![在这里插入图片描述](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/6215aaf0a90d473ab1525a76849aa183~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3NTc5MjMwMTY3MDI=:q75.awebp?rk3s=f64ab15b&x-expires=1773223615&x-signature=HPR%2F1AqnGIo39qVZjgCswvF63%2FI%3D)


##### 2. 音乐本地下载及添加我喜爱的歌曲


我们根据V1.0版本完成的,**输入的关键字和选择音乐来源**进行音乐爬取,通过多线程,将歌曲、歌手、歌曲url地址全都获取;并将这些爬取的音乐数据列表显示到搜索页面中。双击列表页面中某一首歌曲,即可实现音乐播放功能。


V2.0版本中,我们添加了对当前播放音乐的本地下载、搜索页音乐列表一键下载、喜爱的歌列表一键下载、添加我喜爱的歌曲功能。


**音乐下载:**


对于音乐下载,我们可以进行当前播放音乐下载、搜索页音乐列表一键下载、喜爱的歌一键下载。如下图所示:![在这里插入图片描述](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/beed793d894745ebbeb8bd2c09b8cc15~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3NTc5MjMwMTY3MDI=:q75.awebp?rk3s=f64ab15b&x-expires=1773223615&x-signature=etY%2Bl12jcFSabze8dcb8HIGfNdE%3D)  
 核心代码如下:



当前播放音乐下载

def down(self): if bo == 'local': downpath = str(filew) downpath = downpath.replace('/', '\') downpath = downpath + SongName[num] print(downpath) print('explorer /select,{}'.format(downpath)) call('explorer /select,{}'.format(downpath)) else: call('explorer /select,{}'.format(to))

下载所有音乐

def downloadall(self, typer): try: global typerr typerr = typer print(typer) print(typerr) self.work = downall() self.work.start() self.work.trigger.connect(self.disdownall) except: print('默认图片下载错误') pass

下载搜索页列表所有音乐

def downloadalls(self): self.downloadall('boing')

下载喜爱的歌列表所有音乐

def downloadalllove(self): self.downloadall('love')


**添加喜爱的歌:**


对于添加喜爱的歌曲,我们可以通过当前播放音乐的❤标志,也可以通过右键音乐列表进行喜爱的歌曲添加。核心代码如下:



通过点击❤标志,对当前播放音乐添加喜爱的歌

def lovesong(self): if bo == 'boing' or bo == 'boed': try: global loves global loveurls global lovepics global lovelrc if bo == 'boing': loves.append(songs[num]) loveurls.append(urls[num]) lovepics.append(pic[num]) lovelrc.append(lrcs[num]) elif bo == 'boed': loves.append(songed[num]) loveurls.append(urled[num]) lovepics.append(picd[num]) lovelrc.append(lrcd[num]) else: pass except: pass self.work = firstThread() self.work.start() self.work.trigger.connect(self.dispng) r = 0 self.listwidget3.clear() for i in loves: self.listwidget3.addItem(i) self.listwidget3.item(r).setForeground(Qt.white) r = r + 1 print(loves) else: pass

通过右键音乐列表进行喜爱的歌曲添加

def addItem(self): try: global loves global loveurls global lovepics global lovelrc if list_confident == 'boing': loves.append(songs[num_m]) loveurls.append(urls[num_m]) lovepics.append(pic[num_m]) lovelrc.append(lrcs[num_m]) else: loves.append(songed[num_m]) loveurls.append(urled[num_m]) lovepics.append(picd[num_m]) lovelrc.append(lrcd[num_m]) self.work = firstThread() self.work.start() self.work.trigger.connect(self.dispng) except: pass r = 0 self.listwidget3.clear() for i in loves: self.listwidget3.addItem(i) self.listwidget3.item(r).setForeground(Qt.white) r = r + 1 print('done') print(loves)


这样我们就可以把歌曲添加到喜爱的歌子列表页面下,如下图所示。  
 ![在这里插入图片描述](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/4d798649c8ce4253ade2d94104de2168~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3NTc5MjMwMTY3MDI=:q75.awebp?rk3s=f64ab15b&x-expires=1773223615&x-signature=kceUR9D1KWbrNkHfKCu2zDaFl%2Bw%3D)


##### 3. 喜爱的歌初始化读取显示及列表播放


对于添加到喜爱的歌曲列表,我们需要在退出音乐播放器程序时,将这些数据保存到本地文件,方便后面重新运行时初始化读取显示列表。


**喜爱歌曲本地保存:**  
 我们可以把喜爱的歌曲列表、喜爱歌曲图片、歌曲url链接、歌词等数据保存到本地。核心代码如下:



def close(self): reply = QMessageBox.question(self, u'警告', u'确定退出?', QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: close = True try: mixer.music.stop() except: pass try: rmtree(str(data)) except Exception as e: print('删除错误类型是', e.class.name) print('删除错误明细是', e) filepath = '{}/musicdata'.format(apdata) try: mkdir(filepath) except: pass print(filepath) with open(filepath + "/loves", 'w', encoding='utf-8') as f: f.truncate(0) print(f.write(str(loves))) with open(filepath + "/lovepics", 'w', encoding='utf-8') as f: f.truncate(0) print(f.write(str(lovepics))) with open(filepath + "/loveurls", 'w', encoding='utf-8') as f: f.truncate(0) print(f.write(str(loveurls))) with open(filepath + "/lovelrc", 'w', encoding='utf-8') as f: f.truncate(0) print(f.write(str(lovelrc))) with open(filepath + "/voice", 'w', encoding='utf-8') as f: f.truncate(0) print(f.write(str(voice))) try: rmtree(str(data)) except Exception as e: print('删除错误类型是', e.class.name) print('删除错误明细是', e) exit() else: pass


**喜爱的歌初始化读取:**  
 重新运行音乐播放器时,我们需要加载保存在本地的喜爱歌曲数据,并将歌曲列表信息加载显示到喜爱的歌子列表页面中。核心代码如下:



def run(self): try: apdataas = getenv("APPDATA") filepathas = '{}/musicdata'.format(apdataas) global lovelrc global loveurls global loves global lovepics global voice # 读取历史数据开始 try: with open(filepathas + "/voice", 'r', encoding='utf-8') as f: a = f.read() # print(a) voice = float(a) print(voice) self.trigger.emit(str('voicedone')) except: self.trigger.emit(str('voicedone')) pass with open(filepathas + "/loves", 'r', encoding='utf-8') as f: a = f.read() print(a) strer = a loves = literal_eval(strer) with open(filepathas + "/lovepics", 'r', encoding='utf-8') as f: a = f.read() print(a) strer = a lovepics = literal_eval(strer) with open(filepathas + "/loveurls", 'r', encoding='utf-8') as f: a = f.read() print(a) strer = a loveurls = literal_eval(strer) with open(filepathas + "/lovelrc", 'r', encoding='utf-8') as f: a = f.read() print(a) strer = a lovelrc = literal_eval(strer) self.trigger.emit(str('login')) print(loves) print('read finish') except: print('read error') pass # 读取数据结束

# 下载喜爱的歌列表中首项的歌曲封面
try:
    req = get(lovepics[0])
    checkfile = open(str(data + '/ls3.png'), 'w+b')
    for i in req.iter_content(100000):
        checkfile.write(i)

    checkfile.close()
    lsfile = str(data + '/ls3.png')
    safile = str(data + '/first.png')
    draw(lsfile, safile)
    self.trigger.emit(str('first'))
except:
    self.trigger.emit(str('nofirst'))
    pass    

**列表播放:**  
 对于加载的喜爱歌曲列表,我们可以对歌曲进行列表一键播放。



音乐播放

def bofang(self, num, bo): print('尝试进行播放') try: import urllib global pause global songs global music global downloading downloading = True self.console_button_3.setIcon(icon('fa.pause', color='#F76677', font=18)) pause = False try: mixer.stop() except: pass mixer.init() try: self.Timer = QTimer() self.Timer.start(500) except: pass try: self.label.setText('正在寻找文件...') self.work = WorkThread() self.work.start() self.work.trigger.connect(self.display) except: print('无法播放,歌曲下载错误') downloading = False pass except: sleep(0.1) print('播放系统错误') pass

播放所有歌曲

def playall(self, typer): global num global bo try: bo = typer num = 0 self.bofang(bo, num) except: print('playall error') pass

播放喜爱歌曲

def allplaylove(self): self.playall('love')


##### 4. 歌词显示


对于播放的歌曲,我们可以进行歌词打印显示。核心代码如下:



def run(self): if bo == 'love': try: proxies = { 'http': 'http://124.72.109.183:8118', 'http': 'http://49.85.1.79:31666'

        }
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36',
            'X-Requested-With': 'XMLHttpRequest'}
        try:
            try:
                try:
                    aq = lovepics[num]
                    aqq = aq.split('/')
                except:
                    pass
                if type == 'kugou' and len(aqq) - 1 == 6:
                    aqqe = str(aqq[0]) + str('//') + str(aqq[2]) + str('/') + str(aqq[3]) + str('/') + str(
                        '400') + str('/') + str(aqq[5]) + str('/') + str(aqq[6])
                    print(aqqe)
                elif type == 'netease' and len(aqq) - 1 == 4:
                    aqn = aq.split('?')
                    b = '?param=500x500'
                    aqqe = (str(aqn[0]) + str(b))
                    print(aqqe)
                else:
                    aqqe = lovepics[num]
                req = get(aqqe)

                checkfile = open(str(data + '/ls1.png'), 'w+b')
                for i in req.iter_content(100000):
                    checkfile.write(i)

                checkfile.close()
                lsfile = str(data + '/ls1.png')
                safile = str(data + '/back.png')
                draw(lsfile, safile)
                picno = True
            except:
                print('图片错误')
                picno = False
                pass

            url1 = loveurls[num]
            print(url1)
            # os.makedirs('music', exist\_ok=True)
            number = number + 1
            path = str(data + '\{}.临时文件'.format(number))
            headers = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.110.430.128 Safari/537.36',
                'X-Requested-With': 'XMLHttpRequest'
            }
            with get(url1, stream=True, headers=headers) as r, open(path, 'wb') as file:
                total_size = int(r.headers['content-length'])
                content_size = 0
                for content in r.iter_content(chunk_size=1024):
                    if not stopdown:
                        file.write(content)
                        content_size += len(content)
                        plan = (content_size / total_size) \* 100
                        # print(int(plan))
                        develop = str(int(plan)) + str('%')
                        self.trigger.emit(str(develop))
                    else:
                        print ('down')
                        break
                    stopdown = False
            to = 'downloadmusic\{}.mp3'.format(songed[num])
            makedirs('downloadmusic', exist_ok=True)
        except:
            self.trigger.emit(str('nofinish'))
            pass
        try:
            lrct = []
            f = lovelrc[num]  # 按行读取
            # print(f)
            lines = f.split('\n')
            # print(lines)
            for i in lines:
                line1 = i.split('[')
                try:
                    line2 = line1[1].split(']')
                    if line2 == '':
                        pass
                    else:
                        linew = line2[1]
                        # print(linew)
                        lrct.append(linew)
                    self.trigger.emit(str('lrcfinish'))
                except:
                    print('歌词错误')
        except:
            pass
        try:
            copyfile(path, to)
        except:
            pass
        downloading = False
        self.trigger.emit(str('finish'))
    except:
        self.trigger.emit(str('nofinish'))  

效果如下所示:  
 ![在这里插入图片描述](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/13c7775d963d4fd196a52c585ef4af62~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg55So5oi3NTc5MjMwMTY3MDI=:q75.awebp?rk3s=f64ab15b&x-expires=1773223615&x-signature=mHms7T5eqBpDioiXQFGWiGGzFo4%3D)


##### 5. 本地歌曲读取播放


首先我们可以对本地文件夹目录下的音乐进行读取添加到本地歌曲列表中,根据歌曲的文件名进行列表显示。核心代码如下:



本地歌曲文件夹读取添加

def add(self): try: global SongPath global SongName global num global filew global asas fileN = QFileDialog.getExistingDirectory(None, "选取文件夹", "") if not fileN == '': self.listwidget5.clear() filew = fileN + '/' asas = filew l1 = [name for name in listdir(fileN) if name.endswith('.mp3') or name.endswith('.flac') or name.endswith('.wma') or name.endswith('.MP3') or name.endswith('.FLAC') or name.endswith('.WMA')] SongNameadd = l1 SongPathadd = [filew + i for i in SongNameadd] SongName = SongName + SongNameadd SongPath = SongPath + SongPathadd print(SongPath) r = 0 for i in SongName: self.listwidget5.addItem(i) # 将文件名添加到listWidget self.listwidget5.item(r).setForeground(Qt.white) r = r + 1 except: filew = asas


当然我们还可以对本地加载歌曲进行双击播放,首先我们需要将本地歌曲子列表页面中进行双击事件绑定。



self.tab5 = QWidget() self.tab5.setObjectName("tab5") self.tab5_layout = QGridLayout() self.tab5.setLayout(self.tab5_layout) self.listwidget5 = QListWidget(self.tab5) self.listwidget5.doubleClicked.connect(lambda: self.change(self.listwidget5)) self.listwidget5.setContextMenuPolicy(Qt.CustomContextMenu) self.listwidget5.customContextMenuRequested[QPoint].connect(self.myListWidgetContext5)


对子列表页面进行绑定之后,接下来我们就可以完成双击事件,获取歌曲名称,并进行本地播放。



加载当前播放的本地歌曲

def change(self, listwidget): global num global bo # print (item.flags()) bo = 'local' num = int(listwidget.currentRow()) print(num) # self.label.setText(wenjianming)#设置标签的文本为音乐的名字 f = str(SongName[num]).split('.mp3')

一、Python所有方向的学习路线

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照下面的知识点去找对应的学习资源,保证自己学得较为全面。

img
img

二、Python必备开发工具

工具都帮大家整理好了,安装就可直接上手!img

三、最新Python学习笔记

当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。

img

四、Python视频合集

观看全面零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。

img

五、实战案例

纸上得来终觉浅,要学会跟着视频一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。img

六、面试宝典

在这里插入图片描述

在这里插入图片描述

简历模板在这里插入图片描述

了解详情:docs.qq.com/doc/DSnl3ZG…