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

posted @ 2022-04-03 16:13  、一叶孤城  阅读(1334)  评论(1编辑  收藏  举报