演示6:python音乐下载器
演示6:python音乐下载器
- python音乐下载器-申明
- 原理
- 运行效果
- 搜索列表界面效果
- 下载列表界面效果
- 源码
python音乐下载器-申明
请支持正版音乐!本代码只是教学使用,不可用作商业用途,否则后果自负。
原理
使用的是爬虫原理。实际上就是对url进行请求,然后对返回的数据进行分析和提取。
本示例并只使用字符串的剪切功能对数据进行提取,并未使用正则表达。
运行效果
搜索列表界面效果
下载列表界面效果
源码
'''窗口的创建tkinter 窗口库urllib.request 访问请求库urllib.parse 链接编码库_thread 线程库此处需理解'''import tkinter,urllib.request,urllib.parse,_thread,ostk=tkinter.Tk()#创建窗口tk.minsize(800,500)#设置窗口的最小尺寸tk.maxsize(800,500)#设置窗口的最大尺寸tk.title('音乐下载器')#设置窗口上面显示的名字'''数据存储此处需理解'''datasearchgequ=[]#用来存放查询结果中的歌曲名datasearchgeshou=[]#用来存放查询结果中的歌手名datasearchurl=[]#用来存放查询结果中的下载链接,实际上存的是音乐播放页面的链接datasearchclick=[]#记录当前搜索的结果中已经点击下载的那一列,保证已经被点击下载的不能再次点击datalist1=[]#用来记录下载列表的歌曲名datalist2=[]#用来记录下载列表的歌手名dataupdown1=[]#用来记录正在下载的歌曲名dataupdown2=[]#用来记录正在下载的歌手名urlsearch='https://baidu.9ku.com/suggestions/?kw='#搜索请求的链接-URLtabletwofirst=0#用来记录下载列表的第一个显示的歌曲编号'''窗口控件-部分此处需理解'''tkinter.Label(tk,text='歌曲、歌手名').place(x=10,y=8)#标签的显示与设置,用来提示搜索的内容范围该是歌曲或歌手musicname=tkinter.Entry(tk,width=30,textvariable=tkinter.StringVar())#输入框的设置,并关联上变量-musicname,textvariable=tkinter.StringVar() 为设置输入框允许获取musicname.place(x=110,y=10)#设置输入框的位置'''点击搜索按钮时触发的函数实现搜索歌曲或歌手,并将数据存入列表中此处需理解'''def clicksearch(): str=urlsearch urllib.parse.quote(musicname.get())#将请求连接-URL进行编码,防止包含中文导致访问失败 str1=urllib.request.urlopen(str)#对编码后的链接进行访问 data=str1.read().decode('UTF-8')#对获取的数据进行解码,以便方便对中文或其他语言进行阅读 data=data[data.find('<dt>歌曲</dt>'):data.find('<dt>歌手</dt>')]#截取搜索结果中歌曲部分 datasearchgequ.clear()#清空搜索结果的歌曲列表 datasearchurl.clear()#清空搜索结果的下载列表 datasearchgeshou.clear()#清空搜索结果的歌手列表 datasearchclick.clear()#清空点击下载的记录,防止新搜索的结果无法点击下载 while True:#循环,实现获取搜索结果中的所有歌曲信息 datasearchgequ.append(data[data.find('songName') 10:data.find('</span>')])#截取歌曲名,并存入列表 datasearchgeshou.append(data[data.find('singerName') 20:data.find('</span></a>')])#截取歌手名,并存入列表 datasearchurl.append(data[data.find('href=') 6:data.find('\'><span')])#截取下载链接,并存入列表 if data.find('href=')<0:#判断是否将所有歌曲获取完 updatatableone()#刷新搜索结果的表格-画布 break#结束循环 data = data[data.find('</a></dd>') 4:]#获取完一首歌后,将被获取的歌那部分信息删除'''窗口控件-部分此处需理解'''musicsearch=tkinter.Button(tk,width=8,text="搜索",font=("黑体",9),command=clicksearch)#设置搜索按钮,并关联变量musicsearch.place(x=390,y=9)#设置搜索按钮的位置tableone=tkinter.Canvas(tk,width=780,height=450,bg='#ffffff')#设置搜索结果的表格画布,并关联变量tableone.create_rectangle((2,2,780,450))#设置搜索结果的表格画布边框tableone.place(x=10,y=40)#设置搜索结果的表格画布位置tabletwo=tkinter.Canvas(tk,width=780,height=450,bg='#ffffff')#设置下载列表的表格画布,并关联变量tabletwo.create_rectangle((2,2,780,450))#设置下载列表的表格画布边框tabletwo.pack_forget()#设置下载列表的表格不显示'''搜索列表的表格绘制与刷新此处需理解'''def updatatableone(): tableone.create_rectangle((2,2,780,30),fill='#888888')#绘制表头的背景颜色 tableone.create_rectangle((2,31,780,450),fill='#ffffff')#绘制表身的背景颜色,为了防止之前搜索的结果不会消失 tableone.create_text((250,15),text='歌曲')#绘制 歌曲 文字到表头 tableone.create_text((600, 15), text='歌手')#绘制 歌手 文字到表头 tableone.create_text((740, 15), text='操作')#绘制 操作 文字到表头 tableone.create_line((0,30,780,30))#绘制表头与表身之间的分割线 tableone.create_line((500,0,500,30))#绘制 歌曲 与 歌手 之间的分割线 tableone.create_line((700,0,700,30))#绘制 歌手 与 操作 之间的分割线 for i in range(0,len(datasearchgequ)-1):#循环,实现绘制搜索结果的歌曲名、歌手名和操作按钮 tableone.create_text((250,40 i*20),text=datasearchgequ[i])#绘制歌曲名 tableone.create_text((600,40 i*20),text=datasearchgeshou[i])#绘制歌手名 if i in datasearchclick:#判断是否该歌曲已经点击了下载 tableone.create_rectangle((720, 33 i * 20, 760, 48 i * 20), fill='#ffffff')#绘制白色背景的按钮-不可再次点击下载 else: tableone.create_rectangle((720,33 i*20,760,48 i*20),fill='#aaaaaa')#绘制灰色背景的按钮-可点击下载 tableone.create_text((740,42 i*20),text="下载",font=('黑体',7))#绘制操作按钮中的文字 tableone.create_line((0,50 i*20,780,50 i*20))#绘制每一条信息之间的分割线updatatableone()#调用上面的函数'''下载列表的表格绘制与刷新此处需理解'''def updatatabletwo(): tabletwo.create_rectangle((2,2,780,30),fill='#888888')#绘制表头的背景颜色 tabletwo.create_rectangle((2,31,780,450),fill='#ffffff')#绘制表身的背景颜色,为了防止之前下载列表的结果不会消失 tabletwo.create_text((250,15),text='歌曲')#绘制 歌曲 文字到表头 tabletwo.create_text((600, 15), text='歌手')#绘制 歌手 文字到表头 tabletwo.create_text((740, 15), text='状态')#绘制 状态 文字到表头 tabletwo.create_line((0,30,780,30))#绘制表头与表身之间的分割线 tabletwo.create_line((500,0,500,30))#绘制 歌曲 与 歌手 之间的分割线 tabletwo.create_line((700,0,700,30))#绘制 歌手 与 状态 之间的分割线 for i in range(tabletwofirst,len(datalist1)):#循环,实现绘制下载列表的歌曲名、歌手名和操作按钮 tabletwo.create_text((250,40 (i-tabletwofirst)*20),text=datalist1[i])#绘制歌曲名 tabletwo.create_text((600,40 (i-tabletwofirst)*20),text=datalist2[i])#绘制歌手名 if datalist1[i] in dataupdown1 and datalist2[i] in dataupdown2:#判断下载列表中的歌曲状态 tabletwo.create_text((740,42 (i-tabletwofirst)*20),text="正在下载",font=('黑体',7))#绘制正在下载文字 else: tabletwo.create_text((740, 42 (i-tabletwofirst)* 20), text="下载完成", font=('黑体', 7))#绘制下载完成文字 tabletwo.create_line((0,50 (i-tabletwofirst)*20,780,50 (i-tabletwofirst)*20))#绘制每一条信息之间的分割线updatatabletwo()#调用上面的函数'''在搜索结果按钮中点击下载时调用的函数,必要携带的一个参数 e (当然这个可以自定义名称)此处可做了解'''def onclicktableone(e): x=e.x#获取鼠标点击的位置的x坐标 y=int((e.y-30)/20)#获取鼠标点击的位置的y坐标,并将该坐标装换成编号,以便得知点击的是哪首歌的下载 if x>720 and x<760:#判断是否点击的下载按钮范围内,防止点击其他位置也可以下载 if y not in datasearchclick:#判断该歌曲是否已经点击 datasearchclick.append(y)#将该歌曲的搜索结果中的编号保存 updownmusic(y)#调用下载歌曲的函数 updatatableone()#刷新搜索结果的表格-画布'''下载列表滑动滚轮时调用得到函数,必要携带的一个参数 e (当然这个可以自定义名称)此处可做了解'''def tabletwohuadong(e): global tabletwofirst#设置该函数调用的这个变量是全局变量 if e.delta>0:#判断滚轮的滚动方向 tabletwofirst=tabletwofirst-1#滚轮向上滚动,将这个下载列表的第一条显示的编号减1 if tabletwofirst<0:#判断这个变量数值是否小于0 tabletwofirst=0#小于0,将它设置成0,防止出现错误 else: tabletwofirst=tabletwofirst 1#滚轮向下滚动,将这个下载列表的第一条显示的编号加1 if tabletwofirst>len(datalist1)-21:#判断这个变量数值是否超过下载的歌曲数量 tabletwofirst=tabletwofirst-1#超过了,则设置成没有超过,防止出现bug updatatabletwo()#刷新下载列表的表格-画布'''设置表格-画布 的鼠标监听此处可做了解'''tableone.bind('<Button-1>',onclicktableone)#如果搜索结果的表格被点击了,就调用对应的函数tabletwo.bind('<MouseWheel>',tabletwohuadong)#如果下载列表的表格中鼠标滚轮滚动了,就调用对应的函数'''将播放音乐的页面链接转换成音乐文件链接的函数,num为点击下载的歌曲编号此处可做了解'''def updownmusic(num): datalist1.append(datasearchgequ[num])#获取点中的歌曲名,并存入列表 datalist2.append(datasearchgeshou[num])#获取点中的歌手名,并存入列表 a=datasearchurl[num]#获取点中的各州播放页面链接 str2 = "https:" a[:a.find('/play')] '/down' a[a.find('play') 4:]#将链接中的 play 单词改成 down str3 = urllib.request.urlopen(str2)#请求连接 data=str3.read().decode('UTF-8')#将求情结果解码 data=data[data.find('点击下载歌曲</a>') 10:]#找到音乐的真实下载链接 data=data[data.find('href') 6:data.find('\" style')]#提取真实的下载链接 _thread.start_new_thread(writefile,(num,data))#使用线程调用文件保存函数,使用线程的原因是防止在保存时软件无法使用'''文件的保存函数,num 为点击下载的歌曲编号,url 为歌曲的真实下载链接此处可做了解'''def writefile(num,url): mname=datasearchgequ[num]#获取歌曲名 mgeshou=datasearchgeshou[num]#获取歌手名 dataupdown1.append(mname)#将该歌曲存入列表 dataupdown2.append(mgeshou)#将该歌手存入列表 updatatabletwo()#刷新下载列表 name=datasearchgequ[num] "-" datasearchgeshou[num]#设置保存的歌曲文件名 str5 = urllib.request.urlopen(url)#请求真实的下载链接 data=str5.read()#将服务器返回的结果读取出来,无需解码 a=url[url.find('com'):]#获取该歌曲的后缀,因为歌曲的后缀有mp3、wma、midi等 de=os.path.join(os.path.expanduser("~"),'Desktop').replace('\\', '/', 5)#获取桌面路径 fi=open(de '/' name a[a.find('.'):],'wb')#设置文件保存的路径与文件名 fi.write(data)#写文件 fi.close()#关闭写 dataupdown1.remove(mname)#将该歌曲名从正在下载的列表中删除 dataupdown2.remove(mgeshou)#将该歌手名从正在下载的列表中删除 updatatabletwo()#刷新下载列表的表格-画布'''点击所搜列表按钮和下载列表按钮时触发的函数此处需理解'''def clicktablefun1():#点击搜索列表按钮时触发的函数 tableone.place(x=10,y=40)#将搜索结果表格-画布 移到窗口可见位置 tabletwo.place(x=10,y=800)#将下载列表表格-画布 移到窗口不可见位置def clicktablefun2():#点击下载列表按钮时触发的函数 tabletwo.place(x=10,y=40)#将下载列表表格-画布 移到窗口可见位置 tableone.place(x=10,y=800)#将搜索结果表格-画布 移到窗口不可见位置'''窗口控件-部分此处需理解'''tablesearch=tkinter.Button(tk,text='搜索列表',width=16,font=("黑体",9),command=clicktablefun1)#设置搜索列表按钮tablesearch.place(x=500,y=9)#设置搜索列表按钮位置tableupdown=tkinter.Button(tk,text='下载列表',width=16,font=("黑体",9),command=clicktablefun2)#设置下载列表按钮tableupdown.place(x=653,y=9)#设置下载列表按钮位置tk.mainloop()#使窗口显示'''作业:实现一个简易的计算器,能实现数字不大的运算,可参照win系统带的计算器'''
赞 (0)