Spaces:
Running
Running
import requests | |
import gradio as gr | |
from utils import ( | |
download_file, | |
extract_fst_url, | |
HEADER, | |
TIMEOUT, | |
API_BILI, | |
API_BILI_2, | |
API_BILI_1, | |
EN_US, | |
TMP_DIR, | |
) | |
ZH2EN = { | |
"状态栏": "Status", | |
"请输入B站视频链接": "Please input Bilibili video link", | |
"分P": "Part", | |
"视频标题": "Video title", | |
"视频封面": "Video cover", | |
"视频下载": "Download video", | |
"视频简介": "Video introduction", | |
"视频时长(s)": "Video duration(s)", | |
"UP主头像": "Uploader avatar", | |
"UP主昵称": "Uploader nickname", | |
"B站视频解析": "Bilibili video parser", | |
"通道": "Channel", | |
"接口1": "Interface 1", | |
"接口2": "Interface 2", | |
} | |
def _L(zh_txt: str): | |
return ZH2EN[zh_txt] if EN_US else zh_txt | |
def get_fst_url(text): | |
fst_url = extract_fst_url(text) | |
if fst_url: | |
out_url = fst_url.split("?")[0] | |
if out_url[-1] == "/": | |
out_url = out_url[:-1] | |
return out_url | |
else: | |
return f"https://www.bilibili.com/video/{text}" | |
def get_real_url(short_url): | |
return requests.get( | |
short_url, | |
headers=HEADER, | |
allow_redirects=True, | |
timeout=TIMEOUT, | |
).url.split("/?")[0] | |
def get_video(video_url: str, p: int, cache: str): | |
bvid = video_url.split("bilibili.com/video/")[-1] | |
response = requests.get( | |
API_BILI_2, | |
params={ | |
"bv": bvid, | |
"p": p, | |
"otype": "json", | |
}, | |
timeout=TIMEOUT, | |
) | |
response_json = response.json() | |
retcode = response_json["code"] | |
if retcode == 0: | |
qualities: list = response_json["accept_quality"] | |
quality = min(qualities[0], 80) | |
url = requests.get( | |
API_BILI_2, | |
params={ | |
"bv": bvid, | |
"p": p, | |
"q": quality, | |
"otype": "url", | |
}, | |
timeout=TIMEOUT, | |
).text | |
return download_file(url, bvid, cache) | |
else: | |
raise ConnectionError(f"Failed to get video: {retcode}") | |
def channel_2(video_url: str, p: int, cache: str): | |
response = requests.get( | |
API_BILI_1, | |
params={ | |
"url": video_url, | |
"type": "json", | |
}, | |
timeout=TIMEOUT, | |
) | |
response_json = response.json() | |
retcode = response_json["code"] | |
if retcode == 200: | |
title = response_json["title"] | |
cover = response_json["imgurl"] | |
desc = response_json["desc"] | |
response_data = response_json["data"][int(p) - 1] | |
dur = response_data["duration"] | |
author_data = response_json["user"] | |
author = author_data["name"] | |
avatar = author_data["user_img"] | |
video = get_video(video_url, p, cache) | |
return title, cover, video, desc, dur, avatar, author | |
else: | |
raise ConnectionError(f"接口调用失败, 错误码: {retcode}") | |
def channel_1(video_url: str, p: int, cache: str): | |
response = requests.get(API_BILI, params={"url": video_url}, timeout=TIMEOUT) | |
response_json = response.json() | |
retcode = response_json["code"] | |
if retcode == 1: | |
title = response_json["title"] | |
cover = response_json["imgurl"] | |
desc = response_json["desc"] | |
author_data = response_json["user"] | |
author = author_data["name"] | |
avatar = author_data["user_img"] | |
response_data = response_json["data"][int(p) - 1] | |
dur = response_data["duration"] | |
video_id = video_url.split("/")[-1] | |
video = download_file(response_data["video_url"], video_id, cache) | |
return title, cover, video, desc, dur, avatar, author | |
else: | |
raise ConnectionError(f"Failed to call API, error code: {retcode}") | |
# outer func | |
def infer(ch: str, video_url: str, p: int, cache=f"{TMP_DIR}/bili"): | |
status = "Success" | |
title = cover = desc = dur = video = author = avatar = None | |
if not ch: | |
ch == _L("接口1") | |
try: | |
if not video_url: | |
raise ValueError("视频链接为空!") | |
video_url = get_fst_url(video_url) | |
if "b23.tv" in video_url: | |
video_url = get_real_url(video_url) | |
title, cover, video, desc, dur, avatar, author = ( | |
channel_1(video_url, p, cache) | |
if ch == _L("接口1") | |
else channel_2(video_url, p, cache) | |
) | |
except Exception as e: | |
status = f"视频解析失败: {e}" | |
return status, title, cover, video, desc, dur, avatar, author | |
def bili_parser(): | |
return gr.Interface( | |
fn=infer, | |
inputs=[ | |
gr.Dropdown( | |
label=_L("通道"), | |
choices=[_L("接口1"), _L("接口2")], | |
value=_L("接口1"), | |
), | |
gr.Textbox( | |
label=_L("请输入B站视频链接"), | |
placeholder="https://www.bilibili.com/video/*", | |
), | |
gr.Slider(label=_L("分P"), minimum=1, maximum=1000, step=1, value=1), | |
], | |
outputs=[ | |
gr.Textbox(label=_L("状态栏"), show_copy_button=True), | |
gr.Textbox(label=_L("视频标题"), show_copy_button=True), | |
gr.Image(label=_L("视频封面"), show_share_button=False), | |
gr.Video( | |
label=_L("视频下载"), | |
show_download_button=True, | |
show_share_button=False, | |
format="mp4", | |
), | |
gr.TextArea(label=_L("视频简介"), show_copy_button=True), | |
gr.Textbox(label=_L("视频时长(s)"), show_copy_button=True), | |
gr.Image(label=_L("UP主头像"), show_share_button=False), | |
gr.Textbox(label=_L("UP主昵称"), show_copy_button=True), | |
], | |
title=_L("B站视频解析"), | |
flagging_mode="never", | |
examples=[ | |
[_L("接口1"), "BV1Dt4y1o7bU", 1], | |
[_L("接口1"), "https://b23.tv/LSoJzpW", 1], | |
[_L("接口2"), "https://www.bilibili.com/video/BV1G8iRYBE4f", 1], | |
[ | |
_L("接口2"), | |
"【『新年おめでとう | 2024』你就如同烟花一般,在我心中绽放!-哔哩哔哩】 https://b23.tv/LuTAbzj", | |
1, | |
], | |
], | |
cache_examples=False, | |
) | |