主頁 > 軟體設計 > 爬蟲入門經典(二十三) | fiddler抓包爬取QQ音樂

爬蟲入門經典(二十三) | fiddler抓包爬取QQ音樂

2020-11-27 10:22:05 軟體設計

??大家好,我是不溫卜火,是一名計算機學院大資料專業大三的學生,昵稱來源于成語—不溫不火,本意是希望自己性情溫和,作為一名互聯網行業的小白,博主寫博客一方面是為了記錄自己的學習程序,另一方面是總結自己所犯的錯誤希望能夠幫助到很多和自己一樣處于起步階段的萌新,但由于水平有限,博客中難免會有一些錯誤出現,有紕漏之處懇請各位大佬不吝賜教!暫時只在csdn這一個平臺進行更新,博客主頁:https://buwenbuhuo.blog.csdn.net/,
1

PS:由于現在越來越多的人未經本人同意直接爬取博主本人文章,博主在此特別宣告:未經本人允許,禁止轉載!!!

目錄

  • 推薦
  • 一、前言(fiddler)
    • 1.1 簡單介紹及下載
    • 1.2 修改部分設定
  • 二、抓包分析
    • 2.1 嘗試抓包
    • 2.2 分析抓包鏈接
  • 三、部分代碼實作
    • 3.1 根據搜索資訊發送請求歌曲名字和mid
      • 1. 鏈接分析
      • 2. 代碼實作
    • 3.2 根據mid發送請求獲取vk/purl
      • 3.2.1 鏈接分析
      • 3.2.2 代碼實作
    • 3.3 根據purl獲取歌曲位元組
      • 3.3.1 分析
      • 3.3.2 代碼
  • 四、完整代碼
  • 五、運行結果


2


推薦

23
???各位如果想要交流的話,可以加下QQ交流群:974178910,里面有各種你想要的學習資料,?

???歡迎大家關注公眾號【不溫卜火】,關注公眾號即可以提前閱讀又可以獲取各種干貨哦,同時公眾號每滿1024及1024倍數則會抽獎贈送機械鍵盤一份+IT書籍1份喲~?
24

一、前言(fiddler)

1.1 簡單介紹及下載

前三篇博文主要講解了如何破解三種加密方式的方法,但是我們在爬取的時候是不是發現其實是挺繁瑣的,那么接下來的這篇文章我給大家介紹的就是能夠方便我們抓取網頁內容的fiddler抓包工具,
54
爬蟲是爬取看到的資料(可見即可爬),有些app或web的資料直接通過網頁不好分析,這個時候需要使用fiddler工具幫助分析請求和回應,
3
fiddler作為客戶端和服務端的中間代理,可以找到請求也可以找到回應,

說了這么多,下面我們先來下載fiddler:

fiddler中文版下載地址(非官方):http://www.32r.com/soft/43364.html

下載完成后打開如下圖:
4
我們下載完成之后是不是不會使用?沒關系,在此博主給出抓包工具總結,

fiddler抓包工具總結:https://www.cnblogs.com/yyhh/p/5140852.html

1.2 修改部分設定

下面我們需要修改的部分配置

  • 1. 設定成僅從瀏覽器解密
    5
  • 2. 連接的埠
    6
    fiddler如果抓取本地電腦web端的資料,代理就需要設定了,默認會代理本地的瀏覽器,

二、抓包分析

前面介紹了那么多,下面就可以開始進入正題了,
55
下面下給出QQ音樂的Web端的網址:https://y.qq.com/

2.1 嘗試抓包

  • 1. 打開網址
    7
  • 2. 下面進入qq web端搜索音樂
    8
  • 3. 單擊某個音樂試聽
    9
    但是因為著作權原因,有些音樂需要會員才能播放,建議使用會員賬號登錄,然后獲取cookie,
  • 4. 使用fiddler抓包查看
    抓包具體程序:
    抓包工具端: fiddler(點擊右下角)—>出現捕獲中,
    10
    Web端:搜索框—>自己喜歡的音樂(eg:春嬌與志明)—>選擇一個首歌播放—>等待加載完成,
    11
    再次查看抓包工具端: ctrl+F(搜索mp4格式)查看型別—> 選擇最大的檔案保存到本地
    12
    博主本人是讓檔案保存到桌面上,你們測驗的時候自己保存到自己常用的地方,然后用系統自帶的播放器即可打開,如果下載正確的話,是可以能夠正常聽到音樂的,如下圖:
    13

