爬虫程序代码
导入的Python库
import requests
from urllib.request import *
import json
import os.path
爬虫程序的执行菜单
def menu():
print("-----------主菜单-----------")
print('[1]->显示音乐信息')
print('[2]->下载全部')
print('[3]->单曲下载')
print("[4]->查看已下载的歌曲信息")
print("[5]->退出")
print("---------------------------")
获取除歌曲地址之外的其它信息(该函数接收一个输入的歌曲名或歌手名)
def getSingerDataList(nameInfo):
url = "https://c.y.qq.com/soso/fcgi-bin/client_search_cp?&t=0&aggr=1&cr=1&catZhida=1&lossless=0&flag_qc=0&p=1&n=20&w={}".format(
nameInfo)
html = requests.get(url)
html.encoding = "utf-8"
htmlText = html.text
jsonData = json.loads(htmlText.strip("callback()[]"))
SingerDataList = jsonData["data"]["song"]["list"]
return SingerDataList
创建一个歌曲类
class MusicClass:
def __init__(self, meiTi_ID, music_ID, music_Name, singer, albumNames, music_URL=None):
# 分别为歌曲的媒体ID,歌曲的ID,歌曲的名称,歌手,歌手专辑,歌曲URL
self.__meiTi_ID = meiTi_ID
self.__music_ID = music_ID
self.__music_URL = music_URL #歌曲URL
self.__music_Name = music_Name
self.__singer = singer
self.__albumNames = albumNames
self.__local_music_path = None
# 为其中外部要用到的私有属性提供get和set方法
def getMeiTi_ID(self):
return self.__meiTi_ID
def getMusic_ID(self):
return self.__music_ID
def getMusic_Name(self):
return self.__music_Name
def getSinger(self):
return self.__singer
def getMusicPath(self):
return self.__local_music_path
def getAlbumNames(self):
return self.__albumNames
def setMusic_URL(self, music_url):
self.__music_URL = music_url
# 提供显示歌曲详情的方法
def showMusicInfo(self, index="*"):
print("{}: {}-{} {}".format(index, self.__music_Name, self.__singer, self.__albumNames))
# 提供下载歌曲的类方法(根据传入的歌曲实例和保存路径下载歌曲)
@classmethod
def musicDownLoad(cls, self, downLoadUrl):
try:
music_path = "{}\\{}-{}.m4a".format(downLoadUrl, self.__music_Name, self.__singer)
self.showMusicInfo()
print("正在下载中...")
urlretrieve(self.__music_URL, music_path)
self.__local_music_path = music_path # 给实例中的__local_music_path属性赋值
print("下载完成。\n")
except:
print("下载失败!\n")
# 遍历并输出所有歌曲信息
@classmethod
def printAllMusic(self, musicList):
for index in range(len(musicList)):
musicList[index].showMusicInfo(index + 1)
给MusicClass类的实例中歌曲的地址属性赋值(该函数接收一个存储歌曲实例的列表)
def setClassMusicUrl(musicList):
url1 = 'https://c.y.qq.com/base/fcgi-bin/fcg_music_express_mobile3.fcg?&jsonpCallback=MusicJsonCallback&cid=205361747&songmid={}&filename=C400{}.m4a&guid=6612300644'
url2 = 'http://dl.stream.qqmusic.qq.com/C400{}.m4a?vkey={}&guid=6612300644&uin=0&fromtag=66'
for m in musicList:
html2 = requests.get(url1.format(m.getMusic_ID(), m.getMeiTi_ID()))
html2.encoding = "utf-8"
htmlText2 = html2.text
jsonData2 = json.loads(htmlText2)
vkey = jsonData2["data"]["items"][0]["vkey"]
m.setMusic_URL(url2.format(m.getMeiTi_ID(), vkey))
获取音乐信息
def getMusicInformation():
nameInfo = input("请输入歌手或歌名:")
print("歌曲信息获取中...")
SingerDataList = getSingerDataList(nameInfo) # 获取除歌曲地址之外的所有歌曲信息
musicList = [] # 存储歌曲类的实例
# 对获取到的歌曲信息进行解析,把每个歌曲解析出来的信息存储在MusicClass的实例中
for data in SingerDataList:
try:
music = MusicClass(data["media_mid"], data["songmid"], data["songname"], data['singer'][0]['name'],
data["albumname"])
musicList.append(music)
except:
print("信息解析出现错误!\n")
setClassMusicUrl(musicList) # 为musicInfo列表中的每个实例的歌曲地址赋值
return musicList
开始下载获取到的歌曲
def downLoadMusic(musicList, dataList, index=-1):
downLoadUrl = input("请输入要存储歌曲的本地路径:")
# 判断此路径是否存在
if not os.path.exists(downLoadUrl):
# 创建此路径
os.path.makedirs(downLoadUrl)
# 如果创建失败,则终止
if not os.path.exists(downLoadUrl):
return
# 如果index==-1则下载所有音乐
if index == -1:
for mu in musicList:
MusicClass.musicDownLoad(mu, downLoadUrl)
# 清空原有的元素
dataList.clear()
# 将musicInfo集合的元素全部添加到dataList集合中
dataList.extend(musicList)
# 单曲下载
elif index > -1 and index < len(musicList):
MusicClass.musicDownLoad(musicList[index], downLoadUrl)
if not musicList[index] in dataList:
dataList.append(musicList[index])
else:
print("序号不正确\n")
return
print("歌曲下载完成\n")
主程序开始执行的函数
def start():
dataList = [] # 存储已下载的歌曲信息(列表集合)
musicList = getMusicInformation() # 获取音乐实例的集合
while True:
menu() # 显示主菜单
cmd = input("请输入菜单序号:")
if '1' == cmd:
MusicClass.printAllMusic(musicList) # 输出所有搜索到的音乐信息
elif '2' == cmd:
downLoadMusic(musicList, dataList) # 下载所有音乐
elif '3' == cmd:
index = input("请输入序号:") # 下载指定编号的音乐文件
if index.isdigit() == True:
downLoadMusic(musicList, dataList, int(index) - 1) # 开始下载
else:
print("序号必须是数值\n")
elif '4' == cmd:
MusicClass.printAllMusic(dataList) # 输出所有已下载的音乐
elif '5' == cmd:
break # 程序结束
else:
print("输入选项不正确!")
start()
效果演示
菜单效果
显示歌曲信息(该图只显示了前五首歌曲)
下载全部
单曲下载
查看已下载的歌曲信息