爬某音樂平台的付費音樂 - Python - 被標題黨搞煩了的可以來看看


疫情在家是真的無聊,最近發現有人分享了個某我vip音樂的接口。前面做爬蟲的時候一直只能爬到免費音樂,今天來爬爬付費音樂。當然,免費的也可以這樣爬。申明:本文僅做學習交流使用,如有侵權,請聯系我刪除。

爬蟲思路:

  • 搜索歌曲或者歌手;
  • 分析搜索結果頁,有json找json,沒json找網頁渲染的列表;然后通過parsel等分析歌曲列表信息;
  • 點擊一首歌曲,通過開發者工具分析,查找歌曲請求的地方;
  • 擼碼實現過程;
  • 保存歌曲;
  • 用excel文檔或者csv進行保存歌曲有關的文字信息(方便后續做可視化)

 

第一段代碼,用函數寫的:

  1 import os.path
  2 import time
  3 from urllib.parse import quote
  4 import openpyxl
  5 import requests
  6 import concurrent.futures
  7 
  8 def get_response(page_url):
  9     headers = {
 10         "Cookie": "_xxx",
 11         "csrf": "x",
 12         # "Host": "www.xwo.cn",
 13         "Referer": "http://www.xwo.cn/",
 14         "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.82 Safari/537.36",
 15     }
 16     response = requests.get(url=page_url, headers=headers)
 17     response.raise_for_status()
 18     response.encoding = response.apparent_encoding
 19     response.encoding = 'utf-8'
 20     return response
 21 
 22 def save_media(musicRealUrl, musicName, artist, wusun):
 23     # 保存音頻
 24     # 首先創建文件
 25     filePath = f'./{singer}/'
 26     if not os.path.exists(filePath):
 27         os.mkdir(filePath)
 28     # 開始請求音樂的真實地址
 29     musicContent = get_response(musicRealUrl).content
 30     with open(filePath + musicName + ' - ' + artist + ' - ' + wusun + '.mp3', mode='wb') as f:
 31         f.write(musicContent)
 32         print(f'正在下載------------------------------->{musicName},請稍等!')
 33 
 34 def main(singer, numPage):
 35     # 創建一個文檔進行保存文字信息
 36     wb = openpyxl.Workbook()
 37     ws = wb.create_sheet(title=f'{singer}', index=0)
 38     wb.remove(wb['Sheet'])
 39     # 創建表頭
 40     sheetHeader = ['歌曲名','歌曲id','歌手','歌手id','專輯','專輯id','是否無損',
 41                    '是否收費','是否有mv','時長','評分','發行日期']
 42     ws.append(sheetHeader)
 43     # 解析音樂列表頁面
 44     for page in range(1, int(numPage)):
 45         print(f"------------------------開始請求第{page}頁數據,請稍等。--------------------------------------")
 46         url = f'http://www.xxx.cn/api/www/search/searchMusicBykeyWord?key={quote(singer)}&pn={page}&rn=30&httpsStatus=1&reqId=a2dd3070-b252-11ec-a25f-e554156f3f5e'
 47         url = f'http://www.xxx.cn/api/www/search/searchMusicBykeyWord?key={quote(singer)}&pn={page}&rn=30&httpsStatus=1&reqId=59ec28e1-b25b-11ec-9f5c-69be3534bacd'
 48         print(url)
 49         # exit()
 50         json_data = get_response(url).json()
 51         song_list = json_data['data']['list'] # 歌曲列表
 52         for item in song_list:
 53             # 開始解析歌曲列表
 54             musicName = item['name'] # 歌曲名稱
 55             musicId = item['rid'] # 歌曲
 56             artist = item['artist'] # 歌手
 57             aristId = item['artistid']  # 歌手編號
 58             album = item['album'] # 歌曲所屬專輯
 59             if album:
 60                 album = item['album']
 61             else:
 62                 album = None
 63 
 64             albumid = item['albumid']  # 專輯ID
 65             if albumid:
 66                 albumid = item['albumid']
 67             else:
 68                 albumid = None
 69 
 70             lossLess = item['hasLossless'] # 是否無損
 71             if lossLess:
 72                 lossLess = '無損'
 73             else:
 74                 lossLess = ''
 75 
 76             listenFee = item['isListenFee'] # 是否收費
 77             if listenFee:
 78                 listenFee = ''
 79             else:
 80                 listenFee = ''
 81 
 82             hasMv = item['hasmv'] # 是否有mv
 83             if hasMv:
 84                 hasMv = ''
 85             else:
 86                 hasMv = '沒有'
 87             songTime = item['songTimeMinutes'] # 歌曲時長
 88             songScore = item['score100'] # 歌曲評分
 89             releaseDate = item['releaseDate'] # 歌曲發行時間
 90             if releaseDate == "1970-01-01":
 91                 releaseDate = '未知'
 92             else:
 93                 releaseDate = item['releaseDate']
 94             ws.append([musicName, musicId, artist, artist, album, albumid, lossLess,
 95                        listenFee, hasMv, songTime, songScore, releaseDate])
 96             # 開始拼接url
 97             musicRequestUrl = 'https://xxx.kuwo.cn/anti.s?response=url&rid=MUSIC_' + str(musicId) + '&format=acc|mp3&type=convert_url'
 98             # print(musicRequestUrl)
 99             musicRealUrl = get_response(musicRequestUrl).text