2.2 分析抓包鏈接

我們抓包成功以后,就可以開始分析鏈接了,
14
通過上圖,我們可以看到上下的Raw分別代表的是請求和回應,不過我們不用管下方的回應,
56
在請求框中,我們發現GET是可直接訪問的,這個時候我們可以點擊打開這個鏈接(首次打開的時候會有風險提示,我們只需繼續訪問就可以了)
15

URL如下:

https://123.6.21.20/amobile.music.tc.qq.com/C400003K4R1k1UFHot.m4a?guid=455328485&vkey=989DD22B314AA8F897A78B189A6599625AF831C0160449364EA8300956E1B684F72196D02C0170DA55F6E8215E5D9782DF0365EFE921E7BD&uin=4116&fromtag=66

我們進入這個URL之后,如果能播放音樂代表我們找的是正確的,如下圖:
16
🆗找到了鏈接,接下來我們分析這個URL的引數,引數在右側的WebForms內:
17
上圖中的這個url對應的回應就是需要抓取的資料,下面我們多測驗幾個音樂,觀察引數,

我們再來抓取另一首歌曲的的相關資訊,
18
經過多次的對比發現vkey不同,那么vkey怎么獲取到呢?
19
找啊找,終于在上圖中的的url的回應中找到了vk,其實直接找purl更方便

那么圖上的url,怎么發送請求,又要觀察它的引數
20
經過多次的對比發現,有多個引數不同,特別是songmid也不同,songmid怎么獲取呢?找啊找,終于在搜索頁面找到了songmid
21
在上圖中我們看到songmid不同,但是為了更近一步驗證,我們先對其格式化一下,

先給出JSON在線決議網站:
https://www.sojson.com/
下面進行JSON決議
22
通過格式化之后,我們看著就很明顯了,

下面我們需要找的就是搜索頁面每首歌曲的ID
23
通過抓包我們發現這個回傳的是個JSON字串
24
通過對比我們發現此部分正是我們需要的部分,下面我們來找下歌曲的mid
25

三、部分代碼實作

56

3.1 根據搜索資訊發送請求歌曲名字和mid

1. 鏈接分析

首先我們先來看下完整網址

https://c.y.qq.com/soso/fcgi-bin/client_search_cp?ct=24&qqmusic_ver=1298&new_json=1&remoteplace=txt.yqq.center&searchid=41287009571950165&t=0&aggr=1&cr=1&catZhida=1&lossless=0&flag_qc=0&p=1&n=10&w=%E6%98%A5%E5%A8%87%E4%B8%8E%E5%BF%97%E6%98%8E&g_tk_new_20200303=5381&g_tk=5381&loginUin=459804692&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0

打開如下圖所示:
26
我們發現引數有很多那么可以我們嘗試只添加名稱看能否正常訪問,鏈接如下:

https://c.y.qq.com/soso/fcgi-bin/client_search_cp?w=春嬌與志明

27

🆗那么我們就可以知道精簡過后的URL

網址:https://c.y.qq.com/soso/fcgi-bin/client_search_cp
精簡后的引數:w=春嬌與志明
獲取:歌曲名字和mid

2. 代碼實作

56

  • 1. 實作代碼
# encoding: utf-8
'''
  @author 李華鑫
  @create 2020-10-21 18:06
  Mycsdn:https://buwenbuhuo.blog.csdn.net/
  @contact: 459804692@qq.com
  @software: Pycharm
  @file: test.py
  @Version:1.0
  
'''
import requests
import re
import os
from lxml import etree


