qmusic_parser / app.py
admin
fix vip ret
17c780d
raw
history blame
4.75 kB
import os
import re
import shutil
import requests
import gradio as gr
from mutagen.mp3 import MP3
from mutagen.flac import FLAC
from mutagen.id3 import TIT2, TPE1, TALB
def insert_metadata(file_path: str, title, artist, album):
print(f"The file was successfully downloaded and saved to {file_path}")
if file_path.endswith(".flac"):
audio = FLAC(file_path)
audio["TITLE"] = title
audio["ARTIST"] = artist
audio["ALBUM"] = album
else:
audio = MP3(file_path)
try:
audio.add_tags()
except Exception as e:
print(e)
audio.tags.add(TIT2(encoding=3, text=title))
audio.tags.add(TPE1(encoding=3, text=artist))
audio.tags.add(TALB(encoding=3, text=album))
audio.save()
print(f"Metadata was successfully inserted into {file_path}")
def download_file(mid: str, url: str, title, artist, album, cache="./__pycache__"):
if os.path.exists(cache):
shutil.rmtree(cache)
os.makedirs(cache)
local_filename = f"{cache}/{mid}.mp3"
response = requests.get(url, stream=True)
if response.status_code == 200:
with open(local_filename, "wb") as file:
for chunk in response.iter_content(chunk_size=8192):
file.write(chunk)
insert_metadata(local_filename, title, artist, album)
return local_filename
else:
print(f"Download Failure, status code: {response.status_code}")
return url
def extract_fst_url(text):
url_pattern = r'(https?://[^\s"]+)'
match = re.search(url_pattern, text)
if match:
return match.group(1)
else:
return None
def get_real_url(short_url):
return requests.get(
short_url,
headers={
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36"
},
allow_redirects=True,
timeout=10,
).url
def parse_id(url: str):
if not url:
return None
if re.fullmatch(r"^[A-Za-z0-9]{14}$", url):
return str(url)
url = extract_fst_url(url)
if not url:
return None
if url.startswith("https://c6.y.qq.com/base/fcgi-bin/"):
return get_real_url(url).split("songmid=")[1].split("&")[0]
match = re.search(r"songDetail/([^?]+)", url)
if match:
return str(match.group(1))
else:
return None
def infer(url: str):
song = title = song_id = artist = album = quality = size = None
try:
song_mid = parse_id(url)
if not song_mid:
title = "Please enter a valid URL or mid!"
return song, title, song_id, artist, album, quality, size
response = requests.get(
os.getenv("api"),
params={"mid": song_mid},
)
if response.status_code == 200 and response.json()["code"] == 200:
data = response.json()["data"]
song = download_file(
data["mid"],
data["urls"][0]["url"],
data["title"],
data["author"],
data["album"],
)
title = data["title"]
song_id = data["id"]
artist = data["author"]
album = data["album"]
quality = data["urls"][0]["type"]
size = data["urls"][0]["size"]
else:
raise Exception(response.json()["msg"])
except Exception as e:
title = f"{e}"
return song, title, song_id, artist, album, quality, size
if __name__ == "__main__":
gr.Interface(
fn=infer,
inputs=[
gr.Textbox(
label="Please enter the mid or URL of QQ music song",
placeholder="https://y.qq.com/n/ryqq/songDetail/*",
),
],
outputs=[
gr.Audio(label="Song download", show_download_button=True),
gr.Textbox(label="Title", show_copy_button=True),
gr.Textbox(label="Song ID", show_copy_button=True),
gr.Textbox(label="Artist", show_copy_button=True),
gr.Textbox(label="Album", show_copy_button=True),
gr.Textbox(label="Quality", show_copy_button=True),
gr.Textbox(label="Size(B)", show_copy_button=True),
],
title="QQ Music Parser",
description="This site does not provide any audio storage services, only provide the most basic parsing services",
flagging_mode="never",
examples=[
"003N68WJ0mh5jN",
"https://y.qq.com/n/ryqq/songDetail/003N68WJ0mh5jN",
"https://c6.y.qq.com/base/fcgi-bin/u?__=VfAFlMiujMhz",
],
cache_examples=False,
).launch()