127 lines
3.4 KiB
Python
127 lines
3.4 KiB
Python
import os
|
|
import json
|
|
import time
|
|
import requests
|
|
|
|
# 苹果CMS 采集接口地址(可替换为任意可用源)
|
|
API_BASE = "https://caiji.dyttzyapi.com/api.php/provide/vod"
|
|
|
|
# 本地缓存文件
|
|
CACHE_FILE = "cache.json"
|
|
CACHE_TTL = 60 * 30 # 30 分钟
|
|
|
|
|
|
def _fetch(params):
|
|
"""调用采集接口"""
|
|
try:
|
|
resp = requests.get(API_BASE, params=params, timeout=15)
|
|
resp.raise_for_status()
|
|
return resp.json()
|
|
except Exception as e:
|
|
print(f"[collector] 请求失败: {e}")
|
|
return {"list": []}
|
|
|
|
|
|
def fetch_categories():
|
|
"""获取分类列表"""
|
|
data = _fetch({"ac": "list"})
|
|
cats = data.get("class", []) or []
|
|
result = []
|
|
for c in cats:
|
|
result.append({"id": c.get("type_id"), "name": c.get("type_name")})
|
|
return result
|
|
|
|
|
|
def fetch_list(category_id=None, page=1, keyword=None):
|
|
"""获取影视列表"""
|
|
params = {"ac": "detail", "pg": page}
|
|
if category_id:
|
|
params["t"] = category_id
|
|
if keyword:
|
|
params["wd"] = keyword
|
|
data = _fetch(params)
|
|
return _normalize_list(data.get("list", []) or [])
|
|
|
|
|
|
def fetch_detail(vod_id):
|
|
"""获取影视详情"""
|
|
data = _fetch({"ac": "detail", "ids": vod_id})
|
|
items = data.get("list", []) or []
|
|
if not items:
|
|
return None
|
|
return _normalize_detail(items[0])
|
|
|
|
|
|
def _normalize_list(items):
|
|
out = []
|
|
for it in items:
|
|
out.append({
|
|
"vod_id": it.get("vod_id"),
|
|
"name": it.get("vod_name"),
|
|
"pic": it.get("vod_pic"),
|
|
"remarks": it.get("vod_remarks"),
|
|
"year": it.get("vod_year"),
|
|
"area": it.get("vod_area"),
|
|
"type_name": it.get("type_name"),
|
|
})
|
|
return out
|
|
|
|
|
|
def _normalize_detail(it):
|
|
play_from = (it.get("vod_play_from") or "").split("$$$")
|
|
play_url = (it.get("vod_play_url") or "").split("$$$")
|
|
episodes = []
|
|
for i, urls in enumerate(play_url):
|
|
source = play_from[i] if i < len(play_from) else f"线路{i+1}"
|
|
ep_list = []
|
|
for seg in urls.split("#"):
|
|
if "$" in seg:
|
|
title, url = seg.split("$", 1)
|
|
ep_list.append({"title": title, "url": url})
|
|
episodes.append({"source": source, "episodes": ep_list})
|
|
|
|
return {
|
|
"vod_id": it.get("vod_id"),
|
|
"name": it.get("vod_name"),
|
|
"pic": it.get("vod_pic"),
|
|
"content": it.get("vod_content"),
|
|
"year": it.get("vod_year"),
|
|
"area": it.get("vod_area"),
|
|
"type_name": it.get("type_name"),
|
|
"remarks": it.get("vod_remarks"),
|
|
"actors": it.get("vod_actor"),
|
|
"director": it.get("vod_director"),
|
|
"play_sources": episodes,
|
|
}
|
|
|
|
|
|
# ------- 本地缓存 -------
|
|
|
|
def _load_cache():
|
|
if not os.path.exists(CACHE_FILE):
|
|
return {}
|
|
try:
|
|
with open(CACHE_FILE, "r", encoding="utf-8") as f:
|
|
return json.load(f)
|
|
except Exception:
|
|
return {}
|
|
|
|
|
|
def _save_cache(data):
|
|
try:
|
|
with open(CACHE_FILE, "w", encoding="utf-8") as f:
|
|
json.dump(data, f, ensure_ascii=False)
|
|
except Exception as e:
|
|
print(f"[collector] 缓存写入失败: {e}")
|
|
|
|
|
|
def get_categories_cached():
|
|
cache = _load_cache()
|
|
now = time.time()
|
|
if "categories" in cache and now - cache["categories"].get("ts", 0) < CACHE_TTL:
|
|
return cache["categories"]["data"]
|
|
data = fetch_categories()
|
|
cache["categories"] = {"ts": now, "data": data}
|
|
_save_cache(cache)
|
|
return data
|