爬取 qq,酷我,千千VIP音樂下


千千音樂可能是第一次爬(沒爬到vip),但后來我成功爬到了qq和酷我的vip音樂

我覺得難度肯定是qq>kuwo>千千吧

千千和酷我在 上篇 已經有了就不再重復了這篇詳細講講qq音樂

qq音樂

找到一首歌的播放url

直接隨便搜一首歌點播放進入播放頁面

發現media里面有文件(良心)進入這個url就得到了歌的緩存文件

def qq_down_load(song_name,song_api):
    '''
            下載qq音樂
        :param song_name:
        :param song_api:
        :return:
        '''
    header = {
        'Cookie': 'pgv_pvi=3067481088; RK=e3RBBI+cEG; ptcz=801320b5ce845608fe88e3486ad8bb364cbc2f4ca7963d4ccb872b462bcb29cc; pgv_pvid=408922362; pac_uid=1_1179502349; tvfe_boss_uuid=6666e170218e6655; luin=o1179502349; lskey=000100004e6d001faafba92cccb55e1606698d10622c8ef379cf57841d9e7fc90004782e8945132b9edd1ffc; pgv_si=s4840030208; pgv_info=ssid=s6065813728; qqmusic_fromtag=66',
        'Referer': 'https://y.qq.com/portal/player.html',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36'
    }
    res = requests.get(song_api, headers=header)
    res.encoding = res.apparent_encoding
    req = res.content

    with open(song_name+'.mp3','wb') as f:
        f.write(req)
    path = os.getcwd()
    print(song_name + '  成功下載到' + path)
    time.sleep(1.5)
    return

 


找到url變化參數 id,vkey。

重復上面的步驟可以找另一首歌發現這個url只有 vkey和m4a前面C400后面的那串字母改變 (盲猜id)

構造url

這里就是經驗了,一般和id有關的都在歌單里,搜索一下那串字母?(果不其然)

def get_qq_song_list(key_word,page): # 7
    '''
            得到關鍵字和page的歌單
        :param key_word:
        :param page:
        :return:
        '''
    #url = 'http://c.y.qq.com/soso/fcgi-bin/client_search_cp?p='+str(page)+'&w='+key_word

    url='https://c.y.qq.com/soso/fcgi-bin/client_search_cp?p='+str(page)+'&n=10&w='+key_word
    #其實問號后面的都是參數,不能修改的就是p page,刪去參數得到的json文件有微小差別 有的key名字不一樣還是最好不要刪
    header = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36',
        'cookie': 'pgv_pvi=3067481088; RK=e3RBBI+cEG; ptcz=801320b5ce845608fe88e3486ad8bb364cbc2f4ca7963d4ccb872b462bcb29cc; pgv_pvid=408922362; pac_uid=1_1179502349; tvfe_boss_uuid=6666e170218e6655; luin=o1179502349; ts_uid=4023961751; lskey=000100004e6d001faafba92cccb55e1606698d10622c8ef379cf57841d9e7fc90004782e8945132b9edd1ffc; pgv_si=s4840030208; pgv_info=ssid=s6065813728; ts_refer=ADTAGh5_playsong; qqmusic_fromtag=66; userAction=1; yq_index=0; yqq_stat=0; yq_playschange=0; yq_playdata=; player_exist=1; yplayer_open=0; ts_last=y.qq.com/n/yqq/song/000pSUIh12A9uO.html',
        'referer': 'https://y.qq.com/portal/search.html',
        'accept - encoding': 'gzip, deflate, br'
        }
    res = requests.get(url, headers=header)
    reg=r'{.*}'
    req=re.findall(reg,res.text)[0]
    #jsonloads 可以把str 變成json文件 十分好用!
    html=json.loads(req)
    song_list = html['data']['song']['list']
    return song_list


def get_song_info_from_qq(song_info,tot,qq_song_list):
    '''
        從歌單得到每一首歌的數據
        :param tot:
        :param qq_song_list:
        :return:
        '''
    for song in qq_song_list:
        song_info[tot].name = song['songname']
        song_info[tot].atrist_name = song['singer'][0]['name']
        song_info[tot].song_nameid = song['media_mid']
        song_info[tot].song_keyid=song['songmid']
        song_info[tot].belong = 'qq'
        print(tot, song_info[tot].name,'--------歌手:', song_info[tot].atrist_name)
        tot += 1
    return tot

 

