跳转至

song

歌曲相关 API

query_song async

query_song(value: list[str] | list[int]) -> list[dict]

根据 id 或 mid 获取歌曲信息

PARAMETER DESCRIPTION
value

歌曲 id 或 mid 列表

TYPE: list[str] | list[int]

RETURNS DESCRIPTION
list[dict]

歌曲信息

Source code in qqmusic_api/song.py
async def query_song(value: list[str] | list[int]) -> list[dict]:
    """根据 id 或 mid 获取歌曲信息

    Args:
        value: 歌曲 id 或 mid 列表

    Returns:
        歌曲信息
    """
    if not value:
        return []

    param = {
        "types": [0 for _ in range(len(value))],
        "modify_stamp": [0 for _ in range(len(value))],
        "ctx": 0,
        "client": 1,
    }
    if isinstance(value[0], int):
        param["ids"] = value
    else:
        param["mids"] = value
    res = await Api(**API["query"]).update_params(**param).result
    return res["tracks"]

BaseSongFileType

BaseSongFileType(start_code: str, extension: str)

Bases: Enum

基础歌曲文件类型

Source code in qqmusic_api/song.py
def __init__(self, start_code: str, extension: str):
    self.__start_code = start_code
    self.__extension = extension

s property

s: str

歌曲文件类型

e property

e: str

歌曲文件扩展名

SongFileType

SongFileType(start_code: str, extension: str)

Bases: BaseSongFileType

歌曲文件类型

  • MASTER: 臻品母带2.0,24Bit 192kHz,size_new[0]
  • ATMOS_2: 臻品全景声2.0,16Bit 44.1kHz,size_new[1]
  • ATMOS_51: 臻品音质2.0,16Bit 44.1kHz,size_new[2]
  • FLAC: flac 格式,16Bit 44.1kHz~24Bit 48kHz,size_flac
  • OGG_640: ogg 格式,640kbps,size_new[5]
  • OGG_320: ogg 格式,320kbps,size_new[3]
  • OGG_192: ogg 格式,192kbps,size_192ogg
  • OGG_96: ogg 格式,96kbps,size_96ogg
  • MP3_320: mp3 格式,320kbps,size_320mp3
  • MP3_128: mp3 格式,128kbps,size_128mp3
  • ACC_192: m4a 格式,192kbps,size_192aac
  • ACC_96: m4a 格式,96kbps,size_96aac
  • ACC_48: m4a 格式,48kbps,size_48aac
Source code in qqmusic_api/song.py
def __init__(self, start_code: str, extension: str):
    self.__start_code = start_code
    self.__extension = extension

EncryptedSongFileType

EncryptedSongFileType(start_code: str, extension: str)

Bases: BaseSongFileType

加密歌曲文件类型

  • MASTER: 臻品母带2.0,24Bit 192kHz,size_new[0]
  • ATMOS_2: 臻品全景声2.0,16Bit 44.1kHz,size_new[1]
  • ATMOS_51: 臻品音质2.0,16Bit 44.1kHz,size_new[2]
  • FLAC: mflac 格式,16Bit 44.1kHz~24Bit 48kHz,size_flac
  • OGG_640: mgg 格式,640kbps,size_new[5]
  • OGG_320: mgg 格式,320kbps,size_new[3]
  • OGG_192: mgg 格式,192kbps,size_192ogg
  • OGG_96: mgg 格式,96kbps,size_96ogg
Source code in qqmusic_api/song.py
def __init__(self, start_code: str, extension: str):
    self.__start_code = start_code
    self.__extension = extension

get_song_urls async

get_song_urls(mid: list[str], file_type: SongFileType = MP3_128, credential: Credential | None = None) -> dict[str, str]
get_song_urls(mid: list[str], file_type: EncryptedSongFileType, credential: Credential | None = None) -> dict[str, tuple[str, str]]
get_song_urls(mid: list[str], file_type: EncryptedSongFileType | SongFileType = MP3_128, credential: Credential | None = None) -> dict[str, str] | dict[str, tuple[str, str]]

获取歌曲文件链接

Tips

ekey 用于解密加密歌曲

PARAMETER DESCRIPTION
mid

歌曲 mid

TYPE: list[str]

file_type

歌曲文件类型

TYPE: EncryptedSongFileType | SongFileType DEFAULT: MP3_128

credential

账号凭证

TYPE: Credential | None DEFAULT: None

RETURNS DESCRIPTION
SongFileType

{mid: url}

TYPE: dict[str, str] | dict[str, tuple[str, str]]

EncryptedSongFileType

{mid: (url, ekey)}

TYPE: dict[str, str] | dict[str, tuple[str, str]]

