Juanoto2012 commited on
Commit
45e11e9
·
verified ·
1 Parent(s): 56a247e

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +93 -0
app.py ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, HTTPException, Query
2
+ from fastapi.middleware.cors import CORSMiddleware
3
+ from duckduckgo_search import DDGS
4
+ import requests
5
+ import uvicorn
6
+
7
+ app = FastAPI(title="Glimpse Search API", description="API unificada para múltiples motores de búsqueda")
8
+
9
+ # Habilitar CORS para que tu app frontend pueda consumir esta API sin errores
10
+ app.add_middleware(
11
+ CORSMiddleware,
12
+ allow_origins=["*"], # En producción, puedes cambiar "*" por el dominio de tu app
13
+ allow_credentials=True,
14
+ allow_methods=["*"],
15
+ allow_headers=["*"],
16
+ )
17
+
18
+ # Servidores públicos de SearXNG como fallback para los otros motores
19
+ SEARXNG_INSTANCES = [
20
+ "https://searx.be/search",
21
+ "https://searx.fmac.network/search",
22
+ "https://search.mdosch.de/search"
23
+ ]
24
+
25
+ @app.get("/")
26
+ def read_root():
27
+ return {"status": "Glimpse API is running. Use the /search endpoint."}
28
+
29
+ @app.get("/search")
30
+ def search(
31
+ q: str = Query(..., description="Término de búsqueda"),
32
+ engine: str = Query("duckduckgo", description="duckduckgo, brave, startpage, mojeek, qwant")
33
+ ):
34
+ results = []
35
+ engine = engine.lower()
36
+
37
+ # 1. Búsqueda nativa y rápida con DuckDuckGo
38
+ if engine == "duckduckgo":
39
+ try:
40
+ with DDGS() as ddgs:
41
+ # max_results controla cuántos enlaces devuelves
42
+ ddg_results = list(ddgs.text(q, max_results=15))
43
+ for r in ddg_results:
44
+ results.append({
45
+ "title": r.get("title", ""),
46
+ "url": r.get("href", ""),
47
+ "content": r.get("body", "")
48
+ })
49
+ except Exception as e:
50
+ raise HTTPException(status_code=500, detail=f"Error en DuckDuckGo: {str(e)}")
51
+
52
+ # 2. Búsqueda con Brave, Startpage, Mojeek a través del puente de SearXNG
53
+ else:
54
+ # Si enviaste "tapnav", lo mapearemos a algo que Searxng entienda, como qwant
55
+ if engine == "tapnav":
56
+ engine = "qwant"
57
+
58
+ success = False
59
+ params = {
60
+ "q": q,
61
+ "format": "json",
62
+ "engines": engine,
63
+ "language": "es-ES"
64
+ }
65
+
66
+ # Intentar en nuestras instancias de fallback si alguna falla
67
+ for instance in SEARXNG_INSTANCES:
68
+ try:
69
+ resp = requests.get(instance, params=params, timeout=5)
70
+ resp.raise_for_status()
71
+ data = resp.json()
72
+
73
+ for r in data.get("results", []):
74
+ results.append({
75
+ "title": r.get("title", ""),
76
+ "url": r.get("url", ""),
77
+ "content": r.get("content", "")
78
+ })
79
+ success = True
80
+ break # Si tuvo éxito, salimos del bucle
81
+ except Exception as e:
82
+ print(f"Falló la instancia {instance} para el motor {engine}: {e}")
83
+ continue
84
+
85
+ if not success:
86
+ raise HTTPException(status_code=503, detail=f"Todos los servidores proxy para el motor {engine} fallaron temporalmente.")
87
+
88
+ # Devolvemos exactamente el formato que espera tu HTML
89
+ return {"results": results}
90
+
91
+ if __name__ == "__main__":
92
+ # Hugging Face expone los puertos en el 7860 por defecto
93
+ uvicorn.run(app, host="0.0.0.0", port=7860)