找vkey...

我們現在就是要找到這vkey在哪。目的很明白-->在all里面search vkey

找到了這個明顯加密過的url(有不可見人的秘密),preview看下?

這次時發現了一個songplay 文件下有vkey purl等重要東西

發現里面含有vkey,和拼接好的purl 我們接下來就是要找到這個url的變量(下面parameter 有參數)

排除參數

不斷刪去參數打開這個songplay url 直到最簡 

 

發現data后面的數字才是核心(改變其他參數對頁面幾乎沒影響)

從頁面下面的param找到所需參數(data)的含意,然后發現data里面只有有個songmid再變化

也就是只要找到songmid就可以得到vkey 然后就可以下載了 而我們之前已經得到了songmid

(songmid<==>vkey) 在找到 C開頭的那串東西 然后就可下載了

發現之前的那個文件里面有我們要找的songmid這樣一來就大功造成了

 

我開始還盲猜和前面的那個id一樣,結果發現不對我太天真了

下載

def get_qq_song_api(song_nameid,song_keyid): # 6
    '''
            獲得qqsong的下載地址
        :param song_nameid:
        :param song_keyid:
        :return:
        '''
    #在mp3文件前面發現這個songplayer文件估計時得到播放器的一個文件,里面有data參數(加密)可以把下面的參數直接拿來用即可
    # 發現里面有 vkey 還有歌給你把vkey拼好的purl 我們只要在加上頭就可以得到歌曲播放url了
    data='{"req":{"module":"CDN.SrfCdnDispatchServer","method":"GetCdnDispatch","param":{"guid":"408922362","calltype":0,"userip":""}},"req_0":{"module":"vkey.GetVkeyServer","method":"CgiGetVkey","param":{"guid":"408922362","songmid":["%s"],"songtype":[0],"uin":"1179502349","loginflag":1,"platform":"20"}},"comm":{"uin":1179502349,"format":"json","ct":24,"cv":0}}'%song_keyid
    #url='https://u.y.qq.com/cgi-bin/musicu.fcg?-=getplaysongvkey06394791332780847&g_tk=682368363&loginUin=1179502349&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0&data='+data
    #發現可以去掉多余的參數仍有我們想要的
    url='https://u.y.qq.com/cgi-bin/musicu.fcg?-=getplaysongvkey777244506080595&g_tk=682368363&loginUin=1179502349&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0&g_tk=682368363&loginUin=1179502349&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0&data='+data
    header={'cookie': 'pgv_pvi=3067481088; RK=e3RBBI+cEG; ptcz=801320b5ce845608fe88e3486ad8bb364cbc2f4ca7963d4ccb872b462bcb29cc; pgv_pvid=408922362; pac_uid=1_1179502349; tvfe_boss_uuid=6666e170218e6655; luin=o1179502349; ts_uid=4023961751; lskey=000100004e6d001faafba92cccb55e1606698d10622c8ef379cf57841d9e7fc90004782e8945132b9edd1ffc; pgv_si=s4840030208; pgv_info=ssid=s6065813728; ts_refer=ADTAGh5_playsong; qqmusic_fromtag=66; userAction=1; yqq_stat=0; yq_playschange=0; yq_playdata=; player_exist=1; ts_last=y.qq.com/portal/player.html; yplayer_open=1; yq_index=0',
           'referer': 'https://y.qq.com/portal/player.html',
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36'
            }

    req=requests.get(url,headers=header).json()
    purl=req['req_0']['data']['midurlinfo'][0]['purl']

    #print(purl)
    url = 'http://isure.stream.qqmusic.qq.com/C400'+song_nameid+purl[18:-1]

 

完整代碼:

import re
import requests
import json
import pprint
import os
import sys
import time
'''
1 找到一首歌的播放url
2 對比不同的歌找到url變化參數 id。vkey。
3 在all里面search 非id的東西(vkey...)
4 這次時發現了一個songplay 文件下有vkey purl等重要東西
5 不斷刪去參數打開這個songplay url 直到最簡 從地下的param 找到所需參數(data)的 解碼 
6 發現data里面有個songmid 
7 換不同的歌都找這個文件 發現所需參數只有songmid改變 即可以得到vkey  
8 也就是只要找到songmid就可以得到vkey 然后就可以下載了
9 一般在歌單里面可以找到id|songmid 構造 1 的url
10 下載即可

'''
class Song_info(object):
    def __init__(self):
        self.name=''
        self.song_nameid=''
        self.song_keyid=''#qq音樂特有
        self.atrist_name=''
        self.belong=''
