爬某音乐平台的付费音乐 - 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层。