下载网易云和酷我歌曲

  写这篇随笔时,代码已经写完好久了,最近一直在琢磨如何用pyinstaller打包,正好最近开始用博客园,现在才决定写一写(大佬不喜勿喷)

  这有个前身版本,我写在CSDN上了,可以去看看,是关于api分析的(只是最后学校开学就断更了,不知道以后有没有机会补上)

  好,现在可以进入正题了(●'◡'●)写了点注释供小白参考

  下载酷我音乐:

def kuwo(tempath):
    songid = re.findall(r'.*?play_detail/(\d*)', songurl)[0]
    audiolink = json.loads(
        requests.get(f'http://m.kuwo.cn/newh5app/api/mobile/v1/music/src/{songid}').text)['data']['url']
    audio = requests.get(audiolink, timeout=10).content
    # 获取信息
    res = requests.get(f'https://m.kuwo.cn/newh5/singles/songinfoandlrc?musicId={songid}').text
    text = json.loads(res)['data']['songinfo']
    name = text['songName']
    artists = text['artist'].replace('&', '、')
    album = text['album']
    lyric = ''
    for i in json.loads(res)['data']['lrclist']:
        lyric += '[{}:{}.{}]'.format('%02d' % math.floor(float(i['time']) / 60),
                                     '%02d' % math.floor(float(i['time']) % 60),
                                     ('%.2f' % math.modf(float(i['time']))[0])[2:])
        lyric += i['lineLyric'] + '\n'
    # 保存文件
    filename = re.sub(r"[\\/:*?\"<>|]", "", artists) + ' - ' + re.sub(r"[\\/:*?\"<>|]", "", name)
    with open(path + filename + '.aac', 'wb') as f1:
        f1.write(audio)
        f1.close()
    if len(lyric) != 0:
        with open(path + filename + '.lrc', 'w', encoding="UTF-8") as f2:
            f2.write(lyric)
            f2.close()
    strcmd = fr'"{tempath}\ffmpeg\bin\ffmpeg.exe" -i "{path + filename}.aac" -acodec libmp3lame "{path + filename}.mp3"'
    subprocess.call(strcmd, creationflags=0x08000000)
    os.remove(path + filename + '.aac')
    file = ID3(path + filename + '.mp3')
    file['TIT2'] = TIT2(encoding=3, text=name)
    file['TPE1'] = TPE1(encoding=3, text=artists)
    file['TALB'] = TALB(encoding=3, text=album)
    file.save()
    return f'《{name}》下载完成!'

  这当中要注意的是酷我音乐下下来的歌曲文件是aac格式,我调用了ffmpeg把格式转换成了mp3,然后才能调用mutagen库写入歌曲信息,所以运行时要确保ffmpeg在tempath下哦(没有ffmpeg的小朋友请戳这里,当然也可以自己去官网找最新版)。

  下载网易云音乐(无法试听的歌下不了):

def wangyi():
    songid = re.findall(r'.*?id=(\d*)', songurl)[0]
    audiolink = requests.get(f'http://music.163.com/song/media/outer/url?id={songid}.mp3',
                             headers={'user-agent': ''}).url
    if audiolink != 'https://music.163.com/404':
        audio = requests.get(audiolink).content
        # 获取信息
        res = requests.get(f'https://music.163.com/api/song/detail/?ids=%5B{songid}%5D').text
        text = json.loads(res)['songs'][0]
        name = text['name']
        album = text['album']['name']
        artists = []
        for artist in text['artists']:
            artists.append(artist['name'])
        artists = '、'.join(artists)
        lyric = ''
        lrctext = json.loads(requests.get(f'https://music.163.com/api/song/lyric?id={songid}&lv=1&tv=-1').text)
        if 'nolyric' not in lrctext:
            lrc = lrctext['lrc']['lyric']
            tlrc = lrctext['tlyric']['lyric'] + '\n'
            for m in re.compile(r'(\[\d*:\d*.\d*])(.*?)\n').findall(lrc + '\n'):
                lyric += m[0] + m[1] + ' '
                for n in re.compile(r'(\[\d*:\d*.\d*])(.*?)\n').findall(tlrc + '\n'):
                    if n[0] == m[0] and n[1] != m[1]:
                        lyric += n[1]
                lyric += '\n'
        # 保存文件
        filename = re.sub(r"[\\/:*?\"<>|]", "", artists) + ' - ' + re.sub(r"[\\/:*?\"<>|]", "", name)
        with open(path + filename + '.mp3', 'wb') as f1:
            f1.write(audio)
            f1.close()
        if len(lyric) != 0:
            with open(path + filename + '.lrc', 'w', encoding="UTF-8") as f2:
                f2.write(lyric)
                f2.close()
        file = ID3(path + filename + '.mp3')
        file['TIT2'] = TIT2(encoding=3, text=name)
        file['TPE1'] = TPE1(encoding=3, text=artists)
        file['TALB'] = TALB(encoding=3, text=album)
        file.save()
        return f'《{name}》下载完成!'
    else:
        return f'暂不支持下载'

  这里我干了一件有意思的事情,就是在处理歌词这一部分,如果有更好的匹配方法,欢迎留言哦。

  最后整理整理,完整代码差不多像这样:

main.py

import requests
import re
import json
from mutagen.id3 import ID3, TIT2, TPE1, TALB
import getpass
import math
import subprocess
import os
import shutil
import sys


def kuwo(tempath):
    ...


def wangyi():
    ...


if __name__ == '__main__':
    path = r'C:/Users/{}/Music/'.format(getpass.getuser())
    tpath = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__)))
    print('欢迎使用...')
    songurl = input('请输入:\n')
    while songurl != 'exit':
        if 'music.163.com' in songurl:
            print(wangyi())
        elif 'kuwo.cn' in songurl:
            print(kuwo(tpath))
        songurl = input('请输入:\n')
    shutil.rmtree(tpath)
    print('感谢使用(* ̄▽ ̄*)')

  顺带提一嘴如何使用pyinstaller打包软件,首先生成spec:

pyi-makespec -F -i {ico路径} -n {项目名} main.py

  -F是打包成单文件的意思(默认多文件),如果省略-n,第一个脚本的主文件名将作为spec的名字。

  然后找到生成的spec(我的在用户文件夹下)修改如下:

...
datas=[('C:\\Users...\\ffmpeg', 'ffmpeg')]
...

  第一个是资源文件夹的位置,第二个是生成临时目录的名称。如果和我不一样的注意上面的python代码不能照搬!

  最后生成exe:

pyinstaller -F {文件名.spec}

 

上一篇:深拷贝和浅拷贝的区别


下一篇:C++对象模型和this指针学习案例