def get_qq_song_list(key_word,page): # 7
    '''
            得到關鍵字和page的歌單
        :param key_word:
        :param page:
        :return:
    '''
    #url = 'http://c.y.qq.com/soso/fcgi-bin/client_search_cp?p='+str(page)+'&w='+key_word

    url='https://c.y.qq.com/soso/fcgi-bin/client_search_cp?p='+str(page)+'&n=10&w='+key_word
    #其實問號后面的都是參數,不能修改的就是p page,刪去參數得到的json文件有微小差別 有的key名字不一樣還是最好不要刪
    header = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36',
        'cookie': 'pgv_pvi=3067481088; RK=e3RBBI+cEG; ptcz=801320b5ce845608fe88e3486ad8bb364cbc2f4ca7963d4ccb872b462bcb29cc; pgv_pvid=408922362; pac_uid=1_1179502349; tvfe_boss_uuid=6666e170218e6655; luin=o1179502349; ts_uid=4023961751; lskey=000100004e6d001faafba92cccb55e1606698d10622c8ef379cf57841d9e7fc90004782e8945132b9edd1ffc; pgv_si=s4840030208; pgv_info=ssid=s6065813728; ts_refer=ADTAGh5_playsong; qqmusic_fromtag=66; userAction=1; yq_index=0; yqq_stat=0; yq_playschange=0; yq_playdata=; player_exist=1; yplayer_open=0; ts_last=y.qq.com/n/yqq/song/000pSUIh12A9uO.html',
        'referer': 'https://y.qq.com/portal/search.html',
        'accept - encoding': 'gzip, deflate, br'
        }
    res = requests.get(url, headers=header)
    reg=r'{.*}'
    req=re.findall(reg,res.text)[0]
    #jsonloads 可以把str 變成json文件 十分好用!
    html=json.loads(req)
    song_list = html['data']['song']['list']
    return song_list
def get_qq_song_api(song_nameid,song_keyid): # 6
    '''
            獲得qqsong的下載地址
        :param song_nameid:
        :param song_keyid:
        :return:
    '''
    #在mp3文件前面發現這個songplayer文件估計時得到播放器的一個文件,里面有data參數(加密)可以把下面的參數直接拿來用即可
    # 發現里面有 vkey 還有歌給你把vkey拼好的purl 我們只要在加上頭就可以得到歌曲播放url了
    data='{"req":{"module":"CDN.SrfCdnDispatchServer","method":"GetCdnDispatch","param":{"guid":"408922362","calltype":0,"userip":""}},"req_0":{"module":"vkey.GetVkeyServer","method":"CgiGetVkey","param":{"guid":"408922362","songmid":["%s"],"songtype":[0],"uin":"1179502349","loginflag":1,"platform":"20"}},"comm":{"uin":1179502349,"format":"json","ct":24,"cv":0}}'%song_keyid
    #url='https://u.y.qq.com/cgi-bin/musicu.fcg?-=getplaysongvkey06394791332780847&g_tk=682368363&loginUin=1179502349&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0&data='+data
    #發現可以去掉多余的參數仍有我們想要的
    url='https://u.y.qq.com/cgi-bin/musicu.fcg?-=getplaysongvkey777244506080595&g_tk=682368363&loginUin=1179502349&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0&g_tk=682368363&loginUin=1179502349&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0&data='+data
    header={'cookie': 'pgv_pvi=3067481088; RK=e3RBBI+cEG; ptcz=801320b5ce845608fe88e3486ad8bb364cbc2f4ca7963d4ccb872b462bcb29cc; pgv_pvid=408922362; pac_uid=1_1179502349; tvfe_boss_uuid=6666e170218e6655; luin=o1179502349; ts_uid=4023961751; lskey=000100004e6d001faafba92cccb55e1606698d10622c8ef379cf57841d9e7fc90004782e8945132b9edd1ffc; pgv_si=s4840030208; pgv_info=ssid=s6065813728; ts_refer=ADTAGh5_playsong; qqmusic_fromtag=66; userAction=1; yqq_stat=0; yq_playschange=0; yq_playdata=; player_exist=1; ts_last=y.qq.com/portal/player.html; yplayer_open=1; yq_index=0',
           'referer': 'https://y.qq.com/portal/player.html',
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36'
            }
    req=requests.get(url,headers=header).json()
    purl=req['req_0']['data']['midurlinfo'][0]['purl']

    #print(purl)
    url = 'http://isure.stream.qqmusic.qq.com/C400'+song_nameid+purl[18:-1]
    return  url
