jcalbornoz commited on
Commit
9a627fd
·
verified ·
1 Parent(s): 7ac00a3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +81 -72
app.py CHANGED
@@ -1,12 +1,11 @@
1
  import os
2
  import subprocess
3
 
4
- # Instalar los binarios de Playwright al arrancar (Solo necesario en Hugging Face)
5
  try:
6
  import playwright
7
  except ImportError:
8
- subprocess.run(["pip", "install", "playwright"])
9
-
10
  subprocess.run(["playwright", "install", "chromium"])
11
 
12
  import gradio as gr
@@ -14,98 +13,108 @@ from playwright.sync_api import sync_playwright
14
  import pandas as pd
15
  from fpdf import FPDF
16
  import datetime
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
- # --- LÓGICA DE EXTRACCIÓN ---
19
- def extraer_datos_reales(zona, area_m2, tipo_inmueble):
20
  with sync_playwright() as p:
21
  browser = p.chromium.launch(headless=True)
22
- context = browser.new_context(
23
- 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"
24
- )
25
  page = context.new_page()
26
 
27
  zona_url = zona.lower().replace(" ", "-")
28
- url = f"https://www.fincaraiz.com.co/{tipo_inmueble.lower()}/arriendo/{zona_url}"
29
 
30
  try:
31
- page.goto(url, wait_until="networkidle", timeout=60000)
32
- page.wait_for_selector('article', timeout=20000)
33
 
34
  referencias = []
35
- cards = page.query_selector_all('article')
36
 
37
  for card in cards:
38
- if len(referencias) >= 5: break
39
  try:
40
- content = card.inner_text()
41
- lines = content.split('\n')
42
-
43
- precio_line = [l for l in lines if '$' in l][0]
44
- precio = int(''.join(filter(str.isdigit, precio_line)))
45
-
46
- area_line = [l for l in lines if 'm²' in l or 'm2' in l][0]
47
- area_ref = int(''.join(filter(str.isdigit, area_line)))
48
-
49
- if precio > 100000 and area_ref > 5:
50
- referencias.append({
51
- "Precio": precio,
52
- "Area": area_ref,
53
- "Precio_M2": precio / area_ref
54
- })
55
- except:
56
- continue
57
 
58
  browser.close()
59
- return pd.DataFrame(referencias)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  except:
61
  browser.close()
62
- return pd.DataFrame()
63
 
64
- # --- GENERADOR DE PDF ---
65
- def crear_pdf_formal(zona, area, valor_final, df):
66
  pdf = FPDF()
67
  pdf.add_page()
68
  pdf.set_font("Arial", 'B', 16)
69
- pdf.cell(200, 15, "ESTUDIO DE MERCADO INMOBILIARIO", ln=True, align='C')
70
- pdf.ln(10)
71
-
72
- pdf.set_font("Arial", '', 12)
73
- pdf.cell(0, 10, f"Zona: {zona.upper()}", ln=True)
74
- pdf.cell(0, 10, f"Valor Renta Sugerido: ${valor_final:,.0f} COP", ln=True)
75
- pdf.ln(10)
76
-
77
- pdf.set_font("Arial", 'B', 10)
78
- pdf.cell(60, 10, "Referencia", 1)
79
- pdf.cell(60, 10, "Precio", 1)
80
- pdf.cell(60, 10, "Area", 1, ln=True)
81
-
82
- pdf.set_font("Arial", '', 10)
83
- for i, row in df.iterrows():
84
- pdf.cell(60, 10, f"Inmueble {i+1}", 1)
85
- pdf.cell(60, 10, f"${row['Precio']:,.0f}", 1)
86
- pdf.cell(60, 10, f"{row['Area']} m2", 1, ln=True)
87
-
88
- filename = "Reporte_Estimacion.pdf"
89
- pdf.output(filename)
90
- return filename
91
 
92
- # --- INTERFAZ ---
93
- def procesar(zona, area, tipo):
94
- df = extraer_datos_reales(zona, area, tipo)
95
- if df.empty: return "No se hallaron datos.", None, None
96
-
97
- promedio_m2 = df['Precio_M2'].mean()
98
- valor_final = (promedio_m2 * area) * 0.93
99
- pdf_path = crear_pdf_formal(zona, area, valor_final, df)
100
 
101
- return f"### Valor sugerido: ${valor_final:,.0f} COP", df, pdf_path
 
 
 
 
 
 
 
 
 
 
 
 
 
102
 
103
- demo = gr.Interface(
104
- fn=procesar,
105
- inputs=[gr.Textbox(label="Zona"), gr.Number(label="M2"), gr.Dropdown(["Apartamento", "Casa"])],
106
- outputs=[gr.Markdown(), gr.Dataframe(), gr.File(label="Descargar PDF")],
107
- title="Estimador Inmobiliario Colombia"
108
- )
109
 
110
  if __name__ == "__main__":
111
- demo.launch()
 
1
  import os
2
  import subprocess
3
 
4
+ # Configuración de entorno
5
  try:
6
  import playwright
7
  except ImportError:
8
+ subprocess.run(["pip", "install", "playwright folium"])
 
9
  subprocess.run(["playwright", "install", "chromium"])
10
 
11
  import gradio as gr
 
13
  import pandas as pd
14
  from fpdf import FPDF
15
  import datetime