class QQMusicSpider:
    def __init__(self):
        self.url1 = "https://c.y.qq.com/soso/fcgi-bin/client_search_cp"
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36",
            "Referer": "https://y.qq.com/",
            "Cookie": "pgv_pvi=2567757824; ts_uid=64446952; pgv_pvid=6809245960; userAction=1; RK=0ID4VI/yGY; ptcz=6f4eaa825e99af36068b5d51b8e34c1c0087b9c95c44f7b062d5cff7b3c70d22; euin=owSF7e4kNKnz; qm_keyst=Q_H_L_2a6K5_50eO5-itw83Uio7kRWq8WgGbPI1BGlM1c8ng4qZt_ZAxTRmHb8B4SQBWD; uin=278455900; tmeLoginType=2; psrf_qqopenid=8E8FC9D9774A8788D4DF1FD73F2B8D88; psrf_qqaccess_token=22EEB4580A1D37E9AB61B4A2CD6FC0CE; psrf_qqunionid=; qqmusic_key=Q_H_L_2a6K5_50eO5-itw83Uio7kRWq8WgGbPI1BGlM1c8ng4qZt_ZAxTRmHb8B4SQBWD; psrf_musickey_createtime=1602572393; psrf_access_token_expiresAt=1610348393; psrf_qqrefresh_token=1873C9B55CC272116295F7B5AC7DE014; yqq_stat=0; pgv_info=ssid=s3690755542; ts_refer=ADTAGmyqq; pgv_si=s1594386432; yplayer_open=1; qqmusic_fromtag=66; yq_playschange=0; yq_playdata=; player_exist=1; yq_index=1; ts_last=y.qq.com/n/yqq/song/002t78Qs1Av9Kn.html"
        }
        self.w = ""

    def get_search_content(self):
        """獲取搜索結果"""
        data = self.parse_content(url=self.url1, headers=self.headers, params={"w": self.w}).decode("utf-8")
        song_mid_list = re.findall(r'"songmid":"(.*?)"', data)
        song_name_list = re.findall(r'"songname":"(.*?)"', data)
        return list(zip(song_name_list, song_mid_list))


    def parse_content(self, url, headers, params={}):
        """決議url,回傳回應位元組"""
        response = requests.get(url, headers=headers, params=params)
        return response.content

    def parse_json(self, url, headers, params={}):
        """決議url,回傳json"""
        response = requests.get(url, headers=headers, params=params)
        return response.json()

    def parse_xpath(self, html):
        """使用xpath決議html,回傳xpath物件"""
        etree_obj = etree.HTML(html)
        return etree_obj

    def start(self):
        """開始爬蟲"""
        self.w = input("請輸入搜索的歌曲/歌手:")
        search_data = self.get_search_content()
        for index,value in enumerate(search_data):
            print("({}){}".format(index+1,value[0]))
        index = int(input("請輸入歌曲編號進行下載:"))
        print(search_data[index-1])

if __name__ == '__main__':
    QQMusicSpider().start()
  • 2、測驗結果
    28

3.2 根據mid發送請求獲取vk/purl

經過上一小部分的代碼測驗,我們已經能夠獲取到mid和歌手資訊,下面我們根據歌曲的mid搜索vk,

3.2.1 鏈接分析

下面我們現在抓包工具中找到vk的URL

https://u.y.qq.com/cgi-bin/musics.fcg?-=getplaysongvkey6182361656698969&g_tk=5381&sign=zzancg5ohny8sa7re612a04ee9b6b58b82bcdaa064240f964&loginUin=459804692&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0&data=%7B%22req%22%3A%7B%22module%22%3A%22CDN.SrfCdnDispatchServer%22%2C%22method%22%3A%22GetCdnDispatch%22%2C%22param%22%3A%7B%22guid%22%3A%22455328485%22%2C%22calltype%22%3A0%2C%22userip%22%3A%22%22%7D%7D%2C%22req_0%22%3A%7B%22module%22%3A%22vkey.GetVkeyServer%22%2C%22method%22%3A%22CgiGetVkey%22%2C%22param%22%3A%7B%22guid%22%3A%22455328485%22%2C%22songmid%22%3A%5B%22004Uln1G2Aunqw%22%5D%2C%22songtype%22%3A%5B0%5D%2C%22uin%22%3A%22459804692%22%2C%22loginflag%22%3A1%2C%22platform%22%3A%2220%22%7D%7D%2C%22comm%22%3A%7B%22uin%22%3A459804692%2C%22format%22%3A%22json%22%2C%22ct%22%3A24%2C%22cv%22%3A0%7D%7D

