爬取 音乐歌曲(千千,酷我)
Posted cherrypill
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了爬取 音乐歌曲(千千,酷我)相关的知识,希望对你有一定的参考价值。
没有用多线程
1 千千音乐
步骤|思路:
首先要能爬取一首歌然后再爬取歌单的第一面,最后爬取可选择的页数
爬取一首歌首先要找到network里的media 里面如果有东西则可发现这才是这首歌真实的 播放|下载 地址 然后根据xcode来搜索(倒推)它的下载源比如有 songlink,ting...等类似的文件,进去后preview可以看到歌曲的各种介绍,最后爬进这个下载源获得歌曲下载链接等数据 即可
坑点:
(我认为)json文件是像字典一样的所以开头结尾要是{}如果{}前后有东西要先正则除去,之后才能json.loads(xxx)否则会报错说什么不是json格式(这里百度只会叫你该单引号之类的然鹅实际上是上面的问题)
如果request.get(url,parama,headers).text=‘‘ .content=b‘‘则说明header要加referer参数(被反爬了?)
具体讲解见代码
from bs4 import BeautifulSoup import requests from selenium import webdriver import urllib.request import pprint import json import re ‘‘‘ 先找mp3到的下载地址在根据xcode寻找到包含这个歌曲的那个歌单 然后在搜索页面(network第一个)ctrl+f搜索歌曲id ‘‘‘ if __name__==‘__main__‘: search_api=‘http://music.taihe.com/search?‘ singer_name={"key":‘林俊杰‘} print(‘输入歌手名称‘) #singer_name=input() #page_number=int(input()) header = { ‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/80.0.3987.132 Safari/537.36‘ , ‘Cookie‘: ‘E1RjBzZzY1cDRlTmRyWTFtMGN5b0pNM1VTcXQ3aVZTWnJ1fkk2aG94LWRiT1pkRVFBQUFBJCQAAAAAAAAAAAEAAAAOw~ynMTQ2MzUzNTMxNWZibAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ3fvl2d375da0; BAIDUID=10E17A0301BD00EC5B8D0E92CA54188F:FG=1; userid=2818360078; u_id=; u_t=; u_login=1; u_lo=0; BAIDU_SSP_lcr=https://my.oschina.net/zhmlvft/blog/472466?p={{totalPage}}; Hm_lvt_d0ad46e4afeacf34cd12de4c9b553aa6=1583374517,1583387044,1583387159,1583387225; tracesrc=-1%7C%7C-1; __qianqian_pop_tt=6; Hm_lpvt_d0ad46e4afeacf34cd12de4c9b553aa6=1583400033‘ , ‘Referer‘: ‘http://music.taihe.com/song/1137385?pst=sug‘} res=requests.get(search_api,params=singer_name,headers=header) #params可以直接自动识别并拼接关键词就不用我们自己拼了 #得到一个响应 res.encoding=res.apparent_encoding#自动获取编码形式,万能 html=res.text song_ids=re.findall(r‘"sid":(d+),"‘,html) #print(song_ids) #这里直接在源码里面搜其中一个歌的id,不过要先筛选因为会找到很多包含这首歌id的语句 # 这样就能搜到其他歌了因为其他歌的id肯定也符合这个式子, #这个url获得是先播放这首歌在find xcode 可以找到一个得到ting文件这个文件里面有 url=‘http://musicapi.taihe.com/v1/restserver/ting?method=baidu.ting.song.playAAC&format=jsonp&callback=jQuery17209677148092769645_1583387566116&songid=1137385&from=web&_=1583387569190‘ #找同一歌手两首歌发现上面的url只有song_id改变了故可以猜测。。。 header={‘User-Agent‘:‘Mozilla / 5.0(Windows NT 10.0;Win64;x64) AppleWebKit / 537.36(KHTML, likeGecko) Chrome / 80.0.3987.132Safari / 537.36‘ ,‘Cookie‘:‘E1RjBzZzY1cDRlTmRyWTFtMGN5b0pNM1VTcXQ3aVZTWnJ1fkk2aG94LWRiT1pkRVFBQUFBJCQAAAAAAAAAAAEAAAAOw~ynMTQ2MzUzNTMxNWZibAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ3fvl2d375da0;BAIDUID = 10E17A0301BD00EC5B8D0E92CA54188F: FG = 1;userid = 2818360078;u_login = 1;BAIDU_SSP_lcr = https: // my.oschina.net / zhmlvft / blog / 472466?p = {{totalPage}}‘ ,‘Referer‘:‘http: // music.taihe.com / song / 1332939‘ } #现在只需要访问这个网址的showlink|filelink即可下载 这个这么难找的网址感觉一般都有反爬 # 可以先输出一下res(如果是200说明正常访问)看看返回在判断加不加header res=requests.get(url,headers=header) element=re.findall(r‘{.*}‘,res.text)[0] #正则除去开头那些东西否则不会被识别为json文件 print(element) info=json.loads(element) # 要看一下文件时什么格式然后用相应的处理方式 song_download_api=info[‘bitrate‘][‘show_link‘] song_name=info[‘songinfo‘][‘title‘] print(song_name,song_download_api) # with open(‘隔空拥抱.mp3‘,‘wb‘) as f: # f.write(res.content) #只有文字才有gbk,utf-8格式 #text得到的是文本之类的音乐视频如果用text则什么都输出不了,应用content
这是爬取固定歌手某一首歌,的第一面封装一下再找找页码规律从而可以爬取任意页,盲猜歌手名字改变不会影响什么(但是这样有bug,不能爬没版权的东西)代码只改了开始的开始的url部分
from bs4 import BeautifulSoup import requests from selenium import webdriver import urllib.request import pprint import json import re ‘‘‘ 没有版权下不了 先找mp3到的下载地址在根据xcode寻找到包含这个歌曲的那个歌单 然后在搜索页面(network第一个)ctrl+f搜索歌曲id ‘‘‘ def find_songid(singer_name,page): search_api = ‘http://music.taihe.com/search/song?s=1&key=‘+singer_name+‘&jump=0&start=‘+str((page-1)*20)+‘&size=20&third_type=0‘ # singer_name=input() # page_number=int(input()) # 这个网站这么好进一般没有反爬 header = { ‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36‘ , ‘Cookie‘: ‘E1RjBzZzY1cDRlTmRyWTFtMGN5b0pNM1VTcXQ3aVZTWnJ1fkk2aG94LWRiT1pkRVFBQUFBJCQAAAAAAAAAAAEAAAAOw~ynMTQ2MzUzNTMxNWZibAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ3fvl2d375da0; BAIDUID=10E17A0301BD00EC5B8D0E92CA54188F:FG=1; userid=2818360078; u_id=; u_t=; u_login=1; u_lo=0; BAIDU_SSP_lcr=https://my.oschina.net/zhmlvft/blog/472466?p={{totalPage}}; Hm_lvt_d0ad46e4afeacf34cd12de4c9b553aa6=1583374517,1583387044,1583387159,1583387225; tracesrc=-1%7C%7C-1; __qianqian_pop_tt=6; Hm_lpvt_d0ad46e4afeacf34cd12de4c9b553aa6=1583400033‘ , ‘Referer‘: ‘http://music.taihe.com/song/1137385?pst=sug‘} res = requests.get(search_api, params=singer_name, headers=header) # params可以直接自动识别并拼接关键词就不用我们自己拼了 # 得到一个响应 res.encoding = res.apparent_encoding # 自动获取编码形式,万能 html = res.text return html def find_song_info(id): url = ‘http://musicapi.taihe.com/v1/restserver/ting?method=baidu.ting.song.playAAC&format=jsonp&callback=jQuery17209677148092769645_1583387566116&songid=‘ + id + ‘&from=web&_=1583387569190‘ # 找同一歌手两首歌发现上面的url只有song_id改变了故可以猜测。。。 header = { ‘User-Agent‘: ‘Mozilla / 5.0(Windows NT 10.0;Win64;x64) AppleWebKit / 537.36(KHTML, likeGecko) Chrome / 80.0.3987.132Safari / 537.36‘ , ‘Cookie‘: ‘E1RjBzZzY1cDRlTmRyWTFtMGN5b0pNM1VTcXQ3aVZTWnJ1fkk2aG94LWRiT1pkRVFBQUFBJCQAAAAAAAAAAAEAAAAOw~ynMTQ2MzUzNTMxNWZibAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ3fvl2d375da0;BAIDUID = 10E17A0301BD00EC5B8D0E92CA54188F: FG = 1;userid = 2818360078;u_login = 1;BAIDU_SSP_lcr = https: // my.oschina.net / zhmlvft / blog / 472466?p = {{totalPage}}‘ , ‘Referer‘: ‘http: // music.taihe.com / song / 1332939‘ } # 现在只需要访问这个网址的showlink|filelink即可下载 这个这么难找的网址感觉一般都有反爬 # 可以先输出一下res(如果是200说明正常访问)看看返回在判断加不加header res = requests.get(url, headers=header) element = re.findall(r‘{.*}‘, res.text)[0] # 正则除去开头那些东西否则不会被识别为json文件 info = json.loads(element) # 要看一下文件时什么格式然后用相应的处理方式 song_download_api = info[‘bitrate‘][‘show_link‘] song_name = info[‘songinfo‘][‘title‘] return song_name,song_download_api def download(name,api): mp3=requests.get(api).content #print(mp3) with open(name+‘.mp3‘,‘wb‘) as f: f.write(mp3) print(name+‘ 下载完成 ‘) return if __name__==‘__main__‘: pages=int(input(‘要爬取前多少页‘)) singer_name = input(‘输入要爬的歌手名字‘) for page in range(1,pages+1): html=find_songid(singer_name,page) song_ids=re.findall(r‘"sid":(d+),"‘,html) print(song_ids) #这里直接在源码里面搜其中一个歌的id,不过要先筛选因为会找到很多包含这首歌id的语句 # 这样就能搜到其他歌了因为其他歌的id肯定也符合这个式子, #这个url获得是先播放这首歌在find xcode 可以找到一个得到ting文件这个文件里面有 for i in song_ids: song_name,song_download_api=find_song_info(i) download(song_name,song_download_api) # with open(‘隔空拥抱.mp3‘,‘wb‘) as f: # f.write(res.content) #只有文字才有gbk,utf-8格式 #text得到的是文本之类的音乐视频如果用text则什么都输出不了,应用content
2 酷我音乐:
思路:
1 下载一首歌 2 找到歌的id 3 找到所有歌的id 4 进入一首歌的页面 5 下载
6 改变歌手 7 改变页码
先放一首歌发现有一个url?文件进入发现里面就是歌曲的url即可下载url长这样
但是不知道为什么可以不用改动reqid坑我半天
http://www.kuwo.cn/urlformat=mp3&rid=76323299&response=url&type=convert_url3&br=128kmp3&from=web&t=1583462447941&reqId=e2c09e60-5f53-11ea-9a8c-a5d0d057abd1
多找几个能放的歌发现只有rid和reqId改变。这就可以合成歌曲下载地址
然后再搜索歌手,翻页(这里你会发现翻页上方的搜索码不会变化,应该被隐藏了?)可以发现出来一个song_list里面有所有歌的rid,name等data(翻页真时有惊喜)
然后因为不能直接从页面获得搜索url的变化规律所有点击搜索页面点击搜索来抓一个search?的包。可以发现里面的url只有rid和reqId变化,所以只用改rid即可进入单个歌曲的页面然后再根据上面的即可下载歌曲
盲猜改变歌手,页面 仍有用即可得到完整代码 初级版代码,不要管他
import requests import pprint import os import re import selenium from bs4 import BeautifulSoup ‘‘‘ 只能精确搜索(即你在网页上搜索出什么就是什么没有选择余地) ‘‘‘ def get_song_list(singer_name,name,page): #url=‘https://y.qq.com/portal/search.html#page=‘+str(page)+‘&searchid=1&remoteplace=txt.yqq.top&t=song&w=‘+singer_name url=‘http://www.kuwo.cn/api/www/search/searchMusicBykeyWord?key=‘+singer_name+name+‘&pn=‘+str(page)+‘&rn=30‘ header={‘Referer‘: ‘http://www.kuwo.cn/search/list?key=%E5%91%A8%E6%9D%B0%E4%BC%A6‘, ‘csrf‘: ‘7OUIGZGNE07‘, ‘user-agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36‘, ‘cookie‘:‘_ga=GA1.2.816678460.1583305531; _gid=GA1.2.1330734898.1583412010; Hm_lvt_cdb524f42f0ce19b169a8071123a4797=1583412949,1583413217,1583413235,1583413437; Hm_lpvt_cdb524f42f0ce19b169a8071123a4797=1583419987; kw_token=7OUIGZGNE07‘} res=requests.get(url,headers=header) res.encoding=res.apparent_encoding html=res.json() #regular=r"" #html=re.findall(regular,html) song_list=html[‘data‘][‘list‘] return song_list def down_load(song_name,song_api): html=requests.get(song_api).content with open(song_name+‘.mp3‘,‘wb‘) as f: f.write(html) print(song_name+‘ 下载完成‘) def get_song_api(song_name,rid): url=‘http://www.kuwo.cn/url?format=mp3&rid=‘+str(rid)+‘&response=url&type=convert_url3&br=128kmp3&from=web&t=1583424526196&reqId=97a1b160-5efb-11ea-8199-53e1afcdfde3‘ # 1 这里很奇怪reqID为什么可以不用管,直接删掉也行 不然我早就弄好了 # 2 不能直接进preview里然后用里面的url格式来套不然会403 header={‘Cookie‘:‘ga=GA1.2.816678460.1583305531; _gid=GA1.2.1330734898.1583412010; _gat=1; Hm_lvt_cdb524f42f0ce19b169a8071123a4797=1583412949,1583413217,1583413235,1583413437; Hm_lpvt_cdb524f42f0ce19b169a8071123a4797=1583413437; kw_token=3PV9YR4C19D‘, ‘csrf‘:‘3PV9YR4C19D‘, ‘Referer‘:‘http://www.kuwo.cn/play_detail/324244‘, ‘User-Agent‘:‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36‘ }#当前页面的标头 html=requests.get(url,headers=header).json() song_api=html[‘url‘] #print(song_api) #down_load(song_name,song_api) return if __name__==‘__main__‘: singer_name=input(‘ 输入歌手全名 ‘) name=input(‘ 输入歌曲名称 ‘) #pages=int(input(‘输入查看页数 最大10000(否则默认查看第一页)‘)) pages=2 for page in range(1,pages+1): song_list=get_song_list(singer_name,name,page) tot=1 for song in song_list: song_name=(song[‘name‘]) song_rid=song[‘rid‘] song_artist=song[‘artist‘] get_song_api(song_name,song_rid) print(tot,song_name, ‘歌手:‘,song_artist) tot+=1 download_song=input(‘输入要下载的编号 输入pass跳过这一页‘) if download_song==‘pass‘: pass else: download_song=int(download_song) song_name=song_list[download_song-1][‘name‘] song_rid=song_list[download_song-1][‘rid‘] song_artist=song_list[download_song-1][‘artist‘] #down_load(song_name,song_rid) print(song_name,song_artist) exit()
下面是改进后的代码成品
import requests
import pprint
import os
import re
import selenium
import urllib.request
from bs4 import BeautifulSoup
import time
‘‘‘
不能自动获取总页面数量
‘‘‘
def get_song_list(singer_name,name,page):
#url=‘https://y.qq.com/portal/search.html
url=‘http://www.kuwo.cn/api/www/search/searchMusicBykeyWord?key=‘+singer_name+name+‘&pn=‘+str(page)+‘&rn=30‘
header={‘Referer‘: ‘http://www.kuwo.cn/search/list?key=%E5%91%A8%E6%9D%B0%E4%BC%A6‘,
‘csrf‘: ‘7OUIGZGNE07‘,
‘user-agent‘: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36‘,
‘cookie‘:‘_ga=GA1.2.816678460.1583305531; _gid=GA1.2.1330734898.1583412010; Hm_lvt_cdb524f42f0ce19b169a8071123a4797=1583412949,1583413217,1583413235,1583413437; Hm_lpvt_cdb524f42f0ce19b169a8071123a4797=1583419987; kw_token=7OUIGZGNE07‘}
res=requests.get(url,headers=header)
res.encoding=res.apparent_encoding
html=res.json()
song_list=html[‘data‘][‘list‘]
return song_list
def down_load(song_name,song_api):
html=requests.get(song_api).content
with open(song_name+‘.mp3‘,‘wb‘) as f:
f.write(html)
print(song_name+‘ 下载完成‘)
time.sleep(1.5)
def get_song_api(song_name,rid):
url=‘http://www.kuwo.cn/url?format=mp3&rid=‘+str(rid)+‘&response=url&type=convert_url3&br=128kmp3&from=web&t=1583424526196‘
# 1 这里很奇怪reqID为什么可以不用管 不然我早就弄好了
# 2 不能直接进preview里然后用里面的url格式来套不然会403
header={‘Cookie‘:‘ga=GA1.2.816678460.1583305531; _gid=GA1.2.1330734898.1583412010; _gat=1; Hm_lvt_cdb524f42f0ce19b169a8071123a4797=1583412949,1583413217,1583413235,1583413437; Hm_lpvt_cdb524f42f0ce19b169a8071123a4797=1583413437; kw_token=3PV9YR4C19D‘,
‘csrf‘:‘3PV9YR4C19D‘,
‘Referer‘:‘http://www.kuwo.cn/play_detail/324244‘,
‘User-Agent‘:‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36‘
}#当前页面的标头
html=requests.get(url,headers=header).json()
song_api=html[‘url‘]
#print(song_api)
return song_api
def kuwo_spider():
print(‘-----------------introduction---------------‘)
print(‘因涉及到vip音乐下载请不要讨论版权问题 本程序音乐来源--酷我音乐‘)
print(‘输入歌手|歌曲名称可以查找,之后再输入编号即可下载‘)
print(‘flag输入为1代表当前页全部下载,否则正常输入编号下载‘)
print(‘暂不支持同时下载几首歌‘)
print(‘--------------------------------------------‘)
singer_name=input(‘ 输入歌手全名 ‘)
name=input(‘ 输入歌曲名称 ‘)
global flag
flag=input(‘输入flag ‘)
page=0
try:
while 1:
page+=1
song_list=get_song_list(singer_name,name,page)
tot=1
for song in song_list:
song_name=(song[‘name‘])
song_rid=song[‘rid‘]
song_artist=song[‘artist‘]
if flag !=‘1‘:
print(tot, song_name,‘--------歌手:‘,song_artist)
print()
song_api=get_song_api(song_name,song_rid)
if flag == ‘1‘:
down_load(song_name, song_api)
# 加了这句就是下载全部歌曲
tot+=1
if flag==‘1‘:
print(‘输入pass下载下一页 exit 退出‘)
download_song=input()
if download_song == ‘exit‘:
return
if download_song == ‘pass‘:
pass
else:
download_song=input(‘输入要下载的一首歌编号 输入pass加载一页 exit 退出 ‘)
if download_song==‘exit‘:
return
if download_song==‘pass‘:
pass
else:
download_song=int(download_song)
song_name=song_list[download_song-1][‘name‘]
song_rid=song_list[download_song-1][‘rid‘]
song_artist=song_list[download_song-1][‘artist‘]
print(song_name, song_artist,‘开始下载‘)
song_api=get_song_api(song_name,song_rid)
down_load(song_name,song_api)
return
except:
print(‘已经到最后一页‘)
if __name__==‘__main__‘:
kuwo_spider()
print(‘感谢使用‘)
print(‘源码请关注我的博客 https://misaka.design.blog/2020/03/06/%e7%88%ac%e5%8f%96-%e9%9f%b3%e4%b9%90%e6%ad%8c%e6%9b%b2/‘)
!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->!-->
以上是关于爬取 音乐歌曲(千千,酷我)的主要内容,如果未能解决你的问题,请参考以下文章
Python的requests爬取酷我音乐的一些坑(报错友好错误界面csrf动态网页)