FLUJOS/INFO/DOCS/CONTEXT/SCRAPER_IMAGENES_QWEN.md
CAPITANSITO 954f47996f refactor: reorganizar docs y pocs bajo INFO/
- docs/ → INFO/DOCS/CONTEXT/ (documentación técnica en markdown)
- FLUJOS/DOCS/ + FLUJOS_DATOS/DOCS/ → INFO/DOCS/ (txts de arquitectura)
- POCS/ → INFO/POCS/ (pruebas de concepto)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-21 23:49:33 +02:00

271 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Scraper de Imágenes + Analizador Qwen3-VL — Contexto técnico FLUJOS
**Fecha:** 2026-04-21
**Directorio:** `FLUJOS_DATOS/IMAGENES/`
**Entorno:** `FLUJOS_DATOS/myenv/` (Python 3.11, venv)
---
## Componentes del módulo
```
FLUJOS_DATOS/IMAGENES/
├── wikipedia_image_scraper.py # Descarga imágenes de Wikipedia por tema
├── image_analyzer.py # Analiza imágenes con Qwen3-VL-8B
├── image_comparator.py # Compara imágenes (similaridad visual)
├── mongo_helper.py # Utilidades MongoDB para este módulo
├── pipeline_imagenes.py # Orquestador del módulo (flags CLI)
├── requirements_imagenes.txt # Dependencias del módulo
├── model_cache/ # Modelo Qwen descargado (~16 GB) — en .gitignore
└── output/
└── wiki_images/ # Imágenes descargadas — en .gitignore
├── cambio_climático/
├── geopolítica_conflictos/
├── seguridad_internacional_espionaje/
└── ...
```
---
## Parte 1: wikipedia_image_scraper.py
### Qué hace
Descarga imágenes de Wikipedia por tema usando la **Wikimedia REST API**. Para cada tema de FLUJOS busca artículos relacionados, extrae las imágenes de cada artículo y las descarga filtrando iconos/logos pequeños.
### Temas de FLUJOS que se scrapean (`TEMAS_FLUJOS`)
```python
TEMAS_FLUJOS = [
"cambio climático",
"geopolítica conflictos",
"seguridad internacional espionaje",
"libertad de prensa periodismo",
"corporaciones poder económico",
"populismo extremismo",
"desinformación redes sociales",
"privacidad vigilancia masiva",
"biodiversidad medioambiente",
"inteligencia artificial tecnología",
]
```
### Filtros de calidad (imágenes que se descartan)
```python
MIN_WIDTH = 200 # pixels
MIN_HEIGHT = 200 # pixels
MIN_BYTES = 20_000 # 20 KB mínimo
SKIP_PATTERNS = [
"flag_", "Flag_", "icon", "Icon", "logo", "Logo",
"symbol", "Symbol", "coat_of_arms", "commons-logo",
"wiki", "Wiki", "question_mark", "edit-", "nuvola",
"Nuvola", "pictogram", "OOjs", "Ambox", "Portal-", "Disambig",
]
VALID_EXTENSIONS = {".jpg", ".jpeg", ".png", ".webp"}
```
### Flujo interno
```
buscar_articulos(tema, lang='es')
└── GET https://es.wikipedia.org/w/api.php?action=query&list=search&srsearch={tema}
└── para cada artículo:
get_article_images(titulo)
└── GET https://es.wikipedia.org/w/api.php?action=query&prop=images
└── para cada imagen:
get_image_info(filename) → Wikimedia API
└── descarga si pasa filtros
└── guarda en output/wiki_images/{tema_slug}/
└── upsert en MongoDB imagenes_wiki
```
### Deduplicación
Upsert por `archivo` (nombre del fichero) en MongoDB `imagenes_wiki`. Si el fichero ya existe en disco, se salta la descarga.
### Uso CLI
```bash
# Scrape de todos los temas FLUJOS, max 20 imgs/tema, con MongoDB
python wikipedia_image_scraper.py --flujos --max 20 --mongo
# Scrape de un tema concreto
python wikipedia_image_scraper.py --tema "cambio climático" --max 30 --mongo
# Con idioma inglés
python wikipedia_image_scraper.py --tema "climate change" --lang en --max 40
```
### Documento MongoDB generado (colección `imagenes_wiki`)
```json
{
"archivo": "cambio_climático_003.jpg",
"image_path": "/var/www/theflows.net/flujos/FLUJOS_DATOS/IMAGENES/output/wiki_images/cambio_climático/cambio_climático_003.jpg",
"image_url": "https://upload.wikimedia.org/wikipedia/commons/...",
"tema": "cambio climático",
"subtema": "derretimiento glaciar ártico",
"descripcion_wiki": "Glaciar en retroceso en el Ártico, 2019",
"articulo_titulo": "Cambio climático en el Ártico",
"fecha": ISODate("2026-04-21")
}
```
---
## Parte 2: image_analyzer.py (Qwen3-VL-8B)
### Modelo usado
**Qwen/Qwen2.5-VL-7B-Instruct** (HuggingFace)
- Tamaño: ~16 GB en disco (bfloat16)
- Inferencia: CPU (sin GPU disponible actualmente)
- RAM necesaria: ~1618 GB para el modelo + ~2 GB por batch de 4 imágenes
- Cache local: `IMAGENES/model_cache/`
> El servidor tiene 64 GB RAM, por lo que cabe sin problema. En GPU (A100/RTX 3090+) sería 1050x más rápido.
### Carga del modelo
```python
from transformers import Qwen2_5_VLForConditionalGeneration, AutoProcessor
import torch
model = Qwen2_5_VLForConditionalGeneration.from_pretrained(
"Qwen/Qwen2.5-VL-7B-Instruct",
torch_dtype=torch.bfloat16, # mitad de RAM vs float32
device_map="cpu",
cache_dir=str(IMAGENES_DIR / "model_cache"),
)
processor = AutoProcessor.from_pretrained(
"Qwen/Qwen2.5-VL-7B-Instruct",
cache_dir=str(IMAGENES_DIR / "model_cache"),
)
```
### Prompt de análisis
```python
PROMPT = """Analiza esta imagen y proporciona:
1. Una descripción concisa del contenido principal (máx. 2 frases).
2. El tema principal (elige uno): cambio climático, conflicto armado, economía, política, tecnología, sociedad, otro.
3. Lista de 3-5 palabras clave relevantes.
Formato de respuesta:
DESCRIPCIÓN: [descripción]
TEMA: [tema]
PALABRAS CLAVE: [kw1, kw2, kw3]"""
```
### Procesamiento por batch
```python
def analyze_batch(image_paths: list[Path]) -> list[dict]:
"""Procesa hasta 4 imágenes por llamada al modelo."""
```
`batch_size=4` por defecto. Cada batch ocupa ~2 GB RAM adicionales.
### Resume automático
Antes de analizar, verifica qué imágenes ya están en MongoDB `imagenes`:
```python
def get_already_analyzed() -> set[str]:
"""Devuelve set de nombres de archivo ya en la colección imagenes."""
return {doc['archivo'] for doc in db['imagenes'].find({}, {'archivo': 1})}
```
Solo procesa imágenes no presentes en la BD.
### Priorización de imágenes
```python
def get_known_article_titles() -> set[str]:
"""Títulos de artículos presentes en wikipedia/noticias."""
# Prioriza imágenes cuyo tema coincide con artículos existentes
```
Las imágenes de temas con más documentos de texto en la BD se procesan primero, para maximizar la probabilidad de que los nodos imagen queden conectados por comparaciones.
### Documento MongoDB generado (colección `imagenes`)
```json
{
"archivo": "cambio_climático_003.jpg",
"image_path": "/var/www/.../output/wiki_images/cambio_climático/cambio_climático_003.jpg",
"tema": "cambio climático",
"subtema": "calentamiento global",
"texto": "Imagen satelital del retroceso del glaciar ártico entre 1990 y 2023. Se observa una reducción significativa de la capa de hielo.",
"keywords": ["glaciar", "ártico", "deshielo", "calentamiento", "satélite"],
"fecha": ISODate("2026-04-21")
}
```
---
## Parte 3: pipeline_imagenes.py (orquestador)
### Flags CLI
```bash
python pipeline_imagenes.py --scrape # solo scraping de imágenes
python pipeline_imagenes.py --analizar # solo análisis Qwen
python pipeline_imagenes.py --mongo # escribe resultados en MongoDB
python pipeline_imagenes.py --solo-json # escribe JSON local en vez de Mongo
python pipeline_imagenes.py --analizar --carpeta /ruta/custom --mongo
```
### Integración en el pipeline maestro
El `pipeline_maestro.py` lo llama así:
**Fase 1 (scraping):**
```bash
python wikipedia_image_scraper.py --flujos --max 20 --mongo
```
**Fase 2 (análisis):**
```bash
python pipeline_imagenes.py --analizar \
--carpeta FLUJOS_DATOS/IMAGENES/output/wiki_images \
--mongo
```
---
## Dependencias Python (requirements_imagenes.txt)
```
transformers>=4.45
torch>=2.1
qwen-vl-utils
Pillow
requests
pymongo
scikit-learn
python-dotenv
```
Instalación en el venv:
```bash
/var/www/theflows.net/flujos/FLUJOS_DATOS/myenv/bin/python3 -m pip install -r requirements_imagenes.txt
```
---
## Estado actual (2026-04-21)
- Imágenes en disco: ~155 imágenes en `output/wiki_images/` (10 temas × ~15 imgs)
- Imágenes en `imagenes_wiki` (MongoDB): ~150 docs
- Imágenes analizadas con Qwen en `imagenes` (MongoDB): proceso en curso / pendiente de primera ejecución completa
- El modelo Qwen se descarga automáticamente la primera vez que se llama (~16 GB, puede tardar 3060 min)
## Pendiente / mejoras futuras
- Conectar nodos imagen a la colección `comparaciones` (requiere embeddings de imagen o comparación texto-descripción)
- Activar GPU cuando esté disponible (cambiar `device_map="cpu"``"cuda"`)
- Aumentar `--max` a 50+ imágenes por tema una vez el análisis esté validado
- Añadir soporte para imágenes de noticias (no solo Wikipedia)