Python requests 酷狗MP3/MP4下载助手
代码版
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
time:2018-12-2
title:酷狗mp3/1920*1080/1280*720/960*540/768*432MV下载
annotation:
author: pqx
email:[email protected]
"""
import time
import requests
import re
import hashlib
import json
import os
from requests.adapters import HTTPAdapter
def Create_folder(name):#创建文件夹
try:
if '{}'.format(name) not in os.listdir():#如果不存在
os.makedirs('{}'.format(name))#则创建
except:
return ''
def Cleantxt(title):#清洗标题中不能用于命名文件的字符
rstr = r"[\/\\\:\*\?\"\<\>\|]" # '/ \ : * ? " < > |'
title = re.sub(rstr, "_", title) # 替换为下划线
return title
headers = {'referer':'https://www.kugou.com/song/','User-Agent': 'Mozilla/5.0'}
def Get_one_page(url,headers=headers,code='utf-8'):#访问一个页面 返回页面信息
try:
s = requests.Session()#保持会话
s.mount('http://', HTTPAdapter(max_retries=3))#最大重试
s.mount('https://', HTTPAdapter(max_retries=3))
r=s.get(url,headers=headers,timeout=15)#超时设置
r.raise_for_status()#状态码 如果不是200则报错
r.encoding=code#r.apparent_encoding#字符类型
return r.text#返回页面
except Exception as e:
t=time.strftime('%Y/%m/%d %H:%M:%S %a')#时间格式化
with open(r'D:\kugou\Exception.txt','a+',encoding='utf-8') as f:
f.write('time:{}\n\nurl:{}\n\n{}\n\n'.format(t,url,e))
def Get_song_mv(x):#传入搜索关键词 返回MV 哈希值列表
url = "http://mvsearch.kugou.com/mv_search?&keyword={}&pagesize=50&page=1" .format(x)#mv搜索接口
# print('正在访问Mv搜索页面:{}'.format(url))
res = Get_one_page(url,headers={'User-Agent': 'Mozilla/5.0'})#调用get one page函数
msgs=re.findall(r'{("MixSongID".*?)}',res,re.S)#所有mv
LL=[]
for i in range(len(msgs)):
MvName=Cleantxt(re.findall(r'"FileName":"(.*?)"',msgs[i],re.S)[0])#单个Mv名字
print('{}>>> {}'.format(str(i+1),MvName))
MvHash=re.findall(r'"MvHash":"(.*?)"',msgs[i],re.S)[0]#单个哈希值
LL.append([MvName,MvHash])#所有 名字 哈希值形成列表
number = input("\n请输入要下载的歌曲序号(输入-1退出程序)(回车下载全部): ")
if number=='':
ll=LL
return ll#等于空返回列表所有
elif number == '-1':
ll=[]
exit()
return ll#等于-1返回空列表
else :
try:
ll=[LL[int(number)-1]]
return ll#等于*** 返回列表***对应值
except:
print('输入错误,请重新选择')
Get_song_mv(x) #非***重新输入
def Kugou_hash(mv_hash):#传入MV哈希值 返回KEY值
m = hashlib.md5()#哈希 md5加密
# song_hash_upper=mv_hash.upper()#大写
kugou_slat='kugoumvcloud'#盐
m.update((mv_hash+kugou_slat).encode("utf8"))#哈希值+盐
key = m.hexdigest()
return key#返回key值
def Mv_api(mv_hash,key):#访问单个MV页面 返回MV地址 画质
mv_api_url='http://trackermv.kugou.com/interface/index/cmd=100&hash={}&key={}&pid=6&ext=mp4&ismp3=0'.format(mv_hash,key)
# print('正在访问Mv_api页面:{}'.format(mv_api_url))
r= Get_one_page(mv_api_url)
# print(r.text)
rq=re.findall(r'"rq":{"hash":".*?mp4"}',r,re.S)#找1080
sq=re.findall(r'"sq":{"hash":".*?mp4"}',r,re.S)#找720
hd=re.findall(r'"hd":{"hash":".*?mp4"}',r,re.S)#找540
sd = re.findall(r'"sd":{"hash":".*?mp4"}', r, re.S)#找432
if rq!=[]:#如果有1080
mv_url_real = re.findall(r'"downurl":"(.*?)"}', rq[0], re.S)#1080MV真实地址
mv_url = mv_url_real[0].replace('\\', '')
image_quality='_1920_1080'
else:#没有1080
if sq!=[]:#如果有1280
mv_url_real = re.findall(r'"downurl":"(.*?)"}', sq[0], re.S)#720MV真实地址
mv_url = mv_url_real[0].replace('\\', '')
image_quality = '_1280_720'
else:#没有1280
if hd!=[]:#如果有540
mv_url_real = re.findall(r'"downurl":"(.*?)"}', hd[0], re.S)#540MV真实地址
mv_url = mv_url_real[0].replace('\\', '')
image_quality = '_960_540'
else:#没有540
mv_url_real = re.findall(r'"downurl":"(.*?)"}', sd[0], re.S)#432MV真实地址
mv_url = mv_url_real[0].replace('\\', '')
image_quality = '_768_432'
return mv_url,image_quality#返回真实MV地址,画质
def Mv_down(folder_name,mv_url,title,image_quality):#传入地址, 文件名 下载文件
try:
s = requests.Session()
s.mount('http://', HTTPAdapter(max_retries=3))
s.mount('https://', HTTPAdapter(max_retries=3))
mv = s.get(mv_url, headers=headers, timeout=15)
mv.raise_for_status() # 状态码 如果不是200则报错
# print('正在访问Mv真实页面:{}'.format(mv_url))
with open(folder_name +'\\'+ title + image_quality+".mp4", "wb")as fp:
fp.write(mv.content)
except Exception as e:
t = time.strftime('%Y/%m/%d %H:%M:%S %a') # 时间格式化
with open(r'D:\kugou\Exception.txt', 'a+',encoding='utf-8') as f:
f.write('time:{}\n\nurl:{}\n\n{}\n\n'.format(t, mv_url, e))
def Get_song_mp3(x,folder_name):#传入搜索关键词 文件夹名 下载
url = "https://songsearch.kugou.com/song_search_v2?callback=jQuery112406420117201202005_1543656827043&keyword={}&page=1&pagesize=50&userid=-1&clientver=&platform=WebFilter&tag=em&filter=2&iscorrection=1&privilege_filter=0&_=1543656827056" .format(x)
#mp3搜索接口
res = Get_one_page(url,headers={'User-Agent': 'Mozilla/5.0'})#调用get one page函数
js = json.loads(res[res.index('(') + 1:-2])#解析网页
data = js['data']['lists']#list 列表
for i in range(len(data)):
print(str(i + 1) + ".>>>" + str(data[i]['FileName']).replace('<em>', '').replace('</em>', ''))
number = input("\n请输入要下载的歌曲序号(输入-1退出程序)(回车下载全部): ")
if number=='':#等于''下载全部
song_list=re.findall(r'{"SongName":.*?"FileHash":"(.*?)".*?"FileName":"(.*?)".*?}',res,re.S)#所有哈希值 文件名
y=1
for i in song_list:
name=Cleantxt(i[1].replace('\\', '').replace('<em>', '').replace('</em>', ''))#名字
fhash = i[0]
print('正在下载:{},剩余:{}'.format(name, (len(song_list) - y)))
Downloud_song(folder_name,fhash, name)#调用下载
y+=1
print("歌曲已下载完成!")
elif number == '-1':
exit()
else:
try:
name = Cleantxt(str(data[int(number) - 1]['FileName']).replace('<em>', '').replace('</em>', ''))#单个文件
fhash = re.findall('"FileHash":"(.*?)"', res)[int(number) - 1]
Downloud_song(folder_name,fhash, name)
print("歌曲已下载完成!")
except:
print('')
print('输入错误,请重新选择')
print('')
Get_song_mp3(x,folder_name)
def Downloud_song(folder_name,fhash,name):#传入文件夹名 哈希值 标题
hash_url = "http://www.kugou.com/yy/index.php?r=play/getdata&hash=" + fhash
hash_content = Get_one_page(hash_url,headers={'User-Agent': 'Mozilla/5.0'})
play_url = ''.join(re.findall('"play_url":"(.*?)"', hash_content))#真实地址
if play_url!='':
real_download_url = play_url.replace("\\", "")
try:
s = requests.Session()
s.mount('http://', HTTPAdapter(max_retries=3))
s.mount('https://', HTTPAdapter(max_retries=3))
mp3=s.get(real_download_url,headers={'User-Agent': 'Mozilla/5.0'},timeout=15)#访问真实地址 下载歌曲
with open(folder_name +'\\'+ name + ".mp3", "wb")as fp:
fp.write(mp3.content)
except Exception as e:
t = time.strftime('%Y/%m/%d %H:%M:%S %a') # 时间格式化
with open(r'D:\kugou\Exception.txt', 'a+',encoding='utf-8') as f:
f.write('time:{}\n\nurl:{}\n\n{}\n\n'.format(t, name, e))
else:
print('未找到Mp3链接地址')
def Choice():#选择下载歌曲或者MV
y = input('输入***选择:1.>>搜索歌曲 mp3 2.>>搜索MV mp4 》》》')
if y == '2'or y=='1':
return y
else:
print('输入错误,重新输入')
main()
def main():
# x=Cleantxt('Taylor Swift - Style')#测试外文
# x=Cleantxt('Stellar - 찔려')#测试外文
# x=Cleantxt('花澤香菜 - 恋愛サーキュレーション')#测试外文
# x = Cleantxt("SING女团 - 寄明月") # 测试歌名
# x =Cleantxt('七朵组合')# 测试歌手
x = Cleantxt(input('输入歌手或歌名》》》'))#正式
folder_name=r'D:\kugou\%s'%x#文件名
Create_folder(folder_name)#创建文件夹
y=Choice()
if y=='1':#1调用get song mp3 函数
Get_song_mp3(x,folder_name)
elif y=='2':#等于2 调用 get song mv 函数
ll=Get_song_mv(x)#传入搜索值 返回列表
z=0
for i in ll:
title,mv_hash=i[0],i[1]#标题 ,哈希值
key=Kugou_hash(mv_hash)#传入哈希值 返回KEY值
mv_url,image_quality=Mv_api(mv_hash, key)#传入哈希值 key值 返回真实地址 画质
Mv_down(folder_name,mv_url, title,image_quality)#传入文件夹名 真实地址 标题 画质 下载MV
z+=1
print('{} 下载完成,剩余:{}'.format(title,(len(ll)-z)))
print('下载完成')
if __name__=='__main__':
main()
图片版