七夕送女朋友什么礼物好?我反手写了个音乐播放器,女友眼冒金光
Posted yeanky
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了七夕送女朋友什么礼物好?我反手写了个音乐播放器,女友眼冒金光相关的知识,希望对你有一定的参考价值。
七夕送女朋友什么礼物好?我反手写了个音乐播放器,女友眼冒金光!
这是一个用 Python 的 tkinter 库做的一个网络音乐播放器。我不说它的 UI 设计的有多好看,但是它的功能绝对是全站首个!坚持看到底,你不点赞算我输!
成果展示
程序截图
前期准备
程序结构:
文件或文件夹 | 描述 |
---|---|
_pycache_ | 导入模块形成的文件夹 |
musics | 存储下载的音乐 |
get.py | 爬取音乐 |
gui.py | GUI界面 |
lrc.py | 歌词操作 |
main.pyw | 入口文件,双击运行 |
player.py | 播放器文件 |
requirements.txt | 所需库 |
所需第三方库(requirement.txt):
mutagen==1.45.1
pygame==2.0.1
requests==2.26.0
Pillow==8.3.1
安装:
pip install mutagen # 查看歌曲长度
pip install pygame # 播放音乐
pip install requests # 爬取音乐
pip install pillow # 显示图片
或者:
pip install -r requirements.txt
一、爬取音乐
下面的代码为 get.py 里的内容。
具体教程见 酷我音乐搜索、下载详解。
import requests
search_url = 'http://www.kuwo.cn/api/www/search/searchMusicBykeyWord'
search_headers = {
'Referer': 'http://www.kuwo.cn/search/list?key=',
'Cookie': '_ga=GA1.2.12......',
'csrf': 'YO4OH2VYH1A'}
search_params = {
'key': 'str', # 查找关键字
'pn': '1', # 页数
'rn': '20', # 项数
'httpsStatus': '1',
'reqId': '6e028fc0-db8f-11eb-b6f5-ff7d54a57f2b'
}
from_url = 'http://www.kuwo.cn/url'
from_params = {
'rid': '148526468', # 歌曲 rid
'type': 'convert_url3',
'br': '128kmp3',
}
lrc_url = 'http://m.kuwo.cn/newh5/singles/songinfoandlrc?musicId={rid}'
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/91.0.4472.114 Safari/537.36 Edg/91.0.864.59'}
class Kuwo:
def search_kuwo(self, kw):#
search_params.update({'key': kw})
response = requests.get(search_url,
params=search_params,
headers={**headers, **search_headers},
timeout=2,
).json()
datas = response.get('data', {}).get('list', {})
result = [[r.get('name', ''),
r.get('artist', ''),
r.get('album', ''),
r.get('songTimeMinutes', ''),
r.get('pic', ''),
r.get('pic120', ''),
r.get('rid', '')]
for r in datas]
return result
def get_music_url(self, rid):#
from_params['rid'] = rid
url = requests.get(from_url, params=from_params, headers=headers, timeout=2).json()['url']
return url
def get_music_content(self, rid):
url = self.get_music_url(rid)
content = requests.get(url, headers=headers, timeout=2).content
return content
def get_music_lrc(self, rid):
lrc_data = requests.get(lrc_url.format(rid=rid), headers=headers, timeout=2).json()
lrc_list = lrc_data.get('data', {}).get('lrclist', [{1: '无歌词', 2: '0'}])
lrc = [list(l.values()) for l in lrc_list]
return lrc
def get_pic(self, url):
pic = requests.get(url, headers=headers).content
return pic
二、歌词操作
下面代码为 lrc.py 里的代码。
import re
class Lrc:
def __init__(self):
self.LRC = [[0.0, '无歌词']]
self.Times = [0.0]
self.Words = ['无歌词']
def decode_from_str(self, lrc: str):
lrc = lrc.strip('\\n')
res1 = self.SP_DTWDSTR.findall(lrc)
res2 = list()
res3 = dict()
result = dict()
for r in res1:
res2.append([self.SP_DTSTR.findall(r[0]), r[1]])
for r in res2:
for t in r[0]:
res3[self.tosec(t)] = r[1]
result = sorted(list(res3.items()), key=lambda x: x[0])
self.decode(result)
return self.LRC
def decode(self, lrcs):
self.LRC = lrcs
r = list(zip(*lrcs))
self.Words = list(r[0])
self.Times = list(map(self.tosec, list(r[1])))
# 将字符串时间变为秒
def tosec(self, t:str):
res1 = t.split(':')[::-1]
res2 = [float(r) * (60 ** i) for i, r in enumerate(res1)]
result = sum(res2)
return result
# 根据浮点数播放进度获取对应歌词索引
def get_index(self, t:float):
times = [*self.Times, t]
times.sort()
return times.index(t) - 1
三、播放器
下面代码为 player.py 里的内容。
播放器的方法其实和 pygame.mixer.music 的方法差别不大。但要注意的是第 1~2 行代码是用于去除导入 pygame 模块时自动打印的信息。
from os import environ
environ['PYGAME_HIDE_SUPPORT_PROMPT'] = '1'
import pygame
from io import BytesIO
class Player:
def __init__(self):
pygame.mixer.init()
self.music = pygame.mixer.music
def reset(self):
self.music.stop()
pygame.mixer.pre_init()
def load(self, filename):
self.music.load(filename)
def play(self):
self.music.play()
def pause(self):
self.music.pause()
def unpause(self):
self.music.unpause()
def stop(self):
self.music.stop()
def get_length(self):
return self.music.get_length()
def get_pos(self):
return self.music.get_pos()
def set_pos(self, value=0):
self.music.rewind()
self.music.set_pos(value)
def get_volume(self):
return self.music.get_volume()
def set_volume(self, value=0.5):
return self.music.get_volume(value)
def addsong(self, filename):
self.music.quene(filename)
四、GUI 界面
下面代码为 gui.py 中的代码。
有关教程见
from tkinter import *
from tkinter import ttk
from io import BytesIO
from mutagen.mp3 import MP3
from PIL import Image, ImageTk
import get
import player
import lrc
class Window(Tk):
ischanging = False
last_pos = 0
words = ['']
times = [0]
def __init__(self):
Tk.__init__(self)
self.title('JIE 音乐')
self.geometry('650x400')
self.resizable(0, 0)
self.set_notebook()
self.set_control()
self.set_weight()
self.update()
self.after(100, self.timer)
self.mainloop()
def set_notebook(self):
self.nb = ttk.Notebook(self)
self.nb.grid(row=0, column=0, sticky='nswe', padx=2, pady=1)
self.set_search_frame()
self.set_lrc_frame()
self.nb.add(self.search_frame, text=' 搜索 ')
self.nb.add(self.lrc_frame, text=' 歌词 ')
# 控制框
def set_control(self):
self.control_frame = Frame(self)
self.control_frame.grid(row=1, column=0, sticky='nswe', padx=2, pady=1)
self.ctrl_pic = Canvas(self.control_frame, height=40, width=40)
self.ctrl_pic.grid(row=0, column=0)
self.play_btn = Label(self.control_frame, text='▶', font=('宋体', 24, 'bold'),
width=2, height=1, relief='flat')
self.play_btn.bind('<Enter>', lambda event: self.play_btn.configure(fg='orange'))
self.play_btn.bind('<Leave>', lambda event: self.play_btn.configure(fg='black'))
self.play_btn.bind('<Button-1>', self.play_or_pause)
self.play_btn.grid(row=0, column=1, sticky='nswe')
self.var = IntVar()
self.var.set(0)
self.bar = Scale(self.control_frame, label='无歌曲', orient='horizontal',
variable=self.var, showvalue=False, from_=0, to=0,
command=self.change, width=10, length=500)
self.bar.grid(row=0, column=2, sticky='nwe')
self.download_btn = Label(self.control_frame, text='↓', font=('微软雅黑', 15), width=2)
self.download_btn.bind('<Enter>', lambda event: self.download_btn.configure(fg='orange'))
self.download_btn.bind('<Leave>', lambda event: self.download_btn.configure(fg='black'))
self.download_btn.bind('<Button-1>', self.download)
self.download_btn.grid(row=0, column=3, sticky='nswe')
# 搜索界面
def set_search_frame(self):
self.search_frame = Frame(self.nb)
self.inputbox = ttk.Entry(self.search_frame, width=14)
self.inputbox.bind('<Return>',lambda event: self.get_datas(self.inputbox.get()))
self.inputbox.grid(row=0, column=0, sticky='nswe', padx=(2, 0), pady=2)
self.surebtn = ttk.Button(self.search_frame, text='搜索', width=6,
command=lambda: self.get_datas(self.inputbox.get()))
self.surebtn.grid(row=0, column=1, columnspan=2, sticky='nswe', padx=(0, 2), pady=2)
columns = [0, 1, 2, 3, 4]
self.songstable = ttk.Treeview(self.search_frame, columns=columns, show='headings')
self.songstable.column(0, width=25, anchor='w', stretch='no')
self.songstable.heading(0, text='')
self.songstable.column(1, width=200, anchor='w')
self.songstable.heading(1, text='歌曲')
self.songstable.column(2, width=70, anchor='w')
self.songstable.heading(2, text='歌手')
self.songstable.column(3, width=100, anchor='w')
self.songstable.heading(3, text='专辑')
self.songstable.column(4, width=45, anchor='w', stretch='no')
self.songstable.heading(4, text='时长')
self.songstable.grid(row=1, column=0, columnspan=2, sticky='nswe')
self.songstable.bind('<Double-Button-1>',
lambda event: self.selected(self.songstable.item(self.songstable.selection()[0], 'value')))
self.songscroll = ttk.Scrollbar(self.search_frame, orient='vertical',
command=self.songstable.yview)
self.songscroll.grid(row=1, column=2, sticky='nswe')
self.songstable.configure(yscrollcommand=self.songscroll.set)
# 歌词界面
def set_lrc_frame(self):
self.lrc_frame = Frame(self.nb)
self感动哭了!七夕用python送男朋友99999朵玫瑰!!!
女朋友想要听歌,我反手用Flutter做了2个音乐播放器,给她拿捏了