python下载9ku的音乐


python下载9ku的音乐

python版本: 3.8.1

事情源于一朋友给我发了一个Excel, 说让我把这几百首歌给他下载一下...

只得捡起了 python 写个脚本了

1. 歌曲格式(songList.py)

by the way, 好久不写python了, 至于为什么定义了这个格式, 而不是[[歌名, 歌手]]的格式, 因为这里不少重复的, 我这么些的话pycharm可以给我提示出重复的歌(其实Excel转代码的数据为了方便我使用 js 写的)

songList: Dict[Union[str, Any], Union[List[str], Any]] = {
    '是想你的声音啊----袁思睿': ['是想你的声音啊', '袁思睿'],
    '海底----虞姬、圈妹': ['海底', '虞姬、圈妹'],
    '犯错----顾峰': ['犯错', '顾峰'],
    '你到底爱谁----刘嘉亮': ['你到底爱谁', '刘嘉亮'],
    'Wonderful U(Demo)----AGA': ['Wonderful U(Demo)', 'AGA'],
    '只是太爱你----张敬轩': ['只是太爱你', '张敬轩'],
    '心要让你听见----邰正宵': ['心要让你听见', '邰正宵']
}

2. 主程序

看重点那几行代码就好了, 懒得总结了

import json
import os
from typing import Dict
import re
# Dict[Union[str, Any], Union[List[str], Any]]
from list import songList
from difflib import Differ, SequenceMatcher
import requests
from bs4 import BeautifulSoup
from time import time

diff = Differ()
# 定义几个常量
SONG_KEY = 'song'  # 歌名
ID_KEY = 'song_id'  # 歌曲id
SINGER_KEY = 'singer'  # 歌手


def check_if_song_exist(target_song_name: str, target_singer: str) -> str:
    """
    判断9ku是否存在这首歌
    :param target_song_name: 歌名
    :param target_singer: 歌手
    :return 歌曲id
    """
    # 请求歌曲信息
    url = f'http://baidu.9ku.com/suggestions/?kw={target_song_name}&_={int(round(time() * 1000))}'
    soup = BeautifulSoup(requests.get(url).text, 'html.parser')

    a_list = soup.select('a')

    # 最相似的检索结果
    most_similar_song_id = None
    # 最大相似度
    max_similarity = 0

    for a in a_list:
        try:
            # 检索到的歌名+歌手
            search_song = a.select_one('span.songName').get_text() + ' ' + a.select_one('span.singerName').get_text()[
                                                                           1:]
            # 检索到的链接
            search_href = a['href']
            # 匹配相似度
            similarity = SequenceMatcher(a=target_song_name + target_singer, b=search_song).quick_ratio()
            # 判断相似度
            if similarity > max_similarity:
                most_similar_song_id = re.findall(r'(\d{2,100})', search_href)[0]
                max_similarity = similarity
        except:
            pass
    return most_similar_song_id


def get_song_info_by_id(target_song_id: str) -> Dict[str, str]:
    """
    通过歌曲id获取歌曲信息
    :param target_song_id: 歌曲id
    """
    resp = requests.get(f'http://www.9ku.com/html/playjs/1001/{target_song_id}.js')
    return json.loads(resp.text[1:-1])


def download_music(target_song_id: str):
    """
    通过歌曲id获取歌曲mp3
    :param target_song_id: 歌曲id
    """
    song_info = get_song_info_by_id(target_song_id)
    url = song_info['wma']
    path = './music/' + song_info['mname'] + os.path.splitext(url)[-1]
    response = requests.get(url)
    music = response.content
    with open(path, 'ab') as file:  # 保存到本地的文件名
        file.write(music)
        file.flush()


if __name__ == '__main__':

    # 获取歌曲id
    for song in songList.values():
        # 1. 通过第一步检索判断是否存在这个歌曲
        song_id = check_if_song_exist(song[0], song[1])
        if song_id is not None:
            print('找到的歌: ', song_id)
            download_music(song_id)
        else:
            print('未找到的歌: ', {SONG_KEY: song[0], SINGER_KEY: song[1]})