etl module added

This commit is contained in:
garaev kamil 2025-12-05 22:59:33 +03:00
parent 0f619dd954
commit ff36173720
16 changed files with 1573 additions and 0 deletions

View file

@ -0,0 +1,54 @@
import asyncio
from typing import Any, Dict, List, Optional
import httpx
from rate_limiter import JIKAN_RATE_LIMITER
BASE_URL = "https://api.jikan.moe/v4"
CLIENT = httpx.AsyncClient(timeout=15.0)
async def _get(path: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
"""
Обёртка над GET с ретраями и rate-limit'ом.
"""
url = f"{BASE_URL}{path}"
last_exc: Exception | None = None
for i in range(5):
await JIKAN_RATE_LIMITER.acquire()
try:
r = await CLIENT.get(url, params=params)
r.raise_for_status()
return r.json()
except Exception as exc:
last_exc = exc
await asyncio.sleep(1 * 2**i)
raise RuntimeError(f"Jikan unreachable: {last_exc!r}")
async def search_producer(name: str, limit: int = 1) -> List[Dict[str, Any]]:
"""
Поиск студии/продюсера по имени.
Возвращает список элементов из data[]:
[{ "mal_id": int, "name": str, ... }, ...]
"""
if not name:
return []
data = await _get("/producers", {"q": name, "limit": limit})
return data.get("data") or []
async def fetch_producer_full(mal_id: int) -> Optional[Dict[str, Any]]:
"""
Полная инфа по producer'у (есть поле about).
"""
if not isinstance(mal_id, int):
return None
data = await _get(f"/producers/{mal_id}/full")
return data.get("data") or None