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()


图片版
Python requests 酷狗MP3/MP4下载助手