我們打開之后如下圖:
29
下面我們找到data內的資料并復制出來

{"req_0":{"module":"vkey.GetVkeyServer","method":"CgiGetVkey","param":{"guid":"455328485","songmid":["%s"],"songtype":[0],"uin":"0","loginflag":1,"platform":"20"}},"comm":{"uin":0,"format":"json","ct":24,"cv":0}}

30
🆗說明我們測驗是成功的,

網址:https://u.y.qq.com/cgi-bin/musics.fcg
精簡后的引數:data=xxx,這里引數有有{}注意引數拼接問題
獲取:purl

3.2.2 代碼實作

  • 1. 實作代碼
import requests
import re
import os
from lxml import etree


class QQMusicSpider:
    def __init__(self):
        self.url1 = "https://c.y.qq.com/soso/fcgi-bin/client_search_cp"
        self.url2 = 'https://u.y.qq.com/cgi-bin/musicu.fcg?data={"req_0":{"module":"vkey.GetVkeyServer","method":"CgiGetVkey","param":{"guid":"602087500","songmid":["%s"],"songtype":[0],"uin":"0","loginflag":1,"platform":"20"}},"comm":{"uin":0,"format":"json","ct":24,"cv":0}}'
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36",
            "Referer": "https://y.qq.com/",
            "Cookie": "pgv_pvi=2567757824; ts_uid=64446952; pgv_pvid=6809245960; userAction=1; RK=0ID4VI/yGY; ptcz=6f4eaa825e99af36068b5d51b8e34c1c0087b9c95c44f7b062d5cff7b3c70d22; euin=owSF7e4kNKnz; qm_keyst=Q_H_L_2a6K5_50eO5-itw83Uio7kRWq8WgGbPI1BGlM1c8ng4qZt_ZAxTRmHb8B4SQBWD; uin=278455900; tmeLoginType=2; psrf_qqopenid=8E8FC9D9774A8788D4DF1FD73F2B8D88; psrf_qqaccess_token=22EEB4580A1D37E9AB61B4A2CD6FC0CE; psrf_qqunionid=; qqmusic_key=Q_H_L_2a6K5_50eO5-itw83Uio7kRWq8WgGbPI1BGlM1c8ng4qZt_ZAxTRmHb8B4SQBWD; psrf_musickey_createtime=1602572393; psrf_access_token_expiresAt=1610348393; psrf_qqrefresh_token=1873C9B55CC272116295F7B5AC7DE014; yqq_stat=0; pgv_info=ssid=s3690755542; ts_refer=ADTAGmyqq; pgv_si=s1594386432; yplayer_open=1; qqmusic_fromtag=66; yq_playschange=0; yq_playdata=; player_exist=1; yq_index=1; ts_last=y.qq.com/n/yqq/song/002t78Qs1Av9Kn.html"
        }
        self.w = ""

    def get_search_content(self):
        """獲取搜索結果"""
        data = self.parse_content(url=self.url1, headers=self.headers, params={"w": self.w}).decode("utf-8")
        song_mid_list = re.findall(r'"songmid":"(.*?)"', data)
        song_name_list = re.findall(r'"songname":"(.*?)"', data)
        return list(zip(song_name_list, song_mid_list))

    def get_vk(self, songmid):
        """根據歌曲的mid搜索vk"""
        data = self.parse_json(url=self.url2 % songmid, headers=self.headers)
        print(data)

    def parse_content(self, url, headers, params={}):
        """決議url,回傳回應位元組"""
        response = requests.get(url, headers=headers, params=params)
        return response.content

    def parse_json(self, url, headers, params={}):
        """決議url,回傳json"""
        response = requests.get(url, headers=headers, params=params)
        return response.json()

    def parse_xpath(self, html):
        """使用xpath決議html,回傳xpath物件"""
        etree_obj = etree.HTML(html)
        return etree_obj

    def start(self):
        """開始爬蟲"""
        self.w = input("請輸入搜索的歌曲/歌手:")
        search_data = self.get_search_content()
        for index,value in enumerate(search_data):
            print("({}){}".format(index+1,value[0]))
        index = int(input("請輸入歌曲編號進行下載:"))
        self.get_vk(search_data[index-1][1])


if __name__ == '__main__':
    QQMusicSpider().start()
  • 2. 運行結果
    31
  • 3. 格式化查看
    32
  • 4. 嘗試決議
# 代碼如下
data["req_0"]["data"]["midurlinfo"][0]["purl"]

理論上到這里就可以獲取到我們所需要的URL,

3.3 根據purl獲取歌曲位元組

3.3.1 分析

首先我們回憶下剛開始使用抓包工具抓取的音樂的URL
33
我們把url復制出來:

https://123.6.21.20/amobile.music.tc.qq.com/C400003K4R1k1UFHot.m4a?guid=455328485&vkey=EA9D246E2EB9BDCFFBF840E6479B26495C97E5C0EE12BC8FA81BDAEFB47399C5169A4813DA033FA9FEE710887216632680B11940CFC77F64&uin=0&fromtag=66

下面我們看下我們上一步中截取出來的purl
34
把它復制出來

C400003K4R1k1UFHot.m4a?guid=602087500&vkey=D81DEE79601184E377220701E1EB24FA3B4F9B869F8C4D77E8A82ACAA73A088D8A6FB8C934D8430328B3FA93628F4B723AC0759214464A6F&uin=0&fromtag=66

下面我們拼接一下url試試:

https://123.6.21.20/amobile.music.tc.qq.com/C400003K4R1k1UFHot.m4a?guid=602087500&vkey=D81DEE79601184E377220701E1EB24FA3B4F9B869F8C4D77E8A82ACAA73A088D8A6FB8C934D8430328B3FA93628F4B723AC0759214464A6F&uin=0&fromtag=66

35
🆗我們拼接的和我們所想的是一樣的,

網址:https://123.6.21.20/amobile.music.tc.qq.com/
引數:拼接purl
獲取:歌曲位元組

3.3.2 代碼

  • 1. 測驗代碼
import requests
import re
import os
from lxml import etree
requests.packages.urllib3.disable_warnings()

class QQMusicSpider:
    def __init__(self):
        self.url1 = "https://c.y.qq.com/soso/fcgi-bin/client_search_cp"
        self.url2 = 'https://u.y.qq.com/cgi-bin/musicu.fcg?data={"req_0":{"module":"vkey.GetVkeyServer","method":"CgiGetVkey","param":{"guid":"602087500","songmid":["%s"],"songtype":[0],"uin":"0","loginflag":1,"platform":"20"}},"comm":{"uin":0,"format":"json","ct":24,"cv":0}}'
        self.url3 = "https://123.6.21.20/amobile.music.tc.qq.com/"
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36",
            "Referer": "https://y.qq.com/",
            "Cookie": "pgv_pvi=2567757824; ts_uid=64446952; pgv_pvid=6809245960; userAction=1; RK=0ID4VI/yGY; ptcz=6f4eaa825e99af36068b5d51b8e34c1c0087b9c95c44f7b062d5cff7b3c70d22; euin=owSF7e4kNKnz; qm_keyst=Q_H_L_2a6K5_50eO5-itw83Uio7kRWq8WgGbPI1BGlM1c8ng4qZt_ZAxTRmHb8B4SQBWD; uin=278455900; tmeLoginType=2; psrf_qqopenid=8E8FC9D9774A8788D4DF1FD73F2B8D88; psrf_qqaccess_token=22EEB4580A1D37E9AB61B4A2CD6FC0CE; psrf_qqunionid=; qqmusic_key=Q_H_L_2a6K5_50eO5-itw83Uio7kRWq8WgGbPI1BGlM1c8ng4qZt_ZAxTRmHb8B4SQBWD; psrf_musickey_createtime=1602572393; psrf_access_token_expiresAt=1610348393; psrf_qqrefresh_token=1873C9B55CC272116295F7B5AC7DE014; yqq_stat=0; pgv_info=ssid=s3690755542; ts_refer=ADTAGmyqq; pgv_si=s1594386432; yplayer_open=1; qqmusic_fromtag=66; yq_playschange=0; yq_playdata=; player_exist=1; yq_index=1; ts_last=y.qq.com/n/yqq/song/002t78Qs1Av9Kn.html"
        }
        self.w = ""

    def get_search_content(self):
        """獲取搜索結果"""
        data = self.parse_content(url=self.url1, headers=self.headers, params={"w": self.w}).decode("utf-8")
        song_mid_list = re.findall(r'"songmid":"(.*?)"', data)
        song_name_list = re.findall(r'"songname":"(.*?)"', data)
        return list(zip(song_name_list, song_mid_list))

    def get_purl(self, songmid):
        """根據歌曲的mid搜索vk"""
        data = self.parse_json(url=self.url2 % songmid, headers=self.headers)
        return data["req_0"]["data"]["midurlinfo"][0]["purl"]

    def parse_content(self, url, headers, params={}):
        """決議url,回傳回應位元組"""
        response = requests.get(url, headers=headers, params=params)
        return response.content

    def parse_json(self, url, headers, params={}):
        """決議url,回傳json"""
        response = requests.get(url, headers=headers, params=params)
        return response.json()

    def parse_xpath(self, html):
        """使用xpath決議html,回傳xpath物件"""
        etree_obj = etree.HTML(html)
        return etree_obj

    def start(self):
        """開始爬蟲"""
        self.w = input("請輸入搜索的歌曲/歌手:")
        search_data = self.get_search_content()
        for index,value in enumerate(search_data):
            print("({}){}".format(index+1,value[0]))
        index = int(input("請輸入歌曲編號進行下載:"))
        purl = self.get_purl(search_data[index-1][1])
        print(self.url3+purl)


if __name__ == '__main__':
    QQMusicSpider().start()
  • 2. 運行結果
    36

四、完整代碼

# encoding: utf-8
'''
  @author 李華鑫
  @create 2020-10-24 14:37
  Mycsdn:https://buwenbuhuo.blog.csdn.net/
  @contact: 459804692@qq.com
  @software: Pycharm
  @file: QQ音樂.py
  @Version:1.0
  
'''
import requests
import re
import os
from lxml import etree


class QQMusicSpider:
    def __init__(self):
        self.url1 = "https://c.y.qq.com/soso/fcgi-bin/client_search_cp"
        self.url2 = 'https://u.y.qq.com/cgi-bin/musicu.fcg?data={"req_0":{"module":"vkey.GetVkeyServer","method":"CgiGetVkey","param":{"guid":"602087500","songmid":["%s"],"songtype":[0],"uin":"0","loginflag":1,"platform":"20"}},"comm":{"uin":0,"format":"json","ct":24,"cv":0}}'
        self.url3 = "https://123.6.21.20/amobile.music.tc.qq.com/"
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36",
            "Referer": "https://y.qq.com/",
            "Cookie": "pgv_pvi=2567757824; ts_uid=64446952; pgv_pvid=6809245960; userAction=1; RK=0ID4VI/yGY; ptcz=6f4eaa825e99af36068b5d51b8e34c1c0087b9c95c44f7b062d5cff7b3c70d22; euin=owSF7e4kNKnz; qm_keyst=Q_H_L_2a6K5_50eO5-itw83Uio7kRWq8WgGbPI1BGlM1c8ng4qZt_ZAxTRmHb8B4SQBWD; uin=278455900; tmeLoginType=2; psrf_qqopenid=8E8FC9D9774A8788D4DF1FD73F2B8D88; psrf_qqaccess_token=22EEB4580A1D37E9AB61B4A2CD6FC0CE; psrf_qqunionid=; qqmusic_key=Q_H_L_2a6K5_50eO5-itw83Uio7kRWq8WgGbPI1BGlM1c8ng4qZt_ZAxTRmHb8B4SQBWD; psrf_musickey_createtime=1602572393; psrf_access_token_expiresAt=1610348393; psrf_qqrefresh_token=1873C9B55CC272116295F7B5AC7DE014; yqq_stat=0; pgv_info=ssid=s3690755542; ts_refer=ADTAGmyqq; pgv_si=s1594386432; yplayer_open=1; qqmusic_fromtag=66; yq_playschange=0; yq_playdata=; player_exist=1; yq_index=1; ts_last=y.qq.com/n/yqq/song/002t78Qs1Av9Kn.html"
        }
        self.w = ""

    def get_search_content(self):
        """獲取搜索結果"""

        data = self.parse_content(url=self.url1, headers=self.headers, params={"w": self.w}).decode("utf-8")
        song_mid_list = re.findall(r'"songmid":"(.*?)"', data)
        song_name_list = re.findall(r'"songname":"(.*?)"', data)
        return list(zip(song_name_list, song_mid_list))

    def get_purl(self, songmid):
        """根據歌曲的mid搜索vk"""
        data = self.parse_json(url=self.url2 % songmid, headers=self.headers)
        return data["req_0"]["data"]["midurlinfo"][0]["purl"]

    def save_song(self, url,song_name):
        """下載歌曲"""
        print("-"*100)
        filename = song_name+".mp3"
        print("{}下載中...".format(filename))
        data = self.parse_content(url=url, headers=self.headers)
        if data:
            with open(filename,"wb") as file:
                file.write(data)
            print("{}下載完畢".format(filename))
        else:
            print("{}下載失敗,建議豪華綠鉆用戶使用會員賬號修改程式cookie".format(filename))
        print("-" * 100)


    def parse_content(self, url, headers, params={}):
        """決議url,回傳回應位元組"""
        response = requests.get(url, headers=self.headers, params=params,verify=False)
        return response.content

    def parse_json(self, url, headers, params={}):
        """決議url,回傳json"""
        response = requests.get(url, headers=headers, params=params,verify=False)
        return response.json()

    def parse_xpath(self, html):
        """使用xpath決議html,回傳xpath物件"""
        etree_obj = etree.HTML(html)
        return etree_obj

    def start(self):
        """開始爬蟲"""
        self.w = input("輸入要搜索的歌曲/歌手:")
        search_data = self.get_search_content()

        while True:
            for index, value in enumerate(search_data):
                print("({}){}".format(index + 1, value[0]))
            print("(0)退出程式")
            index = int(input("選擇歌曲編號進行下載:"))
            if index == 0:
                break
            purl = self.get_purl(search_data[index - 1][1])
            self.save_song(url=self.url3 + purl,song_name=search_data[index - 1][0])

if __name__ == '__main__':
    QQMusicSpider().start()

五、運行結果

37
38
39
50

美好的日子總是短暫的,雖然還想繼續與大家暢談,但是本篇博文到此已經結束了,如果還嫌不夠過癮,不用擔心,我們下篇見!


51

??好書不厭讀百回,熟讀課思子自知,而我想要成為全場最靚的仔,就必須堅持通過學習來獲取更多知識,用知識改變命運,用博客見證成長,用行動證明我在努力,
??如果我的博客對你有幫助、如果你喜歡我的博客內容,請“點贊” “評論”“收藏”一鍵三連哦!聽說點贊的人運氣不會太差,每一天都會元氣滿滿呦!如果實在要白嫖的話,那祝你開心每一天,歡迎常來我博客看看,
??碼字不易,大家的支持就是我堅持下去的動力,點贊后不要忘了關注我哦!

52
53

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/227981.html

標籤:其他

上一篇:Android -- 讓我一個外行來告訴你Android的多Activity切換中保持Socket長連接的一個實作方法

下一篇:Java中的單例模式最全決議

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more