Iteración HU - IbenMG/GRUPO09-2025-PROYINF GitHub Wiki
Iteración HU02 - Clasificación Automática de Información
Estado: 🟡 En progreso
Total horas estimadas: 9 horas
📋 Tareas Técnicas
# | Tarea | Descripción | Tiempo Estimado | Estado |
---|---|---|---|---|
1 | Definir categorías iniciales | Crear lista base (plagas, clima, cultivos, etc.) y esquema de datos en backend. | 1 hora | ✅ |
2 | Implementar módulo de clasificación | Usar palabras clave para clasificar textos. Función: clasificar_texto(texto) → categorías . |
3 horas | 🟡 |
3 | Integrar en flujo de procesamiento | Asegurar clasificación automática al ingresar datos. | 2 horas | ❌ |
4 | Interfaz de gestión de categorías | Vista para administradores (CRUD de categorías). Actualizar clasificador en tiempo real. | 2 horas | ❌ |
5 | Pruebas y validación | Test con diversos textos. Validar nuevas categorías. | 1 hora | ❌ |
Justificación de Prioridad
La HU02 fue priorizada porque constituye el núcleo funcional del sistema de vigilancia científica agrícola. Su implementación permite:
- Automatizar la organización temática de documentos, habilitando funcionalidades críticas como la generación de boletines personalizados.
- Reducir la carga de trabajo manual, permitiendo escalabilidad y eficiencia operativa.
- Probar tempranamente el flujo completo del sistema (recolección, clasificación, despliegue).
- Mostrar de forma visible e inmediata el valor del sistema al cliente, fortaleciendo la confianza en el desarrollo.
Esta historia de usuario habilita directamente el valor de negocio esperado por la plataforma, por eso se considera esencial abordarla primero.
Código
import requests
from bs4 import BeautifulSoup
import os
from urllib.parse import urljoin
# URL objetivo
url = "https://opia.fia.cl/601/w3-propertyvalue-148969.html"
# Diccionario de palabras clave por categoría agrícola
CATEGORIAS = {
"plagas": ["insecto", "pulgón", "oruga", "infestación", "plaga"],
"clima": ["lluvia", "temperatura", "sequía", "viento", "clima", "cambio climático"],
"cultivos": ["trigo", "maíz", "soja", "cultivo", "plantación", "cultivos sostenibles"],
"recursos hídricos": ["agua", "riego", "recurso hídrico", "sequía", "hidráulico"],
"sustentabilidad": ["agricultura sustentable", "sustentabilidad", "alimentación sostenible", "gestión de recursos naturales"],
"innovación": ["innovación agrícola", "tecnología agrícola", "digitalización agrícola"],
}
# Función para clasificar un texto por categoría
def clasificar_por_categoria(texto):
texto = texto.lower()
categorias = set()
for categoria, palabras in CATEGORIAS.items():
for palabra in palabras:
if palabra.lower() in texto:
categorias.add(categoria)
break
return categorias
# Acceder a la página principal
try:
response = requests.get(url)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
print("Página accedida correctamente")
except requests.exceptions.RequestException as e:
print(f"Error al acceder a la página: {e}")
exit()
# Buscar todos los enlaces
enlaces = soup.find_all('a')
documentos_encontrados = []
# Clasificar enlaces según categorías
for enlace in enlaces:
texto = enlace.get_text().lower()
categorias_detectadas = clasificar_por_categoria(texto)
if categorias_detectadas:
href = enlace.get('href', '')
if href:
href_completo = urljoin(url, href)
documentos_encontrados.append((texto, href_completo, list(categorias_detectadas)))
print(f"Documento encontrado: {texto} → Categorías: {categorias_detectadas}")
if not documentos_encontrados:
print("No se encontraron documentos clasificados.")
exit()
# Función para encontrar el enlace al PDF en la página destino
def obtener_enlace_pdf(pagina_destino):
try:
response = requests.get(pagina_destino)
response.raise_for_status()
soup_destino = BeautifulSoup(response.text, 'html.parser')
pdf_enlace = soup_destino.find('a', href=lambda href: href and href.endswith('.pdf'))
if pdf_enlace:
return urljoin(pagina_destino, pdf_enlace['href'])
else:
print("No se encontró un enlace PDF en la página de destino.")
return None
except requests.exceptions.RequestException as e:
print(f"Error al acceder a la página de destino: {e}")
return None
# Descargar documentos y clasificarlos por carpeta
for i, (nombre, enlace, categorias) in enumerate(documentos_encontrados):
pdf_url = obtener_enlace_pdf(enlace)
if pdf_url:
try:
print(f"Descargando desde: {pdf_url}")
doc_response = requests.get(pdf_url)
doc_response.raise_for_status()
for categoria in categorias:
carpeta = os.path.join("documentos_clasificados", categoria)
os.makedirs(carpeta, exist_ok=True)
nombre_archivo = f"documento_{i+1}.pdf"
ruta_completa = os.path.join(carpeta, nombre_archivo)
with open(ruta_completa, 'wb') as f:
f.write(doc_response.content)
print(f"Guardado en: {ruta_completa}")
except requests.exceptions.RequestException as e:
print(f"Error al descargar {pdf_url}: {e}")
else:
print(f"No se pudo obtener el PDF para: {nombre}")