Source code in qqmusic_api/song.py
async def get_song_urls(
    mid: list[str],
    file_type: EncryptedSongFileType | SongFileType = SongFileType.MP3_128,
    credential: Credential | None = None,
) -> dict[str, str] | dict[str, tuple[str, str]]:
    """获取歌曲文件链接

    Tips:
        `ekey` 用于解密加密歌曲

    Args:
        mid:        歌曲 mid
        file_type:  歌曲文件类型
        credential: 账号凭证

    Returns:
        SongFileType: `{mid: url}`
        EncryptedSongFileType: `{mid: (url, ekey)}`
    """
    encrypted = isinstance(file_type, EncryptedSongFileType)
    # 分割 id,单次最大请求100
    mid_list = [mid[i : i + 100] for i in range(0, len(mid), 100)]
    # 选择文件域名
    domain = "https://isure.stream.qqmusic.qq.com/"
    api_data = API["play_url"] if not encrypted else API["evkey"]
    api = Api(**api_data, credential=credential or Credential())
    urls = {}

    async def get_song_url(mid):
        # 构造请求参数
        file_name = [f"{file_type.s}{_}{_}{file_type.e}" for _ in mid]
        param = {
            "filename": file_name,
            "guid": get_guid(),
            "songmid": mid,
            "songtype": [0 for _ in range(len(mid))],
        }

        res = await api.update_params(**param).result
        data = res["midurlinfo"]
        for info in data:
            song_url = domain + info["wifiurl"] if info["wifiurl"] else ""
            if not encrypted:
                urls[info["songmid"]] = song_url
            else:
                urls[info["songmid"]] = (song_url, info["ekey"])

    await asyncio.gather(*[asyncio.create_task(get_song_url(mid)) for mid in mid_list])
    return urls

get_try_url async

get_try_url(mid: str, vs: str) -> str

获取试听文件链接

Tips

使用 size_try 字段判断是否存在试听文件
参数 vs 请传入歌曲信息 vs 字段第一个

PARAMETER DESCRIPTION
mid

歌曲 mid

TYPE: str

vs

歌曲 vs

TYPE: str

RETURNS DESCRIPTION
str

试听文件链接

Source code in qqmusic_api/song.py
async def get_try_url(mid: str, vs: str) -> str:
    """获取试听文件链接

    Tips:
        使用 `size_try` 字段判断是否存在试听文件
        参数 `vs` 请传入歌曲信息 `vs` 字段第一个

    Args:
        mid: 歌曲 mid
        vs:  歌曲 vs

    Returns:
        试听文件链接
    """
    res = await (
        Api(**API["play_url"])
        .update_params(
            filename=[f"RS02{vs}.mp3"],
            guid=get_guid(),
            songmid=[mid],
            songtype=[1],
        )
        .result
    )
    if url := res["midurlinfo"][0]["wifiurl"]:
        return f"https://isure.stream.qqmusic.qq.com/{url}"
    return ""

Song

Song(*, mid: str | None = None, id: int | None = None)

歌曲类

ATTRIBUTE DESCRIPTION
mid

歌曲 mid

id

歌曲 id

初始化歌曲类

Note

歌曲 mid 和 id,两者至少提供一个

PARAMETER DESCRIPTION
mid

歌曲 mid

TYPE: str | None DEFAULT: None

id

歌曲 id

TYPE: int | None DEFAULT: None

Source code in qqmusic_api/song.py
def __init__(
    self,
    *,
    mid: str | None = None,
    id: int | None = None,
):
    """初始化歌曲类

    Note:
        歌曲 mid 和 id,两者至少提供一个

    Args:
        mid: 歌曲 mid
        id:  歌曲 id
    """
    if mid is None and id is None:
        raise ValueError("mid or id must be provided")
    self.mid = mid or ""
    self.id = id or 0
    self._info: dict | None = None

get_mid async

get_mid() -> str

获取歌曲 mid

RETURNS DESCRIPTION
str

歌曲 mid

Source code in qqmusic_api/song.py
async def get_mid(self) -> str:
    """获取歌曲 mid

    Returns:
        歌曲 mid
    """
    if not self.mid:
        if self.id:
            self.mid = (await query_song([self.id]))[0]["mid"]
    return self.mid

get_id async

get_id() -> int

获取歌曲 id

RETURNS DESCRIPTION
int

歌曲 id

Source code in qqmusic_api/song.py
async def get_id(self) -> int:
    """获取歌曲 id

    Returns:
        歌曲 id
    """
    if not self.id:
        if self.mid:
            self.id = (await query_song([self.mid]))[0]["id"]
    return self.id

get_info async

get_info() -> dict

获取歌曲信息

RETURNS DESCRIPTION
dict

歌曲信息

Source code in qqmusic_api/song.py
async def get_info(self) -> dict:
    """获取歌曲信息

    Returns:
        歌曲信息
    """
    if not self._info:
        if self.mid:
            self._info = (await query_song([self.mid]))[0]
        else:
            self._info = (await query_song([self.id]))[0]
    return self._info

get_detail async

get_detail() -> dict

获取歌曲详细信息

RETURNS DESCRIPTION
dict

详细信息