16
+ import folium
17
+
18
+ # --- LÓGICA DE GEOCALIZACIÓN Y MAPA ---
19
+ def generar_mapa_zona(zona):
20
+ # En un sistema real, usarías una API de geocoding.
21
+ # Aquí creamos un mapa centrado en coordenadas base de Colombia (Bogotá)
22
+ # que el usuario puede previsualizar.
23
+ m = folium.Map(location=[4.6097, -74.0817], zoom_start=12, tiles="CartoDB positron")
24
+ folium.Marker(
25
+ [4.6097, -74.0817],
26
+ popup=f"Zona de Análisis: {zona}",
27
+ icon=folium.Icon(color='blue', icon='info-sign')
28
+ ).add_to(m)
29
+
30
+ map_path = "mapa_tramitia.html"
31
+ m.save(map_path)
32
+ return map_path
33
 
34
+ # --- MOTOR DE EXTRACCIÓN TRAMITIA ---
35
+ def motor_tramitia(zona, area_m2, tipo):
36
  with sync_playwright() as p:
37
  browser = p.chromium.launch(headless=True)
38
+ context = browser.new_context(user_agent="Mozilla/5.0")
 
 
39
  page = context.new_page()
40
 
41
  zona_url = zona.lower().replace(" ", "-")
42
+ url = f"https://www.fincaraiz.com.co/{tipo.lower()}/arriendo/{zona_url}"
43
 
44
  try:
45
+ page.goto(url, wait_until="networkidle", timeout=45000)
46
+ page.wait_for_selector('article', timeout=15000)
47
 
48
  referencias = []
49
+ cards = page.query_selector_all('article')[:5]
50
 
51
  for card in cards:
 
52
  try:
53
+ content = card.inner_text().replace('.', '').replace('$', '')
54
+ nums = [int(s) for s in content.split() if s.isdigit()]
55
+ precio = max(nums)
56
+ area_ref = next((n for n in nums if 15 < n < 500), area_m2)
57
+ referencias.append({"Precio": precio, "Area": area_ref, "Precio_M2": precio/area_ref})
58
+ except: continue
 
 
 
 
 
 
 
 
 
 
 
59
 
60
  browser.close()
61
+
62
+ if not referencias: return "⚠️ No se hallaron datos.", None, None, None
63
+
64
+ df = pd.DataFrame(referencias)
65
+ valor_m2 = df['Precio_M2'].mean()
66
+ valor_estimado = (valor_m2 * area_m2) * 0.93
67
+
68
+ # Generar PDF y Mapa
69
+ pdf_path = generar_pdf_tramitia(zona, area_m2, valor_estimado, df)
70
+ mapa_html = generar_mapa_zona(zona)
71
+
72
+ resumen_html = f"""
73
+ <div style='background-color: #e6fffa; padding: 15px; border-radius: 8px; border: 1px solid #38b2ac;'>
74
+ <h3 style='color: #2c7a7b; margin: 0;'>📍 Análisis Geo-referenciado TramitIA</h3>
75
+ <p style='font-size: 1.1em;'>Estimación para {zona}: <b>${valor_estimado:,.0f} COP</b></p>
76
+ </div>
77
+ """
78
+ return resumen_html, df, pdf_path, mapa_html
79
  except:
80
  browser.close()
81
+ return "❌ Error de conexión.", None, None, None
82
 
83
+ def generar_pdf_tramitia(zona, area, valor, df):
 
84
  pdf = FPDF()
85
  pdf.add_page()
86
  pdf.set_font("Arial", 'B', 16)
87
+ pdf.cell(0, 15, "TRAMITIA - CERTIFICADO TÉCNICO", ln=True, align='C')
88
+ pdf.set_font("Arial", '', 11)
89
+ pdf.cell(0, 10, f"Ubicación: {zona.upper()} | Área: {area}m2", ln=True)
90
+ pdf.cell(0, 10, f"Valor Sugerido: ${valor:,.0f} COP", ln=True)
91
+ pdf.output("Reporte_TramitIA.pdf")
92
+ return "Reporte_TramitIA.pdf"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
 
94
+ # --- INTERFAZ TRAMITIA PRO ---
95
+ with gr.Blocks(css=".gradio-container {background-color: #f7fafc}") as demo:
96
+ gr.HTML("<div style='text-align: center; color: #2d3748;'><h1>🤖 TramitIA Pro</h1><p>Geolocalización e Inteligencia Inmobiliaria</p></div>")
 
 
 
 
 
97
 
98
+ with gr.Row():
99
+ with gr.Column(scale=1):
100
+ zona_input = gr.Textbox(label="Ubicación Detallada", placeholder="Ej: Ciudad Salitre, Bogotá")
101
+ area_input = gr.Number(label="Área M2", value=150)
102
+ tipo_input = gr.Dropdown(["Apartamento", "Casa", "Oficina"], label="Tipo", value="Apartamento")
103
+ btn = gr.Button("INICIAR CONSULTA GEOGRÁFICA", variant="primary")
104
+
105
+ with gr.Column(scale=2):
106
+ res_html = gr.HTML()
107
+ # Componente de Mapa
108
+ mapa_view = gr.HTML(label="Visualización de Zona")
109
+ with gr.Row():
110
+ pdf_file = gr.File(label="Informe Técnico")
111
+ data_view = gr.Dataframe(label="Comparables")
112
 
113
+ btn.click(
114
+ motor_tramitia,
115
+ inputs=[zona_input, area_input, tipo_input],
116
+ outputs=[res_html, data_view, pdf_file, mapa_view]
117
+ )
 
118
 
119
  if __name__ == "__main__":
120
+ demo.launch()