FLUJOS/INFO/DOCS/CONTEXT/SCRAPER_WIKIPEDIA.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

7 KiB

Scraper de Wikipedia — Contexto técnico FLUJOS

Fecha: 2026-04-21
Archivo: FLUJOS_DATOS/WIKIPEDIA/main.py
Utilidades: FLUJOS_DATOS/WIKIPEDIA/wikipedia_utils.py
Entorno: FLUJOS_DATOS/myenv/ (Python 3.11, venv)


Qué hace

Descarga artículos de Wikipedia en español organizados por temas de FLUJOS, los limpia, tokeniza con BERT y los guarda en disco (.txt) y MongoDB (wikipedia).


Temas y palabras clave

El scraper itera sobre un diccionario de temas con listas de keywords. Para cada keyword hace una búsqueda en la Wikipedia API y descarga los artículos encontrados.

temas = {
    "inteligencia y seguridad": [
        "inteligencia", "seguridad", "espionaje", "ciberseguridad", "NSA", "FBI", "CIA",
        "contraterrorismo", "criptografía", "vigilancia", "hackeo", "ransomware", ...
    ],
    "guerras": [
        "guerra", "conflicto", "batalla", "militar", "guerra civil", "intervención militar",
        "fuerzas armadas", "ejército", "terrorismo", "crímenes de guerra", ...
    ],
    "corporaciones": [
        "empresa", "multinacionales", "mercado bursátil", "BlackRock", "Vanguard",
        "fusiones", "adquisiciones", "venture capital", "evasión fiscal", ...
    ],
    "demografía": [
        "población", "migración", "natalidad", "urbanización", "refugiados",
        "desigualdad", "pobreza", "pandemia", ...
    ],
    "cambio climático": [
        "cambio climático", "calentamiento global", "energías renovables",
        "deforestación", "emisiones de carbono", "acuerdo de París", ...
    ],
    "organizaciones internacionales": [
        "OTAN", "BRICS", "ONU", "Unión Europea", "FMI", "Banco Mundial", ...
    ],
    "gobiernos autoritarios": [
        "dictadura", "autoritario", "represión política", "censura", "prisioneros políticos", ...
    ],
}

Cada tema tiene entre 50 y 100 palabras clave. En total son ~500 keywords → cada una genera hasta 50 artículos = potencial de ~25.000 artículos.


Flujo de scraping

para cada (tema, palabras_clave):
    para cada palabra_clave:
        buscar_articulos(palabra_clave, max_articulos=50, offset=0)
            └── GET https://es.wikipedia.org/w/api.php
                    action=query, list=search, srsearch={keyword}
            para cada titulo encontrado:
                if titulo not in titulos_descargados:
                    contenido = obtener_contenido_wikipedia(titulo)
                        └── GET https://es.wikipedia.org/w/api.php
                                action=query, prop=revisions, rvprop=content
                    guardar en articulos_wikipedia/{titulo_limpio}.txt
                    titulos_descargados.add(titulo)
        offset += 50  # paginación
        time.sleep(1) # cortesía hacia la API

Límite de tamaño: Para cuando articulos_wikipedia/ supera 100 GB (en la práctica nunca se ha alcanzado).


Limpieza de texto

def limpiar_texto(texto):
    texto = texto.lower()
    texto = re.sub(r'[^\w\s]', '', texto)   # elimina puntuación
    palabras = texto.split()
    palabras_limpias = [p for p in palabras if p not in stopwords]
    return ' '.join(palabras_limpias)

Stopwords: lista manual en español (~200 palabras). No usa NLTK en este módulo (sí en pipeline_completo.py).


Tokenización BERT

from transformers import BertTokenizer

tokenizer = BertTokenizer.from_pretrained('dccuchile/bert-base-spanish-wwm-cased')

def TOKENIZER():
    archivos = os.listdir('articulos_wikipedia')
    for archivo in archivos:
        contenido = open(f'articulos_wikipedia/{archivo}').read()
        tokens_ids = tokenizer.encode(contenido, add_special_tokens=False)
        with open(f'articulos_tokenizados/{archivo}', 'w') as f:
            f.write(' '.join(map(str, tokens_ids)))
  • Modelo BERT: dccuchile/bert-base-spanish-wwm-cased (BERT en español de la U. de Chile)
  • Truncación: 512 tokens máximo por documento
  • Output: archivo .txt con IDs numéricos separados por espacios

Limpiar nombre de fichero

def limpiar_nombre_archivo(nombre):
    nombre = re.sub(r'[\\/*?:"<>|]', "_", nombre)
    return nombre
# Ejemplo: "Guerra_del_Golfo_(1990)" → "Guerra_del_Golfo__1990_"

El nombre del fichero es el título del artículo de Wikipedia limpiado. Es también el archivo en MongoDB (clave de dedup).


Asignación de tema y subtema

Esta lógica vive en pipeline_completo.py::asignar_tema_y_subtema(), no en el scraper. El scraper solo guarda texto; el tokenizador/comparador asigna el tema.

tematicas = {
    'inteligencia y seguridad': ['inteligencia', 'ciberseguridad', 'espionaje', ...],
    'cambio climático':         ['cambio climático', 'desastres naturales', ...],
    'guerra global':            ['conflictos internacionales', 'guerras civiles', ...],
    'demografía y sociedad':    ['sobrepoblación', 'migraciones', ...],
    'economía y corporaciones': ['economía global', 'corporaciones multinacionales', ...],
}
# Si ningún keyword coincide: tema='otros', subtema='general'

Documento MongoDB generado (colección wikipedia)

{
  "_id": ObjectId,
  "archivo": "Guerra_del_Golfo.txt",
  "tema": "guerra global",
  "subtema": "conflictos internacionales",
  "texto": "La Guerra del Golfo fue un conflicto armado...",
  "fecha": null   // Wikipedia no suele tener fecha de publicación clara
}

La inserción usa upsert por archivo para deduplicar.


Almacenamiento en disco (ignorado por git)

FLUJOS_DATOS/WIKIPEDIA/
├── articulos_wikipedia/        # .gitignore — txt en español por artículo
├── articulos_tokenizados/      # .gitignore — IDs BERT por artículo
├── main.py
├── wikipedia_utils.py
└── docs.txt

Ejecución dentro del pipeline maestro

pipeline_maestro.py Fase 1 llama:

/var/www/theflows.net/flujos/FLUJOS_DATOS/myenv/bin/python3 \
    FLUJOS_DATOS/WIKIPEDIA/main.py

Desde el directorio FLUJOS_DATOS/WIKIPEDIA/ para que las rutas relativas (articulos_wikipedia/) funcionen.


Limitaciones conocidas

  1. Sin fecha en artículos Wikipedia — El scraper no extrae la fecha de revisión. El campo fecha queda en null o vacío en Mongo, lo que rompe los filtros de fecha en la API.
  2. Nombres duplicados potenciales — Artículos con títulos similares generan el mismo nombre de fichero después de la limpieza.
  3. No hay control de idioma — Si un keyword es un acrónimo (NSA, CIA), puede devolver artículos en inglés mezclados con los españoles.
  4. Tokenización trunca a 512 tokens — Artículos largos pierden la segunda mitad para el cálculo de similitud.
  5. Sin rate limiting robusta — Solo time.sleep(1) entre keywords, pero la Wikipedia API tiene un límite de 200 req/s por IP (raramente alcanzado).

Dependencias

transformers>=4.45   (BertTokenizer)
tqdm
requests
pymongo

BERT (dccuchile/bert-base-spanish-wwm-cased) se descarga automáticamente en el primer uso (~500 MB, se cachea en ~/.cache/huggingface/).