pyex / app.py
franyer24's picture
Update app.py
2d1c200 verified
Raw
History Blame Contribute Delete
3.64 kB
from fastapi import FastAPI, Query, Response
import undetected_chromedriver as uc
import requests
import time
import json
import os
from typing import Optional
app = FastAPI()
COOKIES_FILE = "cf_cookies.json"
def save_cookies(cookies: dict):
with open(COOKIES_FILE, "w") as f:
json.dump(cookies, f)
def load_cookies() -> Optional[dict]:
if not os.path.exists(COOKIES_FILE):
return None
with open(COOKIES_FILE, "r") as f:
return json.load(f)
def get_cf_cookie(url):
print("🔍 Iniciando navegador para resolver challenge de Cloudflare...")
try:
options = uc.ChromeOptions()
options.headless = True
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
options.add_argument("--disable-blink-features=AutomationControlled")
driver = uc.Chrome(options=options)
driver.get(url)
# Esperar hasta 30 segundos para que Cloudflare entregue cf_clearance
max_wait = 30
cf_clearance = None
domain = None
for _ in range(max_wait):
cookies = driver.get_cookies()
for cookie in cookies:
if cookie["name"] == "cf_clearance":
cf_clearance = cookie["value"]
domain = cookie["domain"]
break
if cf_clearance:
break
time.sleep(1)
driver.quit()
if cf_clearance:
print("✅ cf_clearance encontrada:", cf_clearance)
result = {"cf_clearance": cf_clearance, "domain": domain}
save_cookies(result)
return result
else:
print("⚠️ No se encontró cf_clearance")
return None
except Exception as e:
print("❌ Error con el navegador:", str(e))
return None
@app.get("/")
def root():
return {"message": "FastAPI + Cloudflare Bypass funcionando ✅"}
@app.get("/cookie")
def get_cookie(
url: str = "https://www.visa.com.do/cmsapi/fx/rates?amount=1&fee=3&utcConvertedDate=10%2F19%2F2025&exchangedate=10%2F19%2F2025&fromCurr=DOP&toCurr=USD"
):
result = get_cf_cookie(url)
if result:
return result
return {"error": "No se pudo obtener cf_clearance"}
@app.get("/scrape")
def scrape(url: str = Query(..., description="URL a scrapear")):
cookie_result = load_cookies()
if not cookie_result:
cookie_result = get_cf_cookie(url)
if not cookie_result:
return {
"error": "No se pudo obtener cf_clearance. Puede que el sitio no esté protegido por Cloudflare o hubo un error con el navegador."
}
headers = {
"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"
}
cookies = {
"cf_clearance": cookie_result["cf_clearance"]
}
try:
res = requests.get(url, headers=headers, cookies=cookies, timeout=10)
if res.status_code in (403, 503):
os.remove(COOKIES_FILE)
return {
"error": f"cf_clearance caducada o inválida (status {res.status_code}). Intenta regenerarla."
}
# Detectar tipo de contenido y devolver el body completo
content_type = res.headers.get("Content-Type", "").lower()
if "application/json" in content_type:
return Response(content=res.text, media_type="application/json")
else:
return Response(content=res.text, media_type="text/html")
except Exception as e:
return {"error": str(e)}