100             print(musicRealUrl)
101             # 開始請求真實地址
102             save_media(musicRealUrl=musicRealUrl, musicName=musicName, artist=artist, wusun=lossLess)
103     wb.close()
104     wb.save(f'./{singer}//{singer} - {time.strftime("%Y-%m-%d", time.localtime())}.xlsx') # 按歌手名和當前日期進行保存
105 
106 if __name__ == "__main__":
107     singer = input('你想要下載的歌手:')
108     numPage = input('你想要下載前幾頁的歌曲(一頁30條):')
109     url = f'http://www.kuwo.cn/search/list?key={quote(singer)}'
110     main(singer, numPage)

 

第二段代碼是把上面的函數整理成了類方法,用面向對象方法寫的:

  1 import time
  2 import openpyxl
  3 import requests
  4 import os
  5 from urllib.parse import quote
  6 
  7 class kuwoSpider():
  8     headers = {
  9         "Cookie": "xx8x",
 10         "csrf": "xx", # 統稱為令牌
 11         # "Host": "www.kuwo.cn", # 這里的host在下載頁面的時候不需要,不然會403
 12         "Referer": "http://www.kxxo.cn/",
 13         "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.82 Safari/537.36",
 14     }
 15 
 16     def __init__(self, singer, numPage, headers=headers):
 17         self.singer = singer
 18         self.numPage = numPage
 19         self.headers = headers
 20 
 21     def get_response(self, url):
 22         response = requests.get(url=url, headers=self.headers)
 23         response.raise_for_status()
 24         response.encoding = response.apparent_encoding
 25         response.encoding = 'utf-8'
 26         return response
 27 
 28     def save_media(self, musicRealUrl, musicName, artist, wusun):
 29         # 保存歌曲
 30         filePath = f'./{self.singer}/' # ./表示在當前目錄下創建一個文件
 31         if not os.path.exists(filePath):
 32             os.mkdir(filePath)
 33 
 34         # 嘗試解析音樂的二進制數據
 35         musicContent = self.get_response(url=musicRealUrl).content
 36         # 開始保存
 37         with open(filePath + musicName + ' - ' + artist + ' - ' + wusun + '.acc', mode='wb') as f:
 38             f.write(musicContent)
 39             print(f'正在下載------------->{musicName},請稍等!')
 40 
 41     def parse_search_page(self,):
 42         # 創建excel文檔
 43         wb = openpyxl.Workbook() # 創建工作簿
 44         ws = wb.create_sheet(title=f'{self.singer} - {time.strftime("%Y-%m-%d", time.localtime())}', index=0) # 創建表
 45         ws.append(['歌曲名','歌曲id','歌手','歌手id','專輯','專輯id','是否無損',
 46                    '是否收費','是否有mv','時長','評分','發行日期']) # 添加表頭
 47         wb.remove(wb['Sheet'])
 48         # 解析搜索頁,解析歌曲並保存歌曲的信息
 49         for page in range(1, self.numPage):
 50             url = f'http://www.xxx.cn/api/www/search/searchMusicBykeyWord?key={quote(self.singer)}&pn={page}&rn=30&httpsStatus=1&reqId=59ec28e1-b25b-11ec-9f5c-69be3534bacd'
 51             # 開始解析歌曲頁面
 52             json_data = self.get_response(url=url).json()
 53             # 歌曲列表
 54             song_lists = json_data['data']['list']
 55             # print(song_lists)
 56             # 提取每首歌的歌曲信息
 57             for item in song_lists:
 58                 # 開始解析歌曲列表
 59                 musicName = item['name']  # 歌曲名稱
 60                 musicId = item['rid']  # 歌曲
 61                 artist = item['artist']  # 歌手
 62                 aristId = item['artistid']  # 歌手編號
 63                 album = item['album']  # 歌曲所屬專輯
 64                 if album:
 65                     album = item['album']
 66                 else:
 67                     album = None
 68 
 69                 albumid = item['albumid']  # 專輯ID
 70                 if albumid:
 71                     albumid = item['albumid']
 72                 else:
 73                     albumid = None
 74 
 75                 lossLess = item['hasLossless']  # 是否無損
 76                 if lossLess:
 77                     lossLess = '無損'
 78                 else:
 79                     lossLess = ''
 80 
 81                 listenFee = item['isListenFee']  # 是否收費
 82                 if listenFee:
 83                     listenFee = ''
 84                 else:
 85                     listenFee = ''
 86 
 87                 hasMv = item['hasmv']  # 是否有mv
 88                 if hasMv:
 89                     hasMv = ''
 90                 else:
 91                     hasMv = '沒有'
 92                 songTime = item['songTimeMinutes']  # 歌曲時長
 93                 songScore = item['score100']  # 歌曲評分
 94                 releaseDate = item['releaseDate']  # 歌曲發行時間
 95                 if releaseDate == "1970-01-01":
 96                     releaseDate = '未知'
 97                 else:
 98                     releaseDate = item['releaseDate']
 99                 #  開始保存文本信息到excel
