bgustscraper 0.2.0

Advanced semantic scraping engine with AI-driven compliance checks and legal terms validation
Documentation
# Daemon Planificador de Agenda (Scheduler) ⏰

`bgustscraper` cuenta con un motor de programación de tareas en segundo plano que permite ejecutar rutinas de raspado complejas de manera desatendida. Está diseñado para garantizar la **tolerancia a fallos**, **evitar el consumo innecesario de recursos** y **evitar el spam o bloqueos de IP** en sitios web protegidos.

---

## 📂 1. Configuración de Agenda: `config/schedule.json`

El planificador asíncrono carga su configuración desde `config/schedule.json`. Este archivo modela las tareas y sus respectivas ventanas horarias semanales de validez:

```json
{
  "jobs": [
    {
      "name": "tasas_bcv",
      "url": "https://www.bcv.org.ve/",
      "days": ["Mon", "Tue", "Wed", "Thu", "Fri"],
      "windows": [
        { "name": "AM", "start": "09:00", "end": "12:59" },
        { "name": "PM", "start": "13:00", "end": "18:00" }
      ],
      "extract_prompt": "Extrae las tasas oficiales de venta del Dólar (USD) y Euro (EUR)...",
      "output_path": "downloads/bcv_rates.json"
    }
  ]
}
```

### Atributos Clave:
*   `days`: Listado de días de la semana de validez (`"Mon"`, `"Tue"`, etc.).
*   `windows`: Segmentos específicos en los cuales la tarea debe ejecutarse.
*   `output_path`: Ruta física en el disco donde se persistirá el resultado de la inferencia JSON final.

---

## 💾 2. Control de Estado en `redb` (Prevención de Spam)

Para cumplir con la regla de negocio de **ejecutar la tarea una sola vez dentro de cada ventana**, el scheduler interactúa directamente con la base de datos de caché local embebida **`redb`**:

### La Lógica de Control:
1.  El daemon del scheduler corre en un bucle infinito asíncrono despertando cada **60 segundos** en Tokio.
2.  Obtiene la hora, día de la semana y fecha local (ej: martes, 10:15 AM).
3.  Busca tareas activas en esa ventana (ej: `tasas_bcv` en la ventana `AM`).
4.  Antes de iniciar Playwright o cualquier llamada, comprueba si existe una marca en la base de datos de `redb` bajo la clave:
    `schedule:<job_name>:<YYYY-MM-DD>:<window_name>` (ej. `schedule:tasas_bcv:2026-06-02:AM`).
5.  **Si existe con valor `EJECUTADO`:** Omitir de forma inmediata. La tarea ya se corrió hoy en esta ventana.
6.  **Si no existe:**
    *   Levanta el worker asíncrono.
    *   Raspa la web, comprime el texto mediante clustering K-Means y ejecuta la extracción estructurada con Qwen.
    *   Guarda el JSON final en el disco (`downloads/bcv_rates.json`).
    *   Inserta la clave `schedule:tasas_bcv:2026-06-02:AM` en `redb` con valor `EJECUTADO`.
    *   Cierra el worker de forma segura.

---

## 🛡️ 3. Resiliencia y Tolerancia a Fallos
Este diseño asíncrono-persistente asegura que:
*   **Si la máquina se apaga o el servidor se reinicia** a las 11:00 AM, al reanudarse, el programador sabrá que ya se ejecutó a las 9:02 AM y no volverá a realizar peticiones innecesarias al sitio web, evitando posibles baneos de IP o consumos extra de CPU.
*   **Si el daemon se inicia tarde** (ej: a las 10:00 AM en lugar de a las 9:00 AM), detectará que no ha corrido hoy en la ventana AM, la ejecutará inmediatamente y la marcará, garantizando la recolección del dato diario de forma segura.