Spaces:
Running
Running
Fix: thumbnail APIs - /api/article + /api/proxy/xlb
Browse files
main.py
CHANGED
|
@@ -779,9 +779,63 @@ def api_categories():
|
|
| 779 |
for k,(u,n) in VNE_CATS.items(): cats.append({"id":k,"name":n,"source":"vne"})
|
| 780 |
return JSONResponse(cats)
|
| 781 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 782 |
@app.get("/api/article")
|
| 783 |
def api_article(url:str=Query(...)):
|
| 784 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 785 |
|
| 786 |
@app.get("/api/storage_status")
|
| 787 |
def api_storage_status():
|
|
|
|
| 779 |
for k,(u,n) in VNE_CATS.items(): cats.append({"id":k,"name":n,"source":"vne"})
|
| 780 |
return JSONResponse(cats)
|
| 781 |
|
| 782 |
+
|
| 783 |
+
@app.get("/api/proxy/xlb")
|
| 784 |
+
def api_xlb(path: str = Query(default="", description="Path after xemlaibongda.top"), limit: int = Query(default=20)):
|
| 785 |
+
try:
|
| 786 |
+
url = f"https://xemlaibongda.top/{path}" if path else "https://xemlaibongda.top/"
|
| 787 |
+
r = requests.get(url, headers=HEADERS, timeout=15)
|
| 788 |
+
if r.status_code != 200:
|
| 789 |
+
return JSONResponse({"videos": []})
|
| 790 |
+
r.encoding = "utf-8"
|
| 791 |
+
soup = BeautifulSoup(r.text, "lxml")
|
| 792 |
+
videos, seen = [], set()
|
| 793 |
+
for a in soup.find_all("a", href=True):
|
| 794 |
+
href = a.get("href", "")
|
| 795 |
+
if "/video/" not in href and "/xem-lai/" not in href:
|
| 796 |
+
continue
|
| 797 |
+
if not href.startswith("http"):
|
| 798 |
+
href = "https://xemlaibongda.top" + href
|
| 799 |
+
clean = href.split("?")[0].split("#")[0]
|
| 800 |
+
if clean in seen: continue
|
| 801 |
+
seen.add(clean)
|
| 802 |
+
img_src = ""
|
| 803 |
+
img = a.find("img") or (a.parent.find("img") if a.parent else None)
|
| 804 |
+
if not img:
|
| 805 |
+
p = a.parent
|
| 806 |
+
for _ in range(5):
|
| 807 |
+
if p and p.find("img"):
|
| 808 |
+
img = p.find("img")
|
| 809 |
+
break
|
| 810 |
+
p = p.parent if p else None
|
| 811 |
+
if img:
|
| 812 |
+
img_src = (img.get("data-src", "") or img.get("src", "") or
|
| 813 |
+
img.get("data-lazy", "") or img.get("data-original", ""))
|
| 814 |
+
if img_src.startswith("//"): img_src = "https:" + img_src
|
| 815 |
+
elif img_src.startswith("/"): img_src = "https://xemlaibongda.top" + img_src
|
| 816 |
+
title = a.find("h3")
|
| 817 |
+
if not title: title = a.find("h2")
|
| 818 |
+
if not title: title = a.find("strong")
|
| 819 |
+
t = title.get_text(strip=True) if title else ""
|
| 820 |
+
if not t:
|
| 821 |
+
slug = clean.split("/video/")[-1].rstrip("/")
|
| 822 |
+
t = slug.replace("-", " ").title()
|
| 823 |
+
videos.append({"title": t[:100], "link": clean, "img": img_src, "source": "xemlaibongda"})
|
| 824 |
+
if len(videos) >= limit: break
|
| 825 |
+
return JSONResponse({"videos": videos})
|
| 826 |
+
except Exception as e:
|
| 827 |
+
return JSONResponse({"videos": [], "error": str(e)})
|
| 828 |
@app.get("/api/article")
|
| 829 |
def api_article(url:str=Query(...)):
|
| 830 |
+
try:
|
| 831 |
+
r2 = requests.get(url, headers=HEADERS, timeout=10)
|
| 832 |
+
if r2.status_code == 200:
|
| 833 |
+
r2.encoding = "utf-8"
|
| 834 |
+
soup = BeautifulSoup(r2.text, "lxml")
|
| 835 |
+
og = soup.find("meta", property="og:image")
|
| 836 |
+
return JSONResponse({"og_image": og.get("content", "") if og else ""})
|
| 837 |
+
except: pass
|
| 838 |
+
return JSONResponse({"og_image": ""})
|
| 839 |
|
| 840 |
@app.get("/api/storage_status")
|
| 841 |
def api_storage_status():
|