chore: quitar rutas absolutas del codigo

Los scrapers y el analizador de imagenes llevaban cableada la ruta de
despliegue de una maquina concreta. Ahora sale de una variable de entorno y,
si no esta, se deduce de la ubicacion del propio fichero: el repo funciona
donde lo clones sin editar nada.

  FLUJOS_DATOS_DIR    raiz de datos para scrapers y comparacion
  FLUJOS_NOTICIAS_DIR scraper historico de medios
  HF_HOME             cache de modelos de Hugging Face

flujos-pipeline.service pasa a plantilla, igual que las de coconews.
This commit is contained in:
hacklab 2026-08-23 17:12:18 +02:00
parent 710904a1ef
commit e2b1f27699
12 changed files with 175 additions and 6682 deletions

View file

@ -62,7 +62,9 @@ def comparar_carpetas(carpeta1, carpeta2, carpeta_comparaciones, nombre_comparac
f_out.write(f"{nombre_archivo1} vs {nombre_archivo2}: {porcentaje:.2f}% de similitud\n")
# Rutas a las carpetas
ruta_base = './FLUJOS_DATOS'
ruta_base = os.getenv('FLUJOS_DATOS_DIR',
os.path.abspath(os.path.join(os.path.dirname(__file__),
'..', '..', '..')))
carpeta_comparaciones = os.path.join(ruta_base, 'COMPARACIONES')
carpeta_wikipedia = os.path.join(ruta_base, 'WIKIPEDIA', 'articulos_tokenizados')
carpeta_torrents = os.path.join(ruta_base, 'TORRENTS', 'TORRENTS_WIKILEAKS_COMPLETO', 'tokenized')

View file

@ -0,0 +1,109 @@
"""
comparar_imagenes_wiki.py
-------------------------
Genera comparaciones entre imagenes_wiki y docs de texto (wikipedia + noticias + torrents)
y las guarda en la colección 'comparaciones'.
Uso:
cd FLUJOS_DATOS/IMAGENES
python comparar_imagenes_wiki.py
python comparar_imagenes_wiki.py --umbral 3.0 # más permisivo
python comparar_imagenes_wiki.py --tema "cambio climático"
"""
import argparse
from pymongo import MongoClient, UpdateOne
from image_comparator import ImageComparator
MONGO_URL = "mongodb://localhost:27017"
DB_NAME = "FLUJOS_DATOS"
TEMAS = [
"cambio climático",
"guerra global",
"inteligencia y seguridad",
"economía y corporaciones",
"demografía y sociedad",
]
TEXT_COLLECTIONS = ["wikipedia", "noticias", "torrents"]
def run(temas: list[str], umbral: float):
client = MongoClient(MONGO_URL, serverSelectionTimeoutMS=5000)
db = client[DB_NAME]
comp = ImageComparator(threshold=umbral)
total_insertadas = 0
for tema in temas:
print(f"\n{'='*60}")
print(f" Tema: {tema}")
print(f"{'='*60}")
# 1. Imágenes de imagenes_wiki para este tema
img_docs = list(db.imagenes_wiki.find(
{"tema": {"$regex": tema, "$options": "i"}},
{"_id": 0}
))
if not img_docs:
print(f" Sin imágenes para '{tema}' — saltando")
continue
print(f" Imágenes encontradas: {len(img_docs)}")
# 2. Docs de texto para este tema
text_docs = []
for col_name in TEXT_COLLECTIONS:
docs = list(db[col_name].find(
{"tema": {"$regex": tema, "$options": "i"}},
{"_id": 0}
).limit(500))
for d in docs:
d.setdefault("source_type", col_name)
text_docs.extend(docs)
print(f" {col_name}: {len(docs)} docs")
if not text_docs:
print(f" Sin docs de texto para '{tema}' — saltando")
continue
# 3. Comparar
comparaciones = comp.compare_batch(img_docs, text_docs)
print(f" Comparaciones generadas (umbral={umbral}%): {len(comparaciones)}")
if not comparaciones:
continue
# Añadir tema a cada comparación para trazabilidad
for c in comparaciones:
c["tema"] = tema
# 4. Guardar en MongoDB (upsert por par noticia1+noticia2)
ops = [
UpdateOne(
{"noticia1": c["noticia1"], "noticia2": c["noticia2"]},
{"$set": c},
upsert=True
)
for c in comparaciones
]
result = db.comparaciones.bulk_write(ops)
n = result.upserted_count + result.modified_count
total_insertadas += result.upserted_count
print(f" Guardadas: {result.upserted_count} nuevas, {result.modified_count} actualizadas")
client.close()
print(f"\n Total nuevas comparaciones: {total_insertadas}")
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--umbral", type=float, default=3.0,
help="Similitud mínima %% (default: 3.0)")
parser.add_argument("--tema", default=None,
help="Procesar solo un tema")
args = parser.parse_args()
temas = [args.tema] if args.tema else TEMAS
run(temas, args.umbral)