def qq_down_load(song_name,song_api):
    '''
            下載qq音樂
        :param song_name:
        :param song_api:
        :return:
    '''
    header = {
        'Cookie': 'pgv_pvi=3067481088; RK=e3RBBI+cEG; ptcz=801320b5ce845608fe88e3486ad8bb364cbc2f4ca7963d4ccb872b462bcb29cc; pgv_pvid=408922362; pac_uid=1_1179502349; tvfe_boss_uuid=6666e170218e6655; luin=o1179502349; lskey=000100004e6d001faafba92cccb55e1606698d10622c8ef379cf57841d9e7fc90004782e8945132b9edd1ffc; pgv_si=s4840030208; pgv_info=ssid=s6065813728; qqmusic_fromtag=66',
        'Referer': 'https://y.qq.com/portal/player.html',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36'
    }
    res = requests.get(song_api, headers=header)
    res.encoding = res.apparent_encoding
    req = res.content

    with open(song_name+'.mp3','wb') as f:
        f.write(req)
    path = os.getcwd()
    print(song_name + '  成功下載到' + path)
    time.sleep(1.5)
    return
def get_song_info_from_qq(song_info,tot,qq_song_list):
    '''
        從歌單得到每一首歌的數據
        :param tot:
        :param qq_song_list:
        :return:
        '''
    for song in qq_song_list:
        song_info[tot].name = song['songname']
        song_info[tot].atrist_name = song['singer'][0]['name']
        song_info[tot].song_nameid = song['media_mid']
        song_info[tot].song_keyid=song['songmid']
        song_info[tot].belong = 'qq'
        print(tot, song_info[tot].name,'--------歌手:', song_info[tot].atrist_name)
        tot += 1
    return tot
def qq_spider():
    print('-----------------introduction---------------')
    print('---------------程序僅供學習交流-------------')
    print('因涉及到vip音樂下載請不要討論版權問題\n本程序音樂來源--qq音樂')
    print('輸入歌手|歌曲名稱可以查找,之后再輸入編號即可下載')print('暫不支持同時下載幾首歌|音質也不知道是啥(默認?)')
    print('--------------------------------------------')
    key_word=input(' 輸入關鍵字\n  ')
    page=0
    global song_info
    song_info=[Song_info() for i in range(10000)]
    global tot
   
    while 1:
        page+=1
        qq_song_list=get_qq_song_list(key_word,page)
        tot=1
        print(qq_song_list)
        get_song_info_from_qq(song_info,tot,qq_song_list)
        #重復選擇下載歌曲並下載

        while(1):
            download_song=input('輸入要下載的一首歌編號 輸入pass加載一頁 exit 退出程序\n')
            if download_song=='exit':
                return
            if download_song=='pass':
                break
            else:
                download_song=int(download_song)
                song_name=song_info[download_song].name
                song_nameid=song_info[download_song].song_nameid
                song_keyid=song_info[download_song].song_keyid
                song_artist=song_info[download_song].atrist_name
                print(song_name, song_artist,'開始下載')
                if song_info[download_song].belong=='qq':
                    #qq音樂要兩個id 一個是song_nameid 一個是獲取vkey的song_keyid
                    print('------正在下載' + song_name + '-------')
                    song_api=get_qq_song_api(song_nameid,song_keyid)
                    qq_down_load(song_name,song_api)

if __name__=='__main__':
    qq_spider()
    time.sleep(1)

 

然而令人失望的是我們能點開的都是免費音樂,經過網站解析后發現付費(vip)試聽音樂的下載url和免費音樂不同 它不是C400開頭而是R... 開頭!!!所以只能通過網站解析來得到下載 試聽的url??!!應該找個vip進去找找規律...說不定vip下載和試聽的url又不一樣。。。

(既然有這種網站我們為什么還要寫爬蟲???多此一舉嗚嗚嗚)

網易雲的日后再補吧,心好累

還是酷我音樂最 和諧 啥都不防

 


--end--


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM