Python-QQ音乐爬虫

爬虫程序代码

导入的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()

效果演示

菜单效果

 

显示歌曲信息(该图只显示了前五首歌曲)

 

下载全部

 

单曲下载

 

查看已下载的歌曲信息

 

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值