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

8.5 KiB
Raw Blame History

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)

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)

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

# 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)

{
  "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

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

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

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:

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

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)

{
  "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

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):

python wikipedia_image_scraper.py --flujos --max 20 --mongo

Fase 2 (análisis):

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:

/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)