View file

@ -29,7 +29,8 @@ from transformers import Qwen3VLForConditionalGeneration, AutoProcessor, BitsAnd
# ── Configuración ──────────────────────────────────────────────────────────────
MODEL_ID = os.getenv("VISION_MODEL", "Qwen/Qwen3-VL-8B-Instruct")
CACHE_DIR = os.getenv("HF_HOME", "/var/www/theflows.net/flujos/FLUJOS_DATOS/IMAGENES/model_cache")
CACHE_DIR = os.getenv("HF_HOME",
os.path.join(os.path.dirname(os.path.abspath(__file__)), "model_cache"))
SUPPORTED_EXTENSIONS = {".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp"}

View file

@ -57,9 +57,13 @@ class ImageComparator:
val = doc.get(field)
if val and isinstance(val, str):
parts.append(val)
# entidades
# entidades (pueden ser strings o dicts)
if doc.get("entidades"):
parts.extend(doc["entidades"])
for e in doc["entidades"]:
if isinstance(e, str):
parts.append(e)
elif isinstance(e, dict):
parts.extend(str(v) for v in e.values() if v)
return " ".join(parts)
# ── Comparación imagen vs lista de documentos ─────────────────────────────

View file

@ -391,15 +391,10 @@ class WikipediaImageScraper:
# Temas de FLUJOS por defecto
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 algoritmos",
"guerra global",
"inteligencia y seguridad",
"economía y corporaciones",
"demografía y sociedad",
]
if __name__ == "__main__":

View file

@ -151,7 +151,7 @@ clean_text():
7) filtra STOPWORDS (lista extensa ES)
/var/www/theflows.net/flujos/FLUJOS_DATOS/NOTICIAS/
$FLUJOS/FLUJOS_DATOS/NOTICIAS/
├── articulos/ (txt limpios en ES, de páginas HTML/Wayback)
├── archivos/ (descargas crudas: pdf, csv, xlsx, docx, zip, html, md, txt)
├── tokenized/ (mismos nombres, contenido = IDs BERT separados por espacio)
@ -270,7 +270,7 @@ Control y límites
- tqdm, logging, os, re, json, time, csv, hashlib, urllib.parse (urlparse/urljoin) → utilidades
[ ESTRUCTURA DE CARPETAS (I/O) ]
/var/www/theflows.net/flujos/FLUJOS_DATOS/NOTICIAS/
$FLUJOS/FLUJOS_DATOS/NOTICIAS/
├── articulos/ (TXT limpios en español, derivados de HTML/Wayback)
├── archivos/ (descargas crudas: .pdf .csv .txt .xlsx .docx .html .md .zip)
├── tokenized/ (TXT con IDs de tokens BERT, máx 512 tokens por archivo)

View file

@ -1,5 +1,4 @@
from deep_translator import GoogleTranslator
from deep_translator import GoogleTranslator
import os
import re
import hashlib
@ -7,7 +6,6 @@ import requests
import json
import time
import logging
from requests_html import HTMLSession
from bs4 import BeautifulSoup
from PyPDF2 import PdfReader
import csv
@ -68,11 +66,14 @@ def clean_text(text):
Limpia el texto eliminando bloques CDATA (incluso con espacios extra),
luego HTML, puntuación y stopwords.
"""
# 1) Eliminar cualquier variante de CDATA (p. ej. '<![ CDATA [ ... ]]>')
text = re.sub(r'<\!\[\s*CDATA\s*\[.*?\]\]>', '', text, flags=re.S)
# 1) Eliminar cualquier variante de CDATA/marked sections malformadas
text = re.sub(r'<!\[.*?\]>', '', text, flags=re.S)
# 2) Parsear HTML
soup = BeautifulSoup(text, 'html.parser')
# 2) Parsear HTML (lxml es más tolerante con HTML malformado)
try:
soup = BeautifulSoup(text, 'lxml')
except Exception:
soup = BeautifulSoup(text, 'html.parser')
text = soup.get_text(separator=" ")
# 3) Minúsculas
@ -436,11 +437,21 @@ def explore_and_extract_articles(url, articles_folder, files_folder, processed_u
logging.info(f"Explorando {url} en profundidad {depth}...")
try:
session = HTMLSession()
response = session.get(url, timeout=30)
response.html.render(timeout=30, sleep=1)
links = response.html.absolute_links
session.close()
headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/120 Safari/537.36"}
response = requests.get(url, timeout=30, headers=headers)
response.raise_for_status()
soup = BeautifulSoup(response.text, "html.parser")
base = url.rstrip("/")
raw_links = set()
for tag in soup.find_all("a", href=True):
href = tag["href"].strip()
if href.startswith("http"):
raw_links.add(href)
elif href.startswith("/"):
from urllib.parse import urlparse as _up
parsed = _up(url)
raw_links.add(f"{parsed.scheme}://{parsed.netloc}{href}")
links = raw_links
except Exception as e:
logging.error(f"Error al acceder a {url}: {e}")
return
@ -587,7 +598,9 @@ def main():
'https://www.spectator.co.uk/'
]
base_folder = '/var/www/theflows.net/flujos/FLUJOS_DATOS/NOTICIAS'
# Por defecto, el directorio donde vive este script
base_folder = os.getenv('FLUJOS_NOTICIAS_DIR',
os.path.dirname(os.path.abspath(__file__)))
articles_folder = os.path.join(base_folder, 'articulos')
files_folder = os.path.join(base_folder, 'archivos')
tokenized_folder = os.path.join(base_folder, 'tokenized')

View file

@ -1,945 +1 @@
empresa
brasileña
investigación
agropec
##uar
##ia
emb
##ra
##pa
empresa
brasile
##ira
pes
##quis
##a
agropec
##u
##ár
##ia
institución
estatal
federal
pública
brasileña
vinculada
ministerio
agricultura
ganadería
abastecimiento
bras
##il
fundada
26
abril
19
##7
##3
cuyos
objetivos
desarrollar
tecnologías
conocimiento
informaciones
técnicas
científicas
agricultura
ganadería
brasileña
tiene
misión
crear
soluciones
investigación
desarrollo
innovación
sostenibilidad
agricultura
beneficio
sociedad
brasileña
actúa
sistema
compuesto
41
centros
investigación
cinco
unidades
servicios
1
##7
unidades
centrales
presente
casi
federación
9
##7
##90
empleados
cuales
244
##4
investigadores
actúa
coordinación
sistema
nacional
investigación
agropec
##uar
##ia
s
##n
##pa
constituido
instituciones
públicas
federales
universidades
empresas
privadas
fundaciones
forma
cooperativa
ejecutan
##do
investigaciones
diferentes
áreas
geográficas
campos
conocimiento
científico
em
términos
cooperación
internacional
empresa
mantiene
68
acuerdos
bilaterales
cooperación
técnica
3
##7
países
64
instituciones
acuerdos
multilaterales
20
organizaciones
internacionales
principalmente
estudios
parcelas
mantiene
laboratorios
desarrollar
estudios
tecnología
punta
unidos
fran
##cia
países
bajos
oficina
regional
g
##han
##a
compartir
conocimiento
científico
tecnológico
continente
africano
asociados
emb
##ra
##pa
empresas
asociadas
emb
##ra
##pa
empresas
asociadas
emb
##ra
##pa
pueden
reproducir
semillas
derivados
partir
momento
cumplan
requisitos
técnicos
establecidos
organización
unidades
emb
##ra
##pa
centros
investigación
productos
emb
##ra
##pa
[UNK]
camp
##ina
grande
p
##b
investigación
algodón
mam
##ona
ame
##n
##do
##im
ger
##gel
##im
si
##sal
emb
##ra
##pa
arroz
por
##oto
santo
[UNK]
go
##i
##ás
go
investigación
arroz
por
##oto
emb
##ra
##pa
cap
##rino
##s
sobra
##l
ce
investigación
cap
##rino
##s
ov
##inos
emb
##ra
##pa
fores
##tas
colo
##mbo
pr
investigación
especies
forestales
emb
##ra
##pa
ga
##do
corte
campo
grande
ms
investigación
bo
##vinos
corte
emb
##ra
##pa
ganado
leche
ju
##iz
for
##a
mg
investigación
leche
bo
##vinos
leche
emb
##ra
##pa
hortalizas
distrito
federal
d
##f
investigación
hortalizas
ab
##ó
##bora
bata
##ta
bata
##tad
##ul
##ce
ber
##en
##jen
##a
cebol
##la
zana
##hor
##ia
cole
##s
gui
##santes
gar
##ban
##zo
lente
##ja
mand
##io
##ca
mel
##ón
maíz
dulce
mos
##taza
pe
##pino
repo
##llo
tomate
etc
emb
##ra
##pa
mand
##io
##ca
fru
##tic
##ult
##ura
tropical
cruz
das
almas
ba
emb
##ra
##pa
mil
##ho
sor
##go
set
##e
lago
##as
mg
investigación
maíz
sor
##go
mi
##jo
emb
##ra
##pa
pecu
##ár
##ia
sudeste
[UNK]
car
##los
sp
investigación
bo
##vinos
corte
bo
##vinos
leche
equi
##nos
forra
##ji
##cultura
emb
##ra
##pa
pecu
##ár
##ia
sul
ba
##gé
r
##s
investigación
bo
##vinos
corte
bo
##vinos
leche
ov
##inos
emb
##ra
##pa
soja
lon
##dri
##na
pr
investigación
soja
giras
##ol
emb
##ra
##pa
su
##ín
##os
aves
con
##có
##r
##dia
s
##c
investigación
su
##inos
pastos
corte
gallinas
postura
emb
##ra
##pa
trigo
pas
##so
fund
##o
r
##s
investigación
trigo
ce
##bada
tri
##tica
##le
centen
##o
can
##ola
hierbas
forra
##jeras
soja
maíz
por
##oto
desarrollo
soja
adaptada
suelos
ácidos
emb
##ra
##pa
uva
vin
##ho
ben
##to
[UNK]
r
##s
investigación
uva
vino
manzana
frutas
clima
temp
##lado
centros
investigación
temas
básicos
emb
##ra
##pa
agro
##bio
##logia
ser
##op
##é
##dica
r
##j
investigación
fijación
biológica
nitrógeno
agricultura
orgánica
emb
##ra
##pa
agro
##ener
##gia
bras
##íl
##ia
d
##f
investigación
biodi
##és
##el
bio
##gá
##s
eta
##nol
fores
##tas
energéticas
emb
##ra
##pa
agro
##ind
##ús
##tri
##a
alimentos
río
ja
##ne
##iro
r
##j
investigación
tecnología
alimentos
emb
##ra
##pa
agro
##ind
##ús
##tri
##a
tropical
fortaleza
ce
investigación
agro
##ind
##ust
##ria
tropical
ca
##ju
coco
emb
##ra
##pa
informática
agropec
##u
##ár
##ia
camp
##inas
sp
investigación
tecnología
información
agro
##ne
##goci
##os
emb
##ra
##pa
[UNK]
agropec
##u
##ár
##ia
[UNK]
car
##los
sp
investigación
agricultura
precisión
ambiente
biotecnología
##a
automa
##tización
procesos
nuevos
materiales
agricultura
agro
##ind
##ust
##ria
familiar
calidad
##es
productos
materias
primas
emb
##ra
##pa
me
##io
ambiente
ja
##guar
##i
##ún
##a
sp
investigación
manejo
gestión
ambiental
emb
##ra
##pa
monitor
##amento
satélite
camp
##inas
sp
investigación
sistemas
informaciones
geográficas
redes
ele
##trón
##icas
adquisición
procesamiento
imágenes
sensores
remoto
##s
datos
obtenidos
campo
emb
##ra
##pa
recursos
genéticos
bio
##tec
##nol
##o
##gia
bras
##íl
##ia
d
##f
investigación
biotecnología
control
biológico
recursos
genéticos
seguridad
biológica
emb
##ra
##pa
solos
río
ja
##ne
##iro
r
##j
investigación
suelo
interacciones
ambiente
centros
investigación
eco
##r
##re
##gional
##es
emb
##ra
##pa
acre
rio
bran
##co
ac
emb
##ra
##pa
agropec
##u
##ár
##ia
oeste
do
##urado
##s
ms
investigación
región
oeste
bras
##il
emb
##ra
##pa
ama
##pá
ma
##cap
##á
ap
emb
##ra
##pa
[UNK]
oc
##identa
##l
man
##au
##s
am
investigación
ama
##zona
##s
frutas
tropicales
[UNK]
seri
##ng
##ue
##ira
especies
forestales
guar
##aná
pis
##cic
##ult
##ura
emb
##ra
##pa
[UNK]
oriental
bel
##ém
pa
investigación
región
ama
##zon
##ia
oriental
emb
##ra
##pa
cerrados
plana
##lti
##na
d
##f
investigación
desarrollo
innovación
tecnológica
agricultura
biom
##a
cerrado
emb
##ra
##pa
clima
tempera
##do
pelotas
r
##s
investigación
región
clima
temp
##lado
bras
##il
desarrolla
actividades
áreas
recursos
naturales
ambiente
granos
fru
##tic
##ult
##ura
oler
##áceas
sistemas
pecu
##arios
énfasis
ganadería
agricultura
base
familiar
emb
##ra
##pa
me
##ion
##orte
ter
##es
##ina
pi
emb
##ra
##pa
pan
##tana
##l
cor
##um
##b
##á
ms
emb
##ra
##pa
[UNK]
por
##to
vel
##ho
ro
emb
##ra
##pa
ro
##ra
##ima
bo
##a
vista
r
##r
emb
##ra
##pa
semi
##ár
##ido
petrol
##ina
pe
emb
##ra
##pa
tab
##ule
##iro
##s
coste
##iro
##s
ara
##ca
##ju
enlaces
externos
página
oficial
emb
##ra
##pa
##en
inglés
portugués
canal
oficial
emb
##ra
##pa
you
##tu
##be
inglés
portugués
base
datos
investigación
agropec
##uar
##ia
empresas
cre
##dencia
##das
emb
##ra
##pa
4 8086 6851 24595 1331 30941 1115 977 11083 11393 8361 30973 6839 1924 5648 2264 8056 29277 2835 1827 11472 3643 29277 2835 1827 1790 5975 4191 24595 3504 2421 22026 2522 5512 3398 6150 4636 7567 8362 29277 2835 1827 2784 15965 3548 3166 4909 7503 5424 2264 6104 2264 11665 2264 1924 2888 8105 30934 10691 1924 3219 4379 8878 6851 10823 3976 2264 11237 1924 4272 4357 3120 4123 2264 11665 7930 3976 6676 2686 2718 7572 8056 2264 5059 5206 4488 21013 4409 17457 1858 1863 2233 1499 2400 23975 14563 12464 6596 6826 8126 18501 8203 5000 8086 8086 11664 2847 9125 3503 3756 2283 8165 2564 12203 18250 5218 17180 20056 1699 7279 2197 1849 2881 9096 2296 29277 19267 2716 8252 10242 5840 29277 19267 2716 1924 18785 979 4166 2287 1858 9997 2264 29277 19267 2716 29857 2881 9096 29277 19267 2716 8252 10511 3287 10242 8056 2881 9096 8512 29277 2835 1827 3319 981 1838 1678 979 4166 19216 30950 979 4166 3120 6552 5436 1924 3350 5824 5927 8512 3255 7503 3385 21700 6428 29277 2835 1827 3385 1092 21700 2822 6796 3385 1016 21700 10072 4496 5424 5873 24595 1331 30941 1115 977 5486 14213 6553 1020 9445 30937 2264 1924 2264 17131 17683 14032 1045 4640 5269 979 979 979 3837 1024 9445 1957 24362 20026 30988 977 30993 24241 30943 30938 1045 4640 5269 28078 3246 1053 2035 1130 979 9561 5788 3126 1299 1420 30936 1239 3837 1331 30941 30973 977 11083 30973 20335 13861 5950 3313 24362 2086 26042 24447 4783 1109 1045 4640 5269 979 979 979 3837 1024 1123 30946 2035 20068 1997 30940 6696 30933 1331 30941 30973 977 11083 30973 1493 30967 30949 30967 1014 1045 4640 5269 979 979 979 4108 981 12193 30935 3396 3858 1150 22012 14876 1023 26042 24447 4783 1109 1150 1634 23072 1650 1331 30941 3197 30935 30935 1502 4099 15000 3855 1159 5

File diff suppressed because it is too large Load diff

View file

@ -242,6 +242,20 @@ def fase_scraping(db, forzar: bool = False):
if not ok_img:
ok = False
# 1d. Comparaciones imagen-texto (imagenes_wiki vs corpus)
log.info("\n[1d] Comparaciones imagen-texto")
antes_comp = db["comparaciones"].count_documents({"source1_type": "imagen"})
ok_comp = run_script(
imagenes_dir / "comparar_imagenes_wiki.py",
args=["--umbral", "3.0"],
cwd=imagenes_dir,
)
despues_comp = db["comparaciones"].count_documents({"source1_type": "imagen"})
stats["comparaciones_imagen_nuevas"] = despues_comp - antes_comp
log.info(f" Comparaciones imagen: +{stats['comparaciones_imagen_nuevas']} nuevas")
if not ok_comp:
ok = False
except Exception as e:
log.error(f" ERROR en fase scraping: {e}")
ok = False

View file

@ -5,15 +5,15 @@ Requires=mongod.service
[Service]
Type=oneshot
User=capitansito
WorkingDirectory=/var/www/theflows.net/flujos/FLUJOS_DATOS
User=__USER__
WorkingDirectory=__INSTALL_DIR__/FLUJOS_DATOS
Environment=MONGO_URL=mongodb://localhost:27017
Environment=DB_NAME=FLUJOS_DATOS
Environment=HF_HOME=/var/www/theflows.net/flujos/FLUJOS_DATOS/IMAGENES/model_cache
Environment=HF_HOME=__INSTALL_DIR__/FLUJOS_DATOS/IMAGENES/model_cache
ExecStart=/var/www/theflows.net/flujos/FLUJOS_DATOS/myenv/bin/python3 \
/var/www/theflows.net/flujos/FLUJOS_DATOS/pipeline_maestro.py
ExecStart=__INSTALL_DIR__/FLUJOS_DATOS/myenv/bin/python3 \
__INSTALL_DIR__/FLUJOS_DATOS/pipeline_maestro.py
# 12h máximo (análisis VLM en CPU puede tardar)
TimeoutStartSec=43200

View file

@ -1,10 +1,10 @@
[Unit]
Description=Ejecutar FLUJOS Pipeline cada semana (domingo 3am)
Description=Ejecutar FLUJOS Pipeline cada 12 horas
Requires=flujos-pipeline.service
[Timer]
# Todos los domingos a las 03:00
OnCalendar=Sun *-*-* 03:00:00
# Cada 12 horas: a las 00:00 y 12:00
OnCalendar=*-*-* 00,12:00:00
# Si el servidor estaba apagado a las 3am, ejecutar al arrancar
Persistent=true