parser163 / app.py
admin
sync ms
06ea550
raw
history blame
5.43 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}")
try:
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}")
except Exception as e:
print(f"An error occurred while processing {file_path}: {e}")
def download_file(id, quality, url, title, artist, album, cache="./__pycache__"):
if os.path.exists(cache):
shutil.rmtree(cache)
os.makedirs(cache)
format = "mp3" if " MP3" in quality else "flac"
local_filename = f"{cache}/{id}.{format}"
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):
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"
}
try:
response = requests.get(
short_url,
headers=headers,
allow_redirects=True,
timeout=10,
)
return response.url
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
return None
def parse_id(url: str):
if not url:
return None
if url.isdigit():
return int(url)
url = extract_fst_url(url)
if not url:
return None
if url.startswith("http://163cn.tv/"):
url = get_real_url(url)
match = re.search(r"id=(\d+)", url)
if match:
return int(match.group(1))
else:
return None
def infer(url: str, level: str):
song_id = parse_id(url)
if not song_id or not level:
return (
None,
"Please input valid url or id and select a sound quality level!",
None,
None,
None,
None,
None,
None,
)
try:
response = requests.get(
os.getenv("api"),
params={"id": song_id, "type": "json", "level": level},
)
if response.status_code == 200:
data = response.json()["data"]
return (
download_file(
data["id"],
data["format"],
data["url"],
data["name"],
data["artist"],
data["album"],
),
data["name"],
data["pic"],
data["artist"],
data["album"],
data["format"],
data["size"],
data["lyric"],
)
except Exception as e:
return (
None,
f"{e}",
None,
None,
None,
None,
None,
None,
)
if __name__ == "__main__":
gr.Interface(
fn=infer,
inputs=[
gr.Textbox(
label="Please input music163 song ID or URL",
placeholder="https://music.163.com/#/song?id=",
),
gr.Dropdown(
choices=[
"standard",
"exhigh",
"lossless",
"hires",
"sky",
"jyeffect",
"jymaster",
],
value="lossless",
label="Sound Quality",
),
],
outputs=[
gr.Audio(label="Song", show_download_button=True),
gr.Textbox(label="Title", show_copy_button=True),
gr.Image(label="Cover", show_download_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", show_copy_button=True),
gr.TextArea(label="Lyrics", show_copy_button=True),
],
title="Parse Music163 Songs without Loss",
description="This site does not provide any audio and video storage services, but only to provide the most basic resolution services",
flagging_mode="never",
).launch()