Python 爬QQ音乐

用最简单易懂的方法爬取QQ音乐

在18年12月8号那个月黑风高的傍晚,个人一个刚学前端的朋友忽然跟我说,想下载付费的歌,我这个小白就夸下海口的说,我来帮你下,毕竟我是学Python的,总不能丢人吧。因而呢,我就打算写一个,可是那天已经很晚了,写是写不出来了,我就在博客上搜了一个爬酷狗的代码帮她下载了几首,而后呢,发给她的时候,我又嘴贱了一句,问她还有什么要下的歌,紧跟着她就说等明天想到在跟我说。就这样我想来想去感受用别人的代码,显的本身很没有诚意,而后就写了一个爬QQ音乐的,就有了下面的代码。原本是想爬网易云的,可是呢,看了一眼网易云的网页。嗯,没错,就是这样的,我决定了爬QQ音乐。那个爬酷狗的代码也是根据输入的关键字来爬的。我就写了一个差很少的。由于比较方便和能够选择要下载的歌。前端


上面看不看无所谓,下面给你们看看效果图。

在这里插入图片描述在这里插入图片描述

有没有交互设计的感受,我真是一个被代码耽误的产品经理啊。而后给你们讲讲,我这个小白是怎么分析网站的。

  1. 打开QQ音乐,搜一首歌(建议你们听一听 短发 这首歌)找到这个json文件,先打开文件别动。
    在这里插入图片描述
  2. 而后点开一首歌,会跳到音乐的详情页,而后点击播放(我这里比较懒,详情页没截屏), 而后找到下面的这个json文件并打开
    在这里插入图片描述
  3. 红线部分就是咱们最后下载歌曲,要拼接url的一部分
    在这里插入图片描述
  4. 最后下载音乐的url以下:
    在这里插入图片描述
    看完上面,也就是说咱们只要请求图2的url就能够获得最后的歌曲下载的url。图二url以下:
    在这里插入图片描述
    data后面原本是base64编码,我给改了,这些都不重要,重要的是这个url的参数,callback这里,我一直觉得是个js加密的参数,让我激动半天,后来找到那个js代码才发现,其实就是个随机数字?,前端真的很气人,只会欺负我这种小白。下面这些参数都是可有可无的,重要的只有 songmid,那么这个参数怎么拿到呢。就在图一那个json文件里面,以下图:
    在这里插入图片描述
    这个mid就是那个参数,也就是说咱们请求这个图一url拿到mid参数,就能够拼接图二的url,最后拿到最终下载歌曲的url了。
    那么问题来了,怎么按照本身想要的歌来请求图一的url呢?总不能每一次都搜索一下吧,那么就来分析一下图一的那个json的url吧,以下:
    在这里插入图片描述
    能够看到一个被base64编码的中文,没错,这个就是你搜索的歌名了。只要把你要下载的歌名,拼接到这个url上就好了。

ok老规矩,分析完网页,附上代码。web

import re
import json
import requests
def music(name):
    url = f"https://c.y.qq.com/soso/fcgi-bin/client_search_cp?ct=24&qqmusic_ver=1298&new_json=1&remoteplace=txt.yqq.song&searchid=62115878671550904&t=0&aggr=1&cr=1&catZhida=1&lossless=0&flag_qc=0&p=1&n=20&w={name}&g_tk=5381&jsonpCallback=MusicJsonCallback2806001545440244&loginUin=0&hostUin=0&format=jsonp&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq&needNewCode=0"
    json_list = requests.get(url).text
    # print(type(json_list))
    res = re.compile(r"MusicJsonCallback.*?{(.*)}", re.S)
    content = re.findall(res, json_list)
    # print(type(content))
    content_1 = '{'+content[0]+'}'
    dict_content = json.loads(content_1)
    # print(dict_content)
    keyword = dict_content["data"]["keyword"]
    # print(keyword)
    list_all = dict_content["data"]["song"]["list"]
    # print(list_all)
    mid_list = []
    music_title_list = []
    for index, for_dict in enumerate(list_all):
        print('_' * 100)
        # 专辑名
        album_name = for_dict["album"]["title"]
        # new url
        mid_list.append(for_dict["mid"])
        # 歌名
        music_title = for_dict["title"]
        music_title_list.append(music_title)
        # 歌手
        singer_name = for_dict["singer"][0]["title"]
        print(" ", index + 1, ">>>", music_title, "          ", singer_name, "               ", album_name)
    number = int(input("要下载第第几首歌(根据序号)\n"))

    down_music(mid_list=mid_list, number=number, music_title_list=music_title_list)

def down_music(mid_list, number, music_title_list):
    url = f"https://u.y.qq.com/cgi-bin/musicu.fcg?callback=getplaysongvkey12314283393950355&g_tk=5381&jsonpCallback=getplaysongvkey12314283393950355&loginUin=0&hostUin=0&format=jsonp&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq&needNewCode=0&data=%7B%22req_0%22:%7B%22module%22:%22vkey.GetVkeyServer%22,%22method%22:%22CgiGetVkey%22,%22param%22:%7B%22guid%22:%224357915898%22,%22songmid%22:[%22{mid_list[number-1]}%22],%22songtype%22:[0],%22uin%22:%220%22,%22loginflag%22:1,%22platform%22:%2220%22%7D%7D,%22comm%22:%7B%22uin%22:0,%22format%22:%22json%22,%22ct%22:20,%22cv%22:0%7D%7D"

    join_url = requests.get(url).text
    res = re.compile(r"getplaysongvkey.*?{(.*)}", re.S)
    url_content = re.findall(res, join_url)
    char_url = "{" + url_content[0] + "}"
    dict_url = json.loads(char_url)
    finally_url = "http://111.7.162.144/amobile.music.tc.qq.com/" + dict_url["req_0"]["data"]["midurlinfo"][0]["purl"]
    name_cd = music_title_list[number - 1]
    print(name_cd)
    
    with open(name_cd + ".mp3", "wb")as fp:
        fp.write(requests.get(finally_url).content)
    print("歌曲已下载完成!")


if __name__ == "__main__":
    name = input("请输入要下载的歌名\n>>> ")
    music(name=name)

这个就是完整的代码了,代码可读性应该很高吧,都说我是小白了。json

注意:
  1. 这个代码写的不是很完善,你搜索歌的时候,是可能有第二页或者是更多页,我请求的那个url只搜出第一页的歌,若是想完善,能够改url里面的参数,在加个判断就行,不过第一页基本就有你想要的歌了,其它页的都是QQ音乐模糊匹配到的没有意义。
  2. 代码是纯我的写的,光分析网页,就找了将近五六个小时的规律,一点也不夸张,看我这么烂的代码就明白,小白的痛苦。
  3. 这个代码我帮我朋友下载过几首歌了,尚未遇到bug,若是大家遇到麻烦评论一下,若是能够,把改好的代码一并发给我,我懒得改?。
重点:建议你们听一听 短发 这首歌,有没有感受很对不起那个她呢?

平常鸡汤:既感性又现实的人,活的真的很累。并发