疫情在家是真的無聊,最近發現有人分享了個某我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層。