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}")