| import asyncio |
| from fastapi import FastAPI, HTTPException |
| from pydantic import BaseModel |
| from playwright.async_api import async_playwright |
|
|
| app = FastAPI(title="SaveFrom Extractor API") |
|
|
| class DownloadRequest(BaseModel): |
| url: str |
|
|
|
|
| @app.get("/") |
| def root(): |
| return {"status": "ok"} |
|
|
|
|
| @app.post("/download") |
| async def extract(req: DownloadRequest): |
| target = f"https://en.savefrom.net/1/{req.url}" |
|
|
| try: |
| async with async_playwright() as p: |
| browser = await p.chromium.launch( |
| headless=True, |
| args=[ |
| "--no-sandbox", |
| "--disable-dev-shm-usage", |
| "--disable-blink-features=AutomationControlled", |
| ], |
| ) |
|
|
| context = await browser.new_context( |
| user_agent=( |
| "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " |
| "AppleWebKit/537.36 (KHTML, like Gecko) " |
| "Chrome/120.0.0.0 Safari/537.36" |
| ), |
| viewport={"width": 1280, "height": 720}, |
| ) |
|
|
| page = await context.new_page() |
| await page.goto(target, wait_until="networkidle", timeout=60_000) |
|
|
| |
| await page.wait_for_timeout(4000) |
|
|
| links = await page.evaluate(""" |
| () => { |
| const results = []; |
| document.querySelectorAll("a").forEach(a => { |
| const href = a.href || ""; |
| if (href.includes(".mp4") || href.includes(".mp3")) { |
| results.push({ |
| url: href, |
| text: a.innerText || null |
| }); |
| } |
| }); |
| return results; |
| } |
| """) |
|
|
| await browser.close() |
|
|
| if not links: |
| raise HTTPException( |
| status_code=404, |
| detail="No downloadable links found" |
| ) |
|
|
| return { |
| "source": "neon dl", |
| "original_url": req.url, |
| "count": len(links), |
| "links": links |
| } |
|
|
| except Exception as e: |
| raise HTTPException( |
| status_code=500, |
| detail=f"Extractor error: {str(e)}" |
| ) |
|
|
| |
| |
| |
| |
| |
| |
| |