feat: motor de correlacion semantica
Reemplaza el solape de palabras por similitud coseno sobre embeddings. La comparacion vieja cruzaba todos los documentos contra todos contando palabras comunes, stopwords incluidas: O(n*m) y mucho falso positivo. El motor nuevo compara noticia contra corpus de leaks en el espacio vectorial, reduce de fragmento a documento por maximo, y penaliza los documentos hub: score = cos - lambda*ln(1+grado). Sin esa penalizacion, los documentos catch-all (cables largos, buzones de correo enteros) salen emparejados con casi cualquier noticia. Escribe en una coleccion aparte, asi que se puede regenerar sin dejar el grafo a oscuras. Acepta --dry-run para calibrar umbrales antes de escribir.
This commit is contained in:
parent
6de1b6de02
commit
91e6c11a08
4 changed files with 335 additions and 17 deletions
66
FLUJOS_DATOS/COMPARACIONES/inspeccionar_pares.py
Normal file
66
FLUJOS_DATOS/COMPARACIONES/inspeccionar_pares.py
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Muestrea pares noticia↔leak en bandas de coseno y vuelca su texto a JSON,
|
||||
para evaluar la calidad del matching y calibrar el umbral. Solo lectura."""
|
||||
import json, os, sys
|
||||
import numpy as np
|
||||
from pymongo import MongoClient
|
||||
|
||||
db = MongoClient("mongodb://localhost:27017", serverSelectionTimeoutMS=4000)["FLUJOS_DATOS"]
|
||||
|
||||
# --- noticias con embedding (query) ---
|
||||
news = list(db.noticias.find(
|
||||
{"embedding": {"$exists": True}, "apto_embedding": {"$ne": False}},
|
||||
{"archivo": 1, "embedding": 1, "titulo_original": 1, "texto": 1, "fecha": 1}))
|
||||
# muestra de noticias para no cargar las 21k (determinista: primeras 3000)
|
||||
news = news[:3000]
|
||||
Qarch = [n["archivo"] for n in news]
|
||||
Q = np.asarray([n["embedding"] for n in news], dtype=np.float32)
|
||||
Q /= np.clip(np.linalg.norm(Q, axis=1, keepdims=True), 1e-9, None)
|
||||
|
||||
# --- chunks de leaks (corpus) ---
|
||||
ch = list(db.embeddings_chunks.find({"coleccion": "torrents"}, {"archivo": 1, "embedding": 1}))
|
||||
C = np.asarray([c["embedding"] for c in ch], dtype=np.float32)
|
||||
C /= np.clip(np.linalg.norm(C, axis=1, keepdims=True), 1e-9, None)
|
||||
leak_of = [c["archivo"] for c in ch]
|
||||
uniq, idx = {}, np.empty(len(ch), dtype=np.int64)
|
||||
names = []
|
||||
for i, a in enumerate(leak_of):
|
||||
j = uniq.setdefault(a, len(names))
|
||||
if j == len(names): names.append(a)
|
||||
idx[i] = j
|
||||
nL = len(names)
|
||||
print(f"news={len(Q)} corpus_chunks={len(C)} leaks={nL}", file=sys.stderr)
|
||||
|
||||
# top-1 leak por noticia (doc-level max) → recolectar (cos, news_i, leak_j)
|
||||
pares = []
|
||||
Ct = np.ascontiguousarray(C.T)
|
||||
for b in range(0, len(Q), 256):
|
||||
S = Q[b:b+256] @ Ct
|
||||
for r in range(S.shape[0]):
|
||||
dm = np.full(nL, -1.0, np.float32)
|
||||
np.maximum.at(dm, idx, S[r])
|
||||
j = int(dm.argmax())
|
||||
pares.append((float(dm[j]), b+r, j))
|
||||
|
||||
# bandas de coseno; muestrear hasta 10 por banda
|
||||
bandas = [(0.40,0.45),(0.45,0.50),(0.50,0.55),(0.55,0.60),(0.60,0.65),(0.65,0.70),(0.70,1.01)]
|
||||
muestras = []
|
||||
for lo, hi in bandas:
|
||||
enb = [p for p in pares if lo <= p[0] < hi]
|
||||
enb.sort(key=lambda x: -x[0])
|
||||
paso = max(1, len(enb)//10)
|
||||
for cos, ni, lj in enb[::paso][:10]:
|
||||
n = news[ni]
|
||||
leak = db.torrents.find_one({"archivo": names[lj]}, {"texto": 1, "archivo": 1, "tema": 1})
|
||||
muestras.append({
|
||||
"banda": f"{lo:.2f}-{hi:.2f}", "cosine": round(cos, 3),
|
||||
"noticia_titulo": (n.get("titulo_original") or "")[:200],
|
||||
"noticia_texto": (n.get("texto") or "")[:600],
|
||||
"leak_archivo": names[lj],
|
||||
"leak_texto": ((leak or {}).get("texto") or "")[:600],
|
||||
})
|
||||
json.dump(muestras, open("/tmp/flujos_pares.json", "w"), ensure_ascii=False, indent=1)
|
||||
print(f"{len(muestras)} pares volcados a /tmp/flujos_pares.json", file=sys.stderr)
|
||||
# resumen por banda
|
||||
from collections import Counter
|
||||
print("por banda:", dict(Counter(m["banda"] for m in muestras)), file=sys.stderr)
|
||||
237
FLUJOS_DATOS/COMPARACIONES/motor_comparacion.py
Normal file
237
FLUJOS_DATOS/COMPARACIONES/motor_comparacion.py
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
motor_comparacion.py — motor de correlación semántica
|
||||
=======================================================
|
||||
Reemplaza el solape-de-palabras (pipeline_completo.py) por SIMILITUD SEMÁNTICA
|
||||
sobre embeddings MiniLM ya calculados (ver backfill_embeddings.py).
|
||||
|
||||
Cómo funciona:
|
||||
- QUERY = noticias con `embedding` (coconews/rss; se preservan los existentes).
|
||||
- CORPUS = chunks de leaks/wiki desde `embeddings_chunks` (recall por fragmento).
|
||||
Si no hay chunks para una colección, cae a `embedding` a nivel doc.
|
||||
- Para cada noticia: coseno contra todo el corpus, reducido a nivel-documento
|
||||
por MAX de chunks.
|
||||
- PENALIZACIÓN DE HUB: los documentos "catch-all" (viewer
|
||||
de cablegate, emails genéricos...) caen cerca del centroide y matchean con todo
|
||||
→ el 39% de los falsos positivos. Se mitiga con:
|
||||
· drop duro de hubs extremos (grado > --max-grado-frac · nº_noticias)
|
||||
· ranking por score = cos − λ·ln(1+grado) (los hubs moderados bajan en el top-k)
|
||||
El GATE de creación de arista sigue siendo el coseno crudo (--umbral 0.55,
|
||||
calibrado con panel de jueces), para no descalibrar las aristas legítimas.
|
||||
|
||||
NO DESTRUCTIVO: nunca escribe en `comparaciones`. Salida = colección nueva.
|
||||
|
||||
Calibración (no escribe):
|
||||
/usr/bin/python3 motor_comparacion.py --dry-run
|
||||
Generación real:
|
||||
/usr/bin/python3 motor_comparacion.py --umbral 0.55 --salida comparaciones_v2
|
||||
"""
|
||||
import argparse
|
||||
import logging
|
||||
import math
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
from collections import Counter, defaultdict
|
||||
|
||||
MONGO_URL = os.getenv("MONGO_URL", "mongodb://localhost:27017")
|
||||
DB_NAME = os.getenv("DB_NAME", "FLUJOS_DATOS")
|
||||
CHUNKS_COL = os.getenv("CHUNKS_COL", "embeddings_chunks")
|
||||
MODEL_NAME = os.getenv("EMBEDDER_MODEL", "paraphrase-multilingual-MiniLM-L12-v2")
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s [motor] %(message)s")
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def conectar():
|
||||
from pymongo import MongoClient
|
||||
from pymongo.errors import ServerSelectionTimeoutError
|
||||
cli = MongoClient(MONGO_URL, serverSelectionTimeoutMS=4000)
|
||||
try:
|
||||
cli.admin.command("ping")
|
||||
except ServerSelectionTimeoutError:
|
||||
log.error("MongoDB no responde en %s — ¿está mongod arriba? Aborto sin tocar nada.", MONGO_URL)
|
||||
sys.exit(2)
|
||||
return cli[DB_NAME]
|
||||
|
||||
|
||||
def cargar_matriz(db, colecciones, query_side=False, limit=0):
|
||||
"""Devuelve (vectores np.float32 [N,384] L2-normalizados, archivos[N])."""
|
||||
import numpy as np
|
||||
vecs, archivos = [], []
|
||||
if query_side:
|
||||
cur = db.noticias.find(
|
||||
{"embedding": {"$exists": True}, "apto_embedding": {"$ne": False}},
|
||||
{"archivo": 1, "embedding": 1})
|
||||
if limit:
|
||||
cur = cur.limit(limit)
|
||||
for d in cur:
|
||||
e = d.get("embedding")
|
||||
if e and d.get("archivo"):
|
||||
vecs.append(e); archivos.append(d["archivo"].strip())
|
||||
else:
|
||||
ch = db[CHUNKS_COL]
|
||||
for d in ch.find({"coleccion": {"$in": colecciones}}, {"archivo": 1, "embedding": 1}):
|
||||
e = d.get("embedding")
|
||||
if e and d.get("archivo"):
|
||||
vecs.append(e); archivos.append(d["archivo"].strip())
|
||||
if not vecs: # fallback: sin chunks → embedding a nivel doc
|
||||
log.warning("Sin chunks en '%s' para %s; usando embedding a nivel documento.",
|
||||
CHUNKS_COL, colecciones)
|
||||
for c in colecciones:
|
||||
for d in db[c].find({"embedding": {"$exists": True}, "apto_embedding": {"$ne": False}},
|
||||
{"archivo": 1, "embedding": 1}):
|
||||
e = d.get("embedding")
|
||||
if e and d.get("archivo"):
|
||||
vecs.append(e); archivos.append(d["archivo"].strip())
|
||||
if not vecs:
|
||||
return np.zeros((0, 384), dtype=np.float32), []
|
||||
M = np.asarray(vecs, dtype=np.float32)
|
||||
norms = np.linalg.norm(M, axis=1, keepdims=True)
|
||||
norms[norms == 0] = 1.0
|
||||
return M / norms, archivos
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(description="Motor de comparación semántica (embeddings + anti-hub)")
|
||||
ap.add_argument("--query", default="noticias")
|
||||
ap.add_argument("--corpus", default="torrents",
|
||||
help="colecciones corpus separadas por coma, p.ej. torrents,wikipedia")
|
||||
ap.add_argument("--topk", type=int, default=15, help="leaks por noticia (el front capa a 8)")
|
||||
ap.add_argument("--umbral", type=float, default=0.52,
|
||||
help="GATE principal: score penalizado mínimo (score = cos − λ·ln(1+grado))")
|
||||
ap.add_argument("--min-cos", type=float, default=0.50, dest="min_cos",
|
||||
help="suelo duro de coseno crudo (descarta la banda tóxica 0.45-0.50)")
|
||||
ap.add_argument("--prefiltro", type=float, default=0.50,
|
||||
help="coseno mínimo para contar como candidato y computar el grado de hub")
|
||||
ap.add_argument("--lambda-hub", type=float, default=0.02, dest="lambda_hub",
|
||||
help="penalización de hub: score = cos − λ·ln(1+grado)")
|
||||
ap.add_argument("--max-grado-frac", type=float, default=0.10, dest="max_grado_frac",
|
||||
help="drop duro de seguridad: descartar leaks que tocan > esta fracción de noticias")
|
||||
ap.add_argument("--marca-evento", type=float, default=0.68, dest="marca_evento",
|
||||
help="coseno a partir del cual se marca posible_evento=true")
|
||||
ap.add_argument("--salida", default="comparaciones_v2")
|
||||
ap.add_argument("--limit-query", type=int, default=0)
|
||||
ap.add_argument("--block", type=int, default=256)
|
||||
ap.add_argument("--dry-run", action="store_true", help="histograma + hubs, NO escribe")
|
||||
args = ap.parse_args()
|
||||
corpus = [c.strip() for c in args.corpus.split(",") if c.strip()]
|
||||
|
||||
if args.salida == "comparaciones":
|
||||
log.error("Negado: --salida no puede ser 'comparaciones' (se preserva intacta). Usa comparaciones_v2.")
|
||||
sys.exit(1)
|
||||
|
||||
import numpy as np
|
||||
db = conectar()
|
||||
|
||||
log.info("Cargando QUERY (%s)…", args.query)
|
||||
Q, q_arch = cargar_matriz(db, [args.query], query_side=True, limit=args.limit_query)
|
||||
log.info("Cargando CORPUS (%s)…", corpus)
|
||||
C, c_arch = cargar_matriz(db, corpus, query_side=False)
|
||||
log.info("QUERY=%d vectores · CORPUS=%d vectores (dim=%d)", len(Q), len(C), Q.shape[1] if len(Q) else 0)
|
||||
if len(Q) == 0 or len(C) == 0:
|
||||
log.error("Faltan embeddings. Corre antes backfill_embeddings.py. Aborto.")
|
||||
sys.exit(3)
|
||||
|
||||
# chunk → documento-leak
|
||||
uniq, leak_names = {}, []
|
||||
c_leak_idx = np.empty(len(c_arch), dtype=np.int64)
|
||||
for i, a in enumerate(c_arch):
|
||||
j = uniq.get(a)
|
||||
if j is None:
|
||||
j = len(leak_names); uniq[a] = j; leak_names.append(a)
|
||||
c_leak_idx[i] = j
|
||||
n_leaks, n_news = len(leak_names), len(Q)
|
||||
log.info("Corpus colapsa a %d documentos-leak distintos.", n_leaks)
|
||||
|
||||
Ct = np.ascontiguousarray(C.T)
|
||||
t0 = time.time()
|
||||
|
||||
# ---- PASE 1: candidatos (noticia, leak, coseno) ≥ prefiltro ----
|
||||
cand_news, cand_leak, cand_cos = [], [], []
|
||||
for b in range(0, n_news, args.block):
|
||||
scores = Q[b:b + args.block] @ Ct
|
||||
for r in range(scores.shape[0]):
|
||||
doc_max = np.full(n_leaks, -1.0, dtype=np.float32)
|
||||
np.maximum.at(doc_max, c_leak_idx, scores[r]) # reducción chunk→doc por MAX
|
||||
for j in np.where(doc_max >= args.prefiltro)[0]:
|
||||
cand_news.append(b + r); cand_leak.append(int(j)); cand_cos.append(float(doc_max[j]))
|
||||
if (b // args.block) % 20 == 0:
|
||||
log.info("… pase1 %d/%d noticias (%d candidatos) — %.0fs",
|
||||
min(b + args.block, n_news), n_news, len(cand_cos), time.time() - t0)
|
||||
log.info("Pase 1: %d candidatos ≥ %.2f.", len(cand_cos), args.prefiltro)
|
||||
|
||||
# ---- grado de hub de cada leak ----
|
||||
grado = Counter(cand_leak)
|
||||
max_grado = args.max_grado_frac * n_news
|
||||
hubs_duros = {j for j, g in grado.items() if g > max_grado}
|
||||
if hubs_duros:
|
||||
ej = ", ".join(leak_names[j][:45] for j in sorted(hubs_duros, key=lambda j: -grado[j])[:3])
|
||||
log.info("Hubs duros descartados (grado > %.0f = %.0f%% noticias): %d leaks. Top: %s",
|
||||
max_grado, args.max_grado_frac * 100, len(hubs_duros), ej)
|
||||
|
||||
# ---- PASE 2: ranking penalizado por noticia, GATE por coseno crudo ----
|
||||
por_news = defaultdict(list) # ni -> [(score_pen, lj, cos)]
|
||||
for ni, lj, cos in zip(cand_news, cand_leak, cand_cos):
|
||||
if lj in hubs_duros:
|
||||
continue
|
||||
score = cos - args.lambda_hub * math.log1p(grado[lj])
|
||||
por_news[ni].append((score, lj, cos))
|
||||
|
||||
edges, todos_cos, todos_score = [], [], []
|
||||
for ni, lst in por_news.items():
|
||||
lst.sort(reverse=True) # ranking por score penalizado
|
||||
for score, lj, cos in lst[:args.topk]:
|
||||
todos_cos.append(cos); todos_score.append(score)
|
||||
if score >= args.umbral and cos >= args.min_cos: # gate hub-aware + suelo de coseno
|
||||
edges.append((q_arch[ni], leak_names[lj], score, cos, grado[lj]))
|
||||
log.info("Generadas %d aristas (gate score≥%.2f, cos≥%.2f, λ_hub=%.3f) en %.0fs.",
|
||||
len(edges), args.umbral, args.min_cos, args.lambda_hub, time.time() - t0)
|
||||
|
||||
if args.dry_run:
|
||||
cos = np.asarray(todos_cos) if todos_cos else np.zeros(0)
|
||||
sco = np.asarray(todos_score) if todos_score else np.zeros(0)
|
||||
log.info("=== DRY-RUN (top-%d/noticia, %d valores) ===", args.topk, len(cos))
|
||||
log.info(" -- coseno crudo --")
|
||||
for lo in [0.50, 0.55, 0.60, 0.65, 0.68, 0.70]:
|
||||
log.info(" cos ≥ %.2f : %d", lo, int((cos >= lo).sum()) if len(cos) else 0)
|
||||
log.info(" -- score penalizado (gate real) --")
|
||||
for lo in [0.50, 0.52, 0.55, 0.60, 0.65]:
|
||||
log.info(" score ≥ %.2f : %d", lo, int((sco >= lo).sum()) if len(sco) else 0)
|
||||
if len(cos):
|
||||
log.info(" cos p50=%.3f p90=%.3f | score p50=%.3f p90=%.3f",
|
||||
float(np.percentile(cos, 50)), float(np.percentile(cos, 90)),
|
||||
float(np.percentile(sco, 50)), float(np.percentile(sco, 90)))
|
||||
top_hubs = sorted(grado.items(), key=lambda kv: -kv[1])[:10]
|
||||
log.info(" leaks-hub por grado (sobre %d noticias):", n_news)
|
||||
for j, g in top_hubs:
|
||||
log.info(" grado=%-5d %s", g, leak_names[j][:70])
|
||||
log.info("No se escribió nada (--dry-run). Elige --umbral/--max-grado-frac y relanza sin --dry-run.")
|
||||
return
|
||||
|
||||
# ---- escritura NO destructiva ----
|
||||
from pymongo import UpdateOne
|
||||
out = db[args.salida]
|
||||
ops = []
|
||||
for a, bk, score, cos, g in edges:
|
||||
n1, n2 = sorted((a, bk)) # orden canónico min/max
|
||||
ops.append(UpdateOne(
|
||||
{"noticia1": n1, "noticia2": n2},
|
||||
{"$set": {"noticia1": n1, "noticia2": n2,
|
||||
"porcentaje_similitud": round(score * 100, 2), # ranking de-hubbeado para el front
|
||||
"cosine": round(cos, 4), "score": round(score, 4),
|
||||
"grado_leak": g, "posible_evento": bool(cos >= args.marca_evento),
|
||||
"metodo": "embedding", "modelo": MODEL_NAME}},
|
||||
upsert=True))
|
||||
for i in range(0, len(ops), 2000):
|
||||
out.bulk_write(ops[i:i + 2000], ordered=False)
|
||||
out.create_index([("noticia1", 1), ("noticia2", 1)], unique=True, name="par_unico")
|
||||
out.create_index([("porcentaje_similitud", -1)], name="sim_desc")
|
||||
n_ev = sum(1 for e in edges if e[3] >= args.marca_evento)
|
||||
log.info("✅ Escritas %d aristas en '%s' (%d marcadas posible_evento ≥%.2f). 'comparaciones' intacta.",
|
||||
len(ops), args.salida, n_ev, args.marca_evento)
|
||||
log.info("Activar en front: COMPARACIONES_COL=%s + repuntar la línea de FLUJOS_APP.js.", args.salida)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -12,6 +12,12 @@ import string
|
|||
import nltk
|
||||
from nltk.corpus import stopwords
|
||||
|
||||
# Raiz de FLUJOS_DATOS. Por defecto se deduce de la ubicacion de este fichero,
|
||||
# asi el repo funciona en cualquier maquina sin editar nada.
|
||||
DATOS_DIR = os.getenv('FLUJOS_DATOS_DIR',
|
||||
os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
||||
|
||||
|
||||
# Descargar stopwords la primera vez
|
||||
nltk.download('stopwords')
|
||||
stop_words = set(stopwords.words('spanish'))
|
||||
|
|
@ -222,23 +228,26 @@ def main():
|
|||
|
||||
try:
|
||||
# Rutas absolutas de los archivos en formato txt
|
||||
carpeta_noticias_txt = '/var/www/theflows.net/flujos/FLUJOS_DATOS/NOTICIAS/articulos'
|
||||
carpeta_wikipedia_txt = '/var/www/theflows.net/flujos/FLUJOS_DATOS/WIKIPEDIA/articulos_wikipedia'
|
||||
carpeta_torrents_txt = '/var/www/theflows.net/flujos/FLUJOS_DATOS/TORRENTS/TORRENTS_WIKILEAKS_COMPLETO/txt'
|
||||
carpeta_noticias_txt = os.path.join(DATOS_DIR, 'NOTICIAS', 'articulos')
|
||||
carpeta_wikipedia_txt = os.path.join(DATOS_DIR, 'WIKIPEDIA', 'articulos_wikipedia')
|
||||
carpeta_torrents_txt = os.path.join(DATOS_DIR, 'TORRENTS', 'TORRENTS_WIKILEAKS_COMPLETO', 'txt')
|
||||
|
||||
# Carpetas con los archivos tokenizados para hacer las comparaciones
|
||||
carpeta_noticias_tokenized = '/var/www/theflows.net/flujos/FLUJOS_DATOS/NOTICIAS/tokenized'
|
||||
carpeta_wikipedia_tokenized = '/var/www/theflows.net/flujos/FLUJOS_DATOS/WIKIPEDIA/articulos_tokenizados'
|
||||
carpeta_torrents_tokenized = '/var/www/theflows.net/flujos/FLUJOS_DATOS/TORRENTS/TORRENTS_WIKILEAKS_COMPLETO/tokenized'
|
||||
carpeta_noticias_tokenized = os.path.join(DATOS_DIR, 'NOTICIAS', 'tokenized')
|
||||
carpeta_wikipedia_tokenized = os.path.join(DATOS_DIR, 'WIKIPEDIA', 'articulos_tokenizados')
|
||||
carpeta_torrents_tokenized = os.path.join(DATOS_DIR, 'TORRENTS', 'TORRENTS_WIKILEAKS_COMPLETO', 'tokenized')
|
||||
|
||||
# Iniciar cliente MongoDB
|
||||
client = init_mongo_client()
|
||||
|
||||
# Omitir la subida de documentos
|
||||
print("Subiendo archivos originales de Noticias a MongoDB...")
|
||||
logging.info("Iniciando subida de noticias a MongoDB")
|
||||
procesar_documentos(carpeta_noticias_txt, client['FLUJOS_DATOS']['noticias'])
|
||||
logging.info("Finalizada subida de noticias a MongoDB")
|
||||
# [DESACTIVADO 2026-06-06] Dual-write legacy de noticias a Mongo.
|
||||
# Escribía docs incompatibles (sin source_type/embedding) en la colección
|
||||
# canónica 'noticias', desincronizándola de coconews. Backup de los 41.467
|
||||
# docs legacy ya existentes en colección 'noticias_legacy_backup'.
|
||||
# El sistema canónico de noticias es ahora coconews (source_type:'rss').
|
||||
# logging.info("Iniciando subida de noticias a MongoDB")
|
||||
# procesar_documentos(carpeta_noticias_txt, client['FLUJOS_DATOS']['noticias'])
|
||||
# logging.info("Finalizada subida de noticias a MongoDB")
|
||||
|
||||
# print("Subiendo archivos originales de Wikipedia a MongoDB...")
|
||||
logging.info("Iniciando subida de Wikipedia a MongoDB")
|
||||
|
|
|
|||
|
|
@ -11,6 +11,12 @@ import string
|
|||
import nltk
|
||||
from nltk.corpus import stopwords
|
||||
|
||||
# Raiz de FLUJOS_DATOS. Por defecto se deduce de la ubicacion de este fichero,
|
||||
# asi el repo funciona en cualquier maquina sin editar nada.
|
||||
DATOS_DIR = os.getenv('FLUJOS_DATOS_DIR',
|
||||
os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
||||
|
||||
|
||||
# Descargar stopwords la primera vez
|
||||
nltk.download('stopwords')
|
||||
stop_words = set(stopwords.words('spanish'))
|
||||
|
|
@ -226,14 +232,14 @@ def manejar_comparaciones_multiproceso(directorios_tokenized):
|
|||
def main():
|
||||
try:
|
||||
# Rutas absolutas de los archivos en formato txt
|
||||
carpeta_noticias_txt = '/var/www/theflows.net/flujos/FLUJOS_DATOS/NOTICIAS/articulos'
|
||||
carpeta_wikipedia_txt = '/var/www/theflows.net/flujos/FLUJOS_DATOS/WIKIPEDIA/articulos_wikipedia'
|
||||
carpeta_torrents_txt = '/var/www/theflows.net/flujos/FLUJOS_DATOS/TORRENTS/TORRENTS_WIKILEAKS_COMPLETO/txt'
|
||||
carpeta_noticias_txt = os.path.join(DATOS_DIR, 'NOTICIAS', 'articulos')
|
||||
carpeta_wikipedia_txt = os.path.join(DATOS_DIR, 'WIKIPEDIA', 'articulos_wikipedia')
|
||||
carpeta_torrents_txt = os.path.join(DATOS_DIR, 'TORRENTS', 'TORRENTS_WIKILEAKS_COMPLETO', 'txt')
|
||||
|
||||
# Carpetas con los archivos tokenizados para hacer las comparaciones
|
||||
carpeta_noticias_tokenized = '/var/www/theflows.net/flujos/FLUJOS_DATOS/NOTICIAS/tokenized'
|
||||
carpeta_wikipedia_tokenized = '/var/www/theflows.net/flujos/FLUJOS_DATOS/WIKIPEDIA/articulos_tokenizados'
|
||||
carpeta_torrents_tokenized = '/var/www/theflows.net/flujos/FLUJOS_DATOS/TORRENTS/TORRENTS_WIKILEAKS_COMPLETO/tokenized'
|
||||
carpeta_noticias_tokenized = os.path.join(DATOS_DIR, 'NOTICIAS', 'tokenized')
|
||||
carpeta_wikipedia_tokenized = os.path.join(DATOS_DIR, 'WIKIPEDIA', 'articulos_tokenizados')
|
||||
carpeta_torrents_tokenized = os.path.join(DATOS_DIR, 'TORRENTS', 'TORRENTS_WIKILEAKS_COMPLETO', 'tokenized')
|
||||
|
||||
# Iniciar cliente MongoDB
|
||||
client = init_mongo_client()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue