- 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>
205 lines
7 KiB
Markdown
205 lines
7 KiB
Markdown
# 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.
|
|
|
|
```python
|
|
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
|
|
|
|
```python
|
|
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
|
|
|
|
```python
|
|
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
|
|
|
|
```python
|
|
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.
|
|
|
|
```python
|
|
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`)
|
|
|
|
```json
|
|
{
|
|
"_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:
|
|
```bash
|
|
/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/`).
|