Source code in qqmusic_api/song.py
async def get_detail(self) -> dict:
    """获取歌曲详细信息

    Returns:
        详细信息
    """
    return await Api(**API["detail"]).update_params(song_mid=self.mid, song_id=self.id).result

get_similar_song async

get_similar_song() -> list[dict]

获取歌曲相似歌曲

RETURNS DESCRIPTION
list[dict]

歌曲信息

Source code in qqmusic_api/song.py
async def get_similar_song(self) -> list[dict]:
    """获取歌曲相似歌曲

    Returns:
        歌曲信息
    """
    return (await Api(**API["similar"]).update_params(songid=await self.get_id()).result)["vecSong"]

get_labels async

get_labels() -> list[dict]

获取歌曲标签

RETURNS DESCRIPTION
list[dict]

标签信息

Source code in qqmusic_api/song.py
async def get_labels(self) -> list[dict]:
    """获取歌曲标签

    Returns:
        标签信息
    """
    return (await Api(**API["labels"]).update_params(songid=await self.get_id()).result)["labels"]
get_related_songlist() -> list[dict]

获取歌曲相关歌单

RETURNS DESCRIPTION
list[dict]

歌单信息

Source code in qqmusic_api/song.py
async def get_related_songlist(self) -> list[dict]:
    """获取歌曲相关歌单

    Returns:
        歌单信息
    """
    return (await Api(**API["playlist"]).update_params(songid=await self.get_id()).result)["vecPlaylist"]
get_related_mv() -> list[dict]

获取歌曲相关MV

RETURNS DESCRIPTION
list[dict]

MV信息

Source code in qqmusic_api/song.py
async def get_related_mv(self) -> list[dict]:
    """获取歌曲相关MV

    Returns:
        MV信息
    """
    return (
        await Api(**API["mv"])
        .update_params(
            songid=str(await self.get_id()),
            songtype=1,
            lastmvid=0,
        )
        .result
    )["list"]

get_other_version async

get_other_version() -> list[dict]

获取歌曲其他版本

RETURNS DESCRIPTION
list[dict]

歌曲信息

Source code in qqmusic_api/song.py
async def get_other_version(self) -> list[dict]:
    """获取歌曲其他版本

    Returns:
        歌曲信息
    """
    return (await Api(**API["other"]).update_params(songid=self.id, songmid=self.mid).result)["versionList"]

get_sheet async

get_sheet() -> list[dict]

获取歌曲相关曲谱

RETURNS DESCRIPTION
list[dict]

曲谱信息

Source code in qqmusic_api/song.py
async def get_sheet(self) -> list[dict]:
    """获取歌曲相关曲谱

    Returns:
        曲谱信息
    """
    return (await Api(**API["sheet"]).update_params(songmid=await self.get_mid(), scoreType=-1).result)["result"]

get_producer async

get_producer() -> list[dict]

获取歌曲制作信息

RETURNS DESCRIPTION
list[dict]

人员信息

Source code in qqmusic_api/song.py
async def get_producer(self) -> list[dict]:
    """获取歌曲制作信息

    Returns:
        人员信息
    """
    return (await Api(**API["producer"]).update_params(songid=self.id, songmid=self.mid).result)["Lst"]

get_url async

get_url(file_type: SongFileType = MP3_128, credential: Credential | None = None) -> str
get_url(file_type: EncryptedSongFileType, credential: Credential | None = None) -> tuple[str, str]
get_url(file_type: SongFileType | EncryptedSongFileType = MP3_128, credential: Credential | None = None) -> str | tuple[str, str]

获取歌曲文件链接

Tips

ekey 用于解密加密歌曲

PARAMETER DESCRIPTION
file_type

歌曲文件类型

TYPE: SongFileType | EncryptedSongFileType DEFAULT: MP3_128

credential

账号凭证

TYPE: Credential | None DEFAULT: None

RETURNS DESCRIPTION
SongFileType

歌曲文件链接

TYPE: str | tuple[str, str]

EncryptedSongFileType

(加密文件链接, ekey)

TYPE: str | tuple[str, str]

Source code in qqmusic_api/song.py
async def get_url(
    self,
    file_type: SongFileType | EncryptedSongFileType = SongFileType.MP3_128,
    credential: Credential | None = None,
) -> str | tuple[str, str]:
    """获取歌曲文件链接

    Tips:
        `ekey` 用于解密加密歌曲

    Args:
        file_type:  歌曲文件类型
        credential: 账号凭证

    Returns:
        SongFileType: 歌曲文件链接
        EncryptedSongFileType: (加密文件链接, ekey)
    """
    return (await get_song_urls([await self.get_mid()], file_type, credential))[self.mid]

get_try_url async

get_try_url() -> str

获取试听文件链接

RETURNS DESCRIPTION
str

试听文件链接

Source code in qqmusic_api/song.py
async def get_try_url(self) -> str:
    """获取试听文件链接

    Returns:
        试听文件链接
    """
    vs = (await self.get_info())["vs"][0]
    if not vs:
        return ""
    return await get_try_url(self.mid, vs)