416 lines
13 KiB
Python
416 lines
13 KiB
Python
|
from fastapi import FastAPI # 导入FastAPI
|
||
|
import uvicorn # uvicorn:主要用于加载和提供应用程序的服务器
|
||
|
import requests
|
||
|
import json
|
||
|
import os
|
||
|
|
||
|
env = os.environ
|
||
|
headers = {
|
||
|
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
|
||
|
'Host': 'www.kuwo.cn',
|
||
|
'referer': 'https://www.kuwo.cn/',
|
||
|
'user-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
|
||
|
'Chrome/103.0.5060.114 Safari/537.36 Edg/103.0.1264.49'
|
||
|
}
|
||
|
|
||
|
# 创建一个app实例
|
||
|
app = FastAPI() if env.get("docs") is not None and env.get("docs").lower() == "true" else FastAPI(openapi_url=None)
|
||
|
|
||
|
|
||
|
# 获取酷我cookie
|
||
|
url = 'https://www.kuwo.cn/'
|
||
|
r = requests.get(url, headers=headers)
|
||
|
cookies = r.cookies.get('kw_token')
|
||
|
csrf = cookies
|
||
|
headers['csrf'] = csrf
|
||
|
headers['Cookie'] = r.headers['Set-Cookie']
|
||
|
|
||
|
|
||
|
# 专辑相关
|
||
|
# 专辑信息
|
||
|
@app.get("/albumInfo")
|
||
|
async def album_info(albumId: int = None, page: int = 1, size: int = 20):
|
||
|
if albumId is None:
|
||
|
info = {
|
||
|
"code": 403,
|
||
|
"msg": "Invalid Request"
|
||
|
}
|
||
|
return info
|
||
|
url = f'http://www.kuwo.cn/api/www/album/albumInfo?albumId={albumId}&pn={page}' \
|
||
|
f'&rn={size}&httpsStatus=1'
|
||
|
r = requests.get(url, headers=headers)
|
||
|
data = json.loads(r.text)["data"]
|
||
|
songList = data["musicList"]
|
||
|
info = {
|
||
|
"code": 200,
|
||
|
"msg": "success",
|
||
|
"total": data["total"],
|
||
|
"albumid": data["albumid"],
|
||
|
"name": data["album"],
|
||
|
"artistid": data["artistid"],
|
||
|
"artist": data["artist"],
|
||
|
"releaseDate": data["releaseDate"],
|
||
|
"lang": data["lang"],
|
||
|
"pic": data["pic"].replace("/300/", "/480/"),
|
||
|
"albuminfo": data["albuminfo"],
|
||
|
"data": [{
|
||
|
"rid": song["rid"],
|
||
|
"name": song["name"],
|
||
|
"artistid": song["artistid"],
|
||
|
"artist": song["artist"],
|
||
|
"albumid": song["albumid"],
|
||
|
"album": song["album"],
|
||
|
"pic": song["pic"],
|
||
|
"duration": song["duration"],
|
||
|
"songTime": song["songTimeMinutes"]
|
||
|
} for song in songList]
|
||
|
}
|
||
|
return info
|
||
|
|
||
|
|
||
|
# 歌手相关
|
||
|
# 歌手专辑
|
||
|
@app.get("/artistAlbum")
|
||
|
async def artistAlbum(artistid: int = None, page: int = 1, size: int = 20):
|
||
|
if artistid is None:
|
||
|
info = {
|
||
|
"code": 403,
|
||
|
"msg": "Invalid Request"
|
||
|
}
|
||
|
return info
|
||
|
url = f'http://www.kuwo.cn/api/www/artist/artistAlbum?artistid={artistid}&pn={page}' \
|
||
|
f'&rn={size}&httpsStatus=1'
|
||
|
r = requests.get(url, headers=headers)
|
||
|
data = json.loads(r.text)['data']
|
||
|
total = int(data["total"])
|
||
|
albumList = data["albumList"]
|
||
|
info = {
|
||
|
"code": 200,
|
||
|
"msg": "success",
|
||
|
"total": total,
|
||
|
"albumList": [{
|
||
|
"albumid": album["albumid"],
|
||
|
"name": album["album"],
|
||
|
"artistid": album["artistid"],
|
||
|
"artist": album["artist"],
|
||
|
"releaseDate": album["releaseDate"],
|
||
|
"pic": album["pic"].replace("/300/", "/480/"),
|
||
|
"lang": album["lang"],
|
||
|
"albuminfo": album["albuminfo"]
|
||
|
} for album in albumList]
|
||
|
}
|
||
|
return info
|
||
|
|
||
|
|
||
|
# 歌手信息
|
||
|
@app.get("/artist")
|
||
|
async def artist(artistid: int = None):
|
||
|
if artistid is None:
|
||
|
info = {
|
||
|
"code": 403,
|
||
|
"msg": "Invalid Request"
|
||
|
}
|
||
|
return info
|
||
|
url = f"https://www.kuwo.cn/api/www/artist/artist?artistid={artistid}&httpsStatus=1"
|
||
|
r = requests.get(url, headers=headers)
|
||
|
if r.headers.get('Set-Cookie') is not None:
|
||
|
headers['Cookie'] = r.headers['Set-Cookie']
|
||
|
headers['csrf'] = r.headers['Set-Cookie'].split("; ")[0].replace("kw_token=", "")
|
||
|
result = json.loads(r.text.replace(' ', ' '))["data"]
|
||
|
info = {
|
||
|
"code": 200,
|
||
|
"msg": "success",
|
||
|
"data": {
|
||
|
"artistid": result["id"],
|
||
|
"name": result["name"],
|
||
|
"albumNum": result["albumNum"],
|
||
|
"musicNum": result["musicNum"],
|
||
|
"mvNum": result["mvNum"],
|
||
|
"artistFans": result["artistFans"],
|
||
|
"pic": result["pic"].replace("/120/", "/480/"),
|
||
|
"gener": result["gener"],
|
||
|
"country": result["country"],
|
||
|
"constellation": result["constellation"],
|
||
|
"birthday": result["birthday"],
|
||
|
"birthplace": result["birthplace"],
|
||
|
"language": result["language"],
|
||
|
"height": result["tall"],
|
||
|
"weight": result["weight"],
|
||
|
"info": result["info"]
|
||
|
}
|
||
|
}
|
||
|
return info
|
||
|
|
||
|
|
||
|
# 歌手音乐
|
||
|
@app.get("/artistMusic")
|
||
|
async def artistMusic(artistid: int = None, page: int = 1, size: int = 20):
|
||
|
if artistid is None:
|
||
|
info = {
|
||
|
"code": 403,
|
||
|
"msg": "Invalid Request"
|
||
|
}
|
||
|
return info
|
||
|
url = f"https://www.kuwo.cn/api/www/artist/artistMusic?artistid={artistid}&pn={page}&rn={size}"
|
||
|
r = requests.get(url, headers=headers)
|
||
|
if r.headers.get('Set-Cookie') is not None:
|
||
|
headers['Cookie'] = r.headers['Set-Cookie']
|
||
|
headers['csrf'] = r.headers['Set-Cookie'].split("; ")[0].replace("kw_token=", "")
|
||
|
js = json.loads(r.text)
|
||
|
result = js["data"]["list"]
|
||
|
total = js["data"]["total"]
|
||
|
songinfos = []
|
||
|
for i in result:
|
||
|
songinfos.append({
|
||
|
'rid': i['rid'],
|
||
|
'name': i['name'].replace(' ', ' '),
|
||
|
'artistid': i['artistid'],
|
||
|
'artists': i['artist'].replace(' ', ' '),
|
||
|
'albumid': i['albumid'],
|
||
|
'album': i['album'].replace(' ', ' '),
|
||
|
'pic': i['pic'].replace('/120/', '/480/'),
|
||
|
'duration': i['duration'],
|
||
|
"songTime": i["songTimeMinutes"]
|
||
|
})
|
||
|
info = {
|
||
|
"code": 200,
|
||
|
"msg": "success",
|
||
|
"total": total,
|
||
|
"data": songinfos
|
||
|
}
|
||
|
return info
|
||
|
|
||
|
|
||
|
# 歌手排行榜
|
||
|
@app.get("/artistRank")
|
||
|
async def artistRank(type: str = "all", page: int = 1, size: int = 20, prefix: str = None):
|
||
|
keyWorkMap = {
|
||
|
"all": "0",
|
||
|
"cnMale": "1",
|
||
|
"cnFemale": "2",
|
||
|
"cnTeam": "3",
|
||
|
"jkMale": "4",
|
||
|
"jkFemale": "5",
|
||
|
"jkTeam": "6",
|
||
|
"eaMale": "7",
|
||
|
"eaFemale": "8",
|
||
|
"eaTeam": "9",
|
||
|
"other": "10"
|
||
|
}
|
||
|
if type not in keyWorkMap.keys():
|
||
|
info = {
|
||
|
"code": 404,
|
||
|
"msg": "Invalid Rank"
|
||
|
}
|
||
|
return info
|
||
|
url = f"https://www.kuwo.cn/api/www/artist/artistInfo?category={keyWorkMap[type]}" \
|
||
|
f"&pn={page}&rn={size}&httpsStatus=1"
|
||
|
url = url + f"&prefix={prefix}" if prefix is not None else url
|
||
|
r = requests.get(url, headers=headers)
|
||
|
if r.headers.get('Set-Cookie') is not None:
|
||
|
headers['Cookie'] = r.headers['Set-Cookie']
|
||
|
headers['csrf'] = r.headers['Set-Cookie'].split("; ")[0].replace("kw_token=", "")
|
||
|
js = json.loads(r.text)
|
||
|
artistList = js["data"]["artistList"]
|
||
|
total = int(js["data"]["total"])
|
||
|
info = {
|
||
|
"code": 200,
|
||
|
"msg": "success",
|
||
|
"total": total,
|
||
|
"data": [{
|
||
|
"artistid": result["id"],
|
||
|
"name": result["name"],
|
||
|
"albumNum": result["albumNum"],
|
||
|
"musicNum": result["musicNum"],
|
||
|
"mvNum": result["mvNum"],
|
||
|
"artistFans": result["artistFans"],
|
||
|
"pic": result["pic"].replace("/300/", "/480/"),
|
||
|
} for result in artistList]
|
||
|
}
|
||
|
return info
|
||
|
|
||
|
|
||
|
# 搜索
|
||
|
@app.get("/search")
|
||
|
async def search(key: str = None, page: int = 1, size: int = 20):
|
||
|
if key is None:
|
||
|
info = {
|
||
|
"code": 403,
|
||
|
"msg": "Invalid Request"
|
||
|
}
|
||
|
return info
|
||
|
url = f'https://www.kuwo.cn/api/www/search/searchMusicBykeyWord?key={key}&pn={page}&rn={size}'
|
||
|
r = requests.get(url, headers=headers)
|
||
|
if r.headers.get('Set-Cookie') is not None:
|
||
|
headers['Cookie'] = r.headers['Set-Cookie']
|
||
|
headers['csrf'] = r.headers['Set-Cookie'].split("; ")[0].replace("kw_token=", "")
|
||
|
js = json.loads(r.text)
|
||
|
result = js['data']['list']
|
||
|
total = int(js['data']['total'])
|
||
|
songinfos = []
|
||
|
for i in result:
|
||
|
songinfos.append({
|
||
|
'rid': i['rid'],
|
||
|
'name': i['name'].replace(' ', ' '),
|
||
|
'artistid': i['artistid'],
|
||
|
'artists': i['artist'].replace(' ', ' '),
|
||
|
'albumid': i['albumid'],
|
||
|
'album': i['album'].replace(' ', ' '),
|
||
|
'pic': i['pic'].replace('/120/', '/480/'),
|
||
|
'duration': i['duration'],
|
||
|
'songTime': i['songTimeMinutes']
|
||
|
})
|
||
|
info = {
|
||
|
"code": 200,
|
||
|
"msg": "success",
|
||
|
"total": total,
|
||
|
"data": songinfos
|
||
|
}
|
||
|
return info
|
||
|
|
||
|
|
||
|
# 歌曲相关
|
||
|
# 下载链接
|
||
|
@app.get("/link")
|
||
|
async def link(rid: int = None):
|
||
|
if rid is None:
|
||
|
info = {
|
||
|
"code": 403,
|
||
|
"msg": "Invalid Request"
|
||
|
}
|
||
|
return info
|
||
|
url = f'http://www.kuwo.cn/api/v1/www/music/playUrl?mid={rid}&type=convert_url3&br=320kmp3'
|
||
|
r = requests.get(url, headers=headers)
|
||
|
result = json.loads(r.text)["data"]["url"]
|
||
|
info = {
|
||
|
"code": 200,
|
||
|
"msg": "success",
|
||
|
"data": {
|
||
|
"LQ": result
|
||
|
}
|
||
|
}
|
||
|
return info
|
||
|
|
||
|
|
||
|
# 歌词
|
||
|
@app.get("/lyric")
|
||
|
async def lyric(rid: int = None):
|
||
|
if rid is None:
|
||
|
info = {
|
||
|
"code": 403,
|
||
|
"msg": "Invalid Request"
|
||
|
}
|
||
|
return info
|
||
|
url = f'http://kuwo.cn/newh5/singles/songinfoandlrc?musicId={rid}'
|
||
|
r = requests.get(url, headers=headers)
|
||
|
data = json.loads(r.text)['data']['lrclist']
|
||
|
info = {
|
||
|
"code": 200,
|
||
|
"msg": "success",
|
||
|
"data": data
|
||
|
}
|
||
|
return info
|
||
|
|
||
|
|
||
|
# 歌曲排行榜
|
||
|
@app.get("/songRank")
|
||
|
async def songRank(type: str = None, page: int = 1, size: int = 20):
|
||
|
keyWorkMap = {
|
||
|
"hot": "16",
|
||
|
"new": "17",
|
||
|
"classic": "26",
|
||
|
}
|
||
|
if type not in keyWorkMap.keys():
|
||
|
info = {
|
||
|
"code": 404,
|
||
|
"msg": "Invalid Rank"
|
||
|
}
|
||
|
return info
|
||
|
url = f"https://www.kuwo.cn/api/www/bang/bang/musicList?bangId={keyWorkMap[type]}&pn={page}" \
|
||
|
f"&rn={size}&httpsStatus=1"
|
||
|
r = requests.get(url, headers=headers)
|
||
|
if r.headers.get('Set-Cookie') is not None:
|
||
|
headers['Cookie'] = r.headers['Set-Cookie']
|
||
|
headers['csrf'] = r.headers['Set-Cookie'].split("; ")[0].replace("kw_token=", "")
|
||
|
js = json.loads(r.text)
|
||
|
result = js["data"]["musicList"]
|
||
|
total = int(js["data"]["num"])
|
||
|
info = {
|
||
|
"code": 200,
|
||
|
"msg": "success",
|
||
|
"total": total,
|
||
|
"data": [{"rid": i["rid"], "name": i["name"], "artistid": i["artistid"],
|
||
|
"artist": i["artist"], "albumid": i["albumid"], "album": i["album"],
|
||
|
"pic": i["pic"], "duration": i["duration"], "songTime": i["songTimeMinutes"]} for i in result]}
|
||
|
return info
|
||
|
|
||
|
|
||
|
# 歌曲信息
|
||
|
@app.get("/songInfo")
|
||
|
async def songInfo(rid: int = None):
|
||
|
if rid is None:
|
||
|
info = {
|
||
|
"code": 403,
|
||
|
"msg": "Invalid Request"
|
||
|
}
|
||
|
return info
|
||
|
url = f'http://kuwo.cn/newh5/singles/songinfoandlrc?musicId={rid}'
|
||
|
r = requests.get(url, headers=headers)
|
||
|
data = json.loads(r.text)['data']['songinfo']
|
||
|
info = {
|
||
|
"code": 200,
|
||
|
"msg": "success",
|
||
|
"data": {
|
||
|
"rid": rid,
|
||
|
"name": data["songName"],
|
||
|
"artistid": int(data["artistId"]),
|
||
|
"artist": data["artist"],
|
||
|
"albumid": int(data["albumId"]),
|
||
|
"album": data["album"],
|
||
|
"pic": data["pic"].replace("/240/", "/480/")
|
||
|
.replace("kwcdn.kuwo.cn", "kuwo.cn").replace("http://", "https://"),
|
||
|
"duration": int(data["duration"]),
|
||
|
"songTime": data["songTimeMinutes"]
|
||
|
}
|
||
|
}
|
||
|
return info
|
||
|
|
||
|
|
||
|
# 歌曲信息以及歌词
|
||
|
@app.get("/songInfoAndLyric")
|
||
|
async def songInfoAndLyric(rid: int = None):
|
||
|
if rid is None:
|
||
|
info = {
|
||
|
"code": 403,
|
||
|
"msg": "Invalid Request"
|
||
|
}
|
||
|
return info
|
||
|
url = f'http://kuwo.cn/newh5/singles/songinfoandlrc?musicId={rid}'
|
||
|
r = requests.get(url, headers=headers)
|
||
|
result = json.loads(r.text)
|
||
|
lyric = result['data']['lrclist']
|
||
|
data = result['data']['songinfo']
|
||
|
info = {
|
||
|
"code": 200,
|
||
|
"msg": "success",
|
||
|
"songInfo": {
|
||
|
"rid": rid,
|
||
|
"name": data["songName"],
|
||
|
"artistid": int(data["artistId"]),
|
||
|
"artist": data["artist"],
|
||
|
"albumid": int(data["albumId"]),
|
||
|
"album": data["album"],
|
||
|
"pic": data["pic"].replace("/240/", "/480/"),
|
||
|
"duration": int(data["duration"]),
|
||
|
"songTime": data["songTimeMinutes"]
|
||
|
},
|
||
|
"lyric": lyric
|
||
|
}
|
||
|
return info
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
host = env.get("host") if env.get("host") is not None else "0.0.0.0"
|
||
|
port = int(env.get("port")) if env.get("port") is not None else 8000
|
||
|
uvicorn.run(app='main:app', host=host, port=port)
|