提问:你平常都是如何听歌和下载歌曲的?官网?软件?
简介:作为计算机的爱好者,对计算的使用已经是非常熟悉了解的了,当然对编程语言也是有些许了解。听周围人说,无法听取某些歌曲或下载某些歌曲,身为脚本小子的我,分析了对应网页,编写了一个音乐播放器,并且歌曲对应的歌词也会随音乐的播放进行滚动。
一、导入需要的库
工欲善其事必先利其器,在开始编写时,先分析好大概的结构和所需的功能,导入对应的第三方库。
import tkinter as tk GUI 界面搭建
import time 计时
import requests 网页请求库
import urllib.parse as parse 格式化字符编码
import json json数据分析
import os 系统库
from pygame import mixer #音乐播放
from mutagen.mp3 import MP3 # 用来的到一个.mp3文件的时长
二、构建GUI界面
这里使用的是tkinter来创建界面,这个库,搭建界面简单便捷,小巧,并且容易打包
tk.Tk() 创建一个主窗口
title 标题
geometry("长x宽") 设置窗口的长宽
geometry("长x宽+x轴位置+y轴位置") 设置窗口的长宽以及在窗口的显示位置
font 字体 字号
grid 布局 行 列
StringVar() 字符串变量类型
command 调用函数
mainloop() 显示窗口
root = tk.Tk()
root.title("######音乐播放器")
root.geometry("800x400")
input_lable = tk.Label(root,text="请输入歌名或作者:",font=('楷体',12))
input_lable.grid(row=1,column=0)
input_en = tk.StringVar()
input_entry = tk.Entry(root,textvariable=input_en,font=("楷体",12))
input_entry.grid(row=1,column=1)
index_input = tk.Button(root,text="搜索",command=select_1)
index_input.grid(row=1,column=2)
#歌曲列表
list_box = tk.Listbox(root,font=('楷体',12),width=43,height=21)
list_box.grid(row=2,column=0,columnspan=3,rowspan=5)
#歌词
text = tk.Text(root,width=63,height=20)
text.grid(row=2,column=3,rowspan=3,columnspan=5)
b_buttom = tk.Button(root,text="播放",command=select_2)
b_buttom.grid(row=5,column=3)
tk.mainloop()
二、歌曲id和歌曲名下载
with open(f'{zuoze}.mp3', 'wb') as f:
with open('文件名和后缀','读取或写入方式') as 小名
打开的文件如果不存在,便会新建一个 WB 二进制写入
def M_musci(music_name):
file = open("m1.txt", 'w').close()
print(music_name) #音乐名称
keyword = parse.urlencode({'keyword': music_name}) #构建参数
keyword = keyword[keyword.find('=') + 1:] #去除建
#请求头
headers={'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3741.400 QQBrowser/10.5.3863.400'}
#拼接网址
url = f"https://music.163.com/api/search/get/web?csrf_token=hlpretag=&hlposttag=&s={keyword}&type=1&offset=0&total=true&limit=20"
#文本数据
response = requests.get(url, headers=headers).json()
json_list = response["result"]["songs"]
for i in json_list:
print(i)
ID = i['id']
name = i['name']
str_zuozhe = i['artists']
for j in str_zuozhe:
str_zuozhe=j['name']
with open("m1.txt",'a',encoding='utf-8') as f:
f.write(str_zuozhe+'\t'+name+'\t'+str(ID)+'\n')
三、文件处理函数
read 读取文件
split() 去除尾部不需要的字符
def Information_from_file(): #文件处理函数
with open('m1.txt','r',encoding='utf-8') as f: #读取保存的歌曲文件
str_1=f.read() #读取
# print(str_1)
list_1=str_1.split('\n')[:-1] #去除换行符 取0到末尾
print(list_1)
song_names=[];song_name=[];song_id=[] #三个列表变量 歌曲名 歌曲哈希值 歌曲ID
for str_2 in list_1: #遍历读取的字符
str_2=str_2.split('\t') #去除格式符
print(str_2)
song_names.append(str_2[0]) #作者
song_name.append(str_2[1]) #名称
song_id.append(str_2[2]) #歌曲ID
return song_names,song_name,song_id #返回这三个列表
四、歌曲下载函数
append 数据添加进列表
writer 文件写入
time.time() 获取当前时间
def Downlad(zuoze,music_id): #音乐的下载传递两个参数 音乐哈希值 音乐ID
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3741.400 QQBrowser/10.5.3863.400'}
# 发送请求
url = f'https://music.163.com/api/song/lyric?id={music_id}&lv=1&kv=1&tv=-1'
response = requests.get(url, headers=headers).json()
# print(response['lrc'])
list = response['lrc']['lyric']
list_1 = list.split('\n')[:-1]
print(list_1)
song_list = []
time_list = []
for str_1 in list_1:
# 歌曲时间
str_2 = str_1[:str_1.find(']') + 1]
time_list.append(str_2)
str_1 = str_1[str_1.find(']') + 1:]
song_list.append(str_1)
print(song_list)
print(time_list)
time_list = Get_Time(time_list) # 时间列表
new_url = f"http://music.163.com/song/media/outer/url?id={music_id}.mp3"
response = requests.get(new_url, headers=headers).content
with open(f'{zuoze}.mp3', 'wb') as f:
f.write(response)
start_time = time.time()
audio = MP3(f'{zuoze}.mp3')
untime = time.time()
time_music = audio.info.length
mixer.init()
mixer.music.load(f'{zuoze}.mp3')
mixer.music.play()
mixer.stop()
return True, time_list, song_list, time_music
五、歌曲搜索函数
delete(从0位开始,结尾结束)
get() 获取输入的值
insert(开始位置,插入的字符串)
def select_1(): #选择
list_box.delete(0,tk.END)
M_musci(input_en.get()) #输入的值
list_1=Information_from_file()[1] #歌曲名
for i in range(len(list_1)): #遍历歌曲名
list_box.insert(tk.END,str(list_1[i])) #显示歌曲名
六、播放函数
update 数据更新
def select_2():
dict_id={}
dict_name={} #定义两个变量
text.delete(0.0,tk.END)
list_1=Information_from_file()[0] # 作者
list_2=Information_from_file()[1] # 名称
list_3=Information_from_file()[2] # id
for i in range(len(list_2)): #遍历歌曲名
print(list_2[i])
dict_id[list_2[i]]=list_2[i] #将哈希 传递给对应的音乐名 name:哈希值
dict_name[list_2[i]]=list_3[i] #将ID 传递给对应的name name:ID
print(dict_name,dict_id)
name_1 = list_box.get(tk.ACTIVE)
zuoze = dict_id[name_1] # 获取对应的音乐ID
print(zuoze)
id1 = dict_name[name_1] # 获取对应的音乐哈希值
bool_1=Downlad(zuoze,id1)
# 显示一个进度条
for i in range(1, 101):
tk.Label(root, text='{}%|{}'.format(i, int(i / 4 % 26) * '■')).grid(row=5, columnspan=2, column=6, sticky=tk.W)
root.update() # 更新
time_list = bool_1[1] # 时间列表
song_list = bool_1[2] # 歌曲列表
music_time = bool_1[3] # 音乐时间
i = 0
T = 0
while True:
# end_time = time.time()
try:
# time.sleep(((time_list[T]) - time_list[T])+1)
text.insert('{}.0'.format(i + 1), (song_list[i] + '\n').center(56, ' ')) # 将第一行插入歌曲列表的第i个 居中显示
text.update()
# text.send(tk.END)
text.see(tk.END)
i += 1
if T == 0: # 真
time.sleep(time_list[T]) # 暂停几秒
elif T == len(time_list)-1: #
time.sleep(4)
else:
time.sleep(time_list[T+1] - time_list[T])
T += 1
root.update()
except:
break
七、音乐播放歌词时间函数
def Get_Time(time_list):
for i in range(len(time_list)): #遍历时间列表
minute = time_list[i][1:3] #分
second = time_list[i][4:6] #秒
h_second = time_list[i][7:9] #毫秒
time_list[i] = int(minute) * 60 + int(second) + float('0.' + h_second) #时间列表
return time_list
八、全部源码
# -*- coding:utf-8 -*-
"""
File name : main.PY
Program IDE : PyCharm
Create file time: 2022/10/19 11:46
File Create By Author : 小梦
"""
import tkinter as tk
import tkinter as tk
import time
import requests
import urllib.parse as parse
import json
import os
from pygame import mixer #音乐播放
from mutagen.mp3 import MP3 # 用来的到一个.mp3文件的时长
def M_musci(music_name):
file = open("m1.txt", 'w').close()
keyword = parse.urlencode({'keyword': music_name}) #构建参数
keyword = keyword[keyword.find('=') + 1:] #去除建
headers={'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3741.400 QQBrowser/10.5.3863.400'}
url = f"https://music.163.com/api/search/get/web?csrf_token=hlpretag=&hlposttag=&s={keyword}&type=1&offset=0&total=true&limit=20"
response = requests.get(url, headers=headers).json()
json_list = response["result"]["songs"]
for i in json_list:
ID = i['id']
name = i['name']
str_zuozhe = i['artists']
for j in str_zuozhe:
str_zuozhe=j['name']
with open("m1.txt",'a',encoding='utf-8') as f:
f.write(str_zuozhe+'\t'+name+'\t'+str(ID)+'\n')
num=0
id_1=True
def Get_Time(time_list):
for i in range(len(time_list)): #遍历时间列表
minute = time_list[i][1:3] #分
second = time_list[i][4:6] #秒
h_second = time_list[i][7:9] #毫秒
time_list[i] = int(minute) * 60 + int(second) + float('0.' + h_second) #时间列表
return time_list
def Information_from_file(): #文件处理函数
with open('m1.txt','r',encoding='utf-8') as f: #读取保存的歌曲文件
str_1=f.read() #读取
list_1=str_1.split('\n')[:-1] #去除换行符 取0到末尾
song_names=[];song_name=[];song_id=[] #三个列表变量 歌曲名 歌曲哈希值 歌曲ID
for str_2 in list_1: #遍历读取的字符
str_2=str_2.split('\t') #去除格式符
song_names.append(str_2[0]) #作者
song_name.append(str_2[1]) #名称
song_id.append(str_2[2]) #歌曲ID
return song_names,song_name,song_id #返回这三个列表
def Downlad(zuoze,music_id): #音乐的下载传递两个参数 音乐哈希值 音乐ID
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3741.400 QQBrowser/10.5.3863.400'}
url = f'https://music.163.com/api/song/lyric?id={music_id}&lv=1&kv=1&tv=-1'
response = requests.get(url, headers=headers).json()
list = response['lrc']['lyric']
list_1 = list.split('\n')[:-1]
print(list_1)
song_list = []
time_list = []
for str_1 in list_1:
str_2 = str_1[:str_1.find(']') + 1]
time_list.append(str_2)
str_1 = str_1[str_1.find(']') + 1:]
song_list.append(str_1)
time_list = Get_Time(time_list) # 时间列表
new_url = f"http://music.163.com/song/media/outer/url?id={music_id}.mp3"
response = requests.get(new_url, headers=headers).content
with open(f'{zuoze}.mp3', 'wb') as f:
f.write(response)
start_time = time.time()
audio = MP3(f'{zuoze}.mp3')
untime = time.time()
time_music = audio.info.length
mixer.init()
mixer.music.load(f'{zuoze}.mp3')
mixer.music.play()
mixer.stop()
return True, time_list, song_list, time_music
def select_1(): #选择
list_box.delete(0,tk.END)
M_musci(input_en.get()) #输入的值
list_1=Information_from_file()[1] #歌曲名
for i in range(len(list_1)): #遍历歌曲名
list_box.insert(tk.END,str(list_1[i])) #显示歌曲名
def select_2():
dict_id={}
dict_name={} #定义两个变量
text.delete(0.0,tk.END)
list_1=Information_from_file()[0] # 作者
list_2=Information_from_file()[1] # 名称
list_3=Information_from_file()[2] # id
for i in range(len(list_2)): #遍历歌曲名
print(list_2[i])
dict_id[list_2[i]]=list_2[i] #将哈希 传递给对应的音乐名 name:哈希值
dict_name[list_2[i]]=list_3[i] #将ID 传递给对应的name name:ID
name_1 = list_box.get(tk.ACTIVE)
zuoze = dict_id[name_1] # 获取对应的音乐ID
id1 = dict_name[name_1] # 获取对应的音乐哈希值
bool_1=Downlad(zuoze,id1)
for i in range(1, 101):
tk.Label(root, text='{}%|{}'.format(i, int(i / 4 % 26) * '■')).grid(row=5, columnspan=2, column=6, sticky=tk.W)
root.update() # 更新
time_list = bool_1[1] # 时间列表
song_list = bool_1[2] # 歌曲列表
music_time = bool_1[3] # 音乐时间
i = 0
T = 0
while True:
try:
text.insert('{}.0'.format(i + 1), (song_list[i] + '\n').center(56, ' ')) # 将第一行插入歌曲列表的第i个 居中显示
text.update()
text.see(tk.END)
i += 1
if T == 0: # 真
time.sleep(time_list[T]) # 暂停几秒
elif T == len(time_list)-1: #
time.sleep(4)
else:
time.sleep(time_list[T+1] - time_list[T])
T += 1
root.update()
except:
break
root = tk.Tk()
root.title("#####音乐播放器")
root.geometry("800x400")
input_lable = tk.Label(root,text="请输入歌名或作者:",font=('楷体',12))
input_lable.grid(row=1,column=0)
input_en = tk.StringVar()
input_entry = tk.Entry(root,textvariable=input_en,font=("楷体",12))
input_entry.grid(row=1,column=1)
index_input = tk.Button(root,text="搜索",command=select_1)
index_input.grid(row=1,column=2)
list_box = tk.Listbox(root,font=('楷体',12),width=43,height=21)
list_box.grid(row=2,column=0,columnspan=3,rowspan=5)
text = tk.Text(root,width=63,height=20)
text.grid(row=2,column=3,rowspan=3,columnspan=5)
b_buttom = tk.Button(root,text="播放",command=select_2)
b_buttom.grid(row=5,column=3)
tk.mainloop()
效果图
缺点:
1、部分代码过于冗余,不够规范,运行有些卡顿
1、点击播放时,会先将歌曲下载到本地,然后播放,待优化
3、只能单首播放,且只有一次
4、不能暂停