47 lines
1.4 KiB
Python
47 lines
1.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""Bilibili video fetcher — uses official web API."""
|
|
|
|
import re
|
|
import requests
|
|
from loguru import logger
|
|
from typing import Dict, Any
|
|
|
|
|
|
API_URL = "https://api.bilibili.com/x/web-interface/view"
|
|
HEADERS = {
|
|
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
|
|
}
|
|
|
|
|
|
async def fetch_bilibili(url_or_bv: str) -> Dict[str, Any]:
|
|
"""Fetch Bilibili video metadata via official API."""
|
|
logger.info(f"Fetching Bilibili: {url_or_bv}")
|
|
|
|
bv_id = url_or_bv
|
|
if "bilibili.com" in url_or_bv or "b23.tv" in url_or_bv:
|
|
match = re.search(r'BV\w+', url_or_bv)
|
|
if match:
|
|
bv_id = match.group()
|
|
else:
|
|
raise ValueError(f"Cannot extract BV ID from: {url_or_bv}")
|
|
|
|
resp = requests.get(API_URL, params={"bvid": bv_id}, headers=HEADERS, timeout=10)
|
|
resp.raise_for_status()
|
|
data = resp.json()
|
|
|
|
if data.get("code") != 0:
|
|
raise ValueError(f"Bilibili API error: {data.get('message')}")
|
|
|
|
video = data["data"]
|
|
return {
|
|
"title": video.get("title", ""),
|
|
"description": video.get("desc", ""),
|
|
"author": video.get("owner", {}).get("name", ""),
|
|
"url": f"https://www.bilibili.com/video/{bv_id}",
|
|
"cover": video.get("pic", ""),
|
|
"bvid": bv_id,
|
|
"duration": video.get("duration", 0),
|
|
"view_count": video.get("stat", {}).get("view", 0),
|
|
"platform": "bilibili",
|
|
}
|