100                 ws.append([musicName, musicId, artist, artist, album, albumid, lossLess,
101                        listenFee, hasMv, songTime, songScore, releaseDate])
102                 # 拼接歌曲播放的請求url
103                 musicRequestUrl = 'https://xxx.kuwo.cn/anti.s?response=url&rid=MUSIC_' + str(musicId) + '&format=acc|mp3&type=convert_url'
104                 # 請求url並獲取到下載地址
105                 musicRealUrl = requests.get(url=musicRequestUrl).text # 這里的headers不一樣
106                 # 開始調用函數進行保存
107                 self.save_media(musicRealUrl=musicRealUrl, musicName=musicName, artist=artist, wusun=lossLess)
108 
109         wb.close() # 關閉表格
110         wb.save(f'./{self.singer}//{self.singer} - {time.strftime("%Y-%m-%d", time.localtime())}.xlsx') # 保存到當前歌手目錄下
111 
112 
113     def run(self):
114         # 最后執行的函數
115         self.parse_search_page()
116 
117 if __name__ == "__main__":
118     # 程序入口,傳入歌手或者歌曲名還有要采集的頁數
119     singer = input("請輸入歌手或者歌曲:")
120     numPage = int(input("請輸入要采集的最大頁數(每頁30條):")) # 強制轉換,不然運行程序的時候會出現str和int類型的問題
121     app = kuwoSpider(singer, numPage)
122     app.run()

程序運行截圖:

 

幾個問題:

  • headers參數,根據開發者工具添加的時候最好按順序,比如,cookies,user-agent,不要user-agent,cookies,不然會網頁會無響應,程序獲取不到數據;
  • 請求歌曲真實播放地址的時候,就是.mp3后綴的地址的時候,headers里的host參數,要剔除,不然會無響應,403,程序獲取不到數據;
  • 保存excel文件的時候,我這里寫的都是變量,要注意f和/還有{,一不小心就出錯了;
  • 定頁碼的時候,可以定成一頁一頁爬取,每次爬完運行程序,我這里是批量爬取;

為防止面向監獄編程,代碼里有關headers參數和url參數地方都有改動。很多人爬付費音樂的時候卡在播放真實地址的那個地方,他的程序都只能獲取到免費音樂,遇到付費的就提示類似的:‘該為付費音樂’怎么地,那是因為在沒有會員的前提下,我們所能抓取的東西,就只能那么多。有心人可以百度那個播放請求的地址,也可以自己充個會員,然后通過開發者工具抓取播放請求的地址,還有一種方法,就是留言留郵箱,我發給你。

最后:不要相信那種標題黨類似 -- 白嫖,用python爬取付費音樂。這種人只會嘩眾取寵,為了點流量和博人眼球,浪費查找資料人的時間和感情,用陽壽在寫代碼,祝他們早點下18層。


免責聲明!

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



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