Cómo estoy diseñando Rolsfera: arquitectura real de un agregador de noticias con scraping, RSS, IA y automatización
Arquitectura real de Rolsfera, un agregador de noticias con scraping, RSS e IA. Decisiones técnicas, stack, errores y próximos pasos.

Llevo meses construyendo Rolsfera y todavía no he escrito una sola línea sobre su arquitectura. Supongo que por lo mismo que le pasa a la mayoría de desarrolladores con sus proyectos personales: estás tan metido en resolver problemas que documentar se siente como un lujo. Pero creo que ya toca.
Rolsfera es un agregador de noticias. No uno de esos que simplemente muestra feeds RSS en una interfaz bonita. Es un sistema que recoge información de múltiples fuentes (RSS, scraping, APIs), la procesa, la filtra, la resume con IA y la distribuye a canales como Telegram o X. Todo eso con un grado razonable de automatización, pero con revisión humana en los puntos donde importa.
Este artículo no es un tutorial paso a paso. Es un mapa de las decisiones técnicas que he tomado, por qué las he tomado y dónde me he equivocado. Si estás pensando en montar algo parecido, espero ahorrarte algunas iteraciones.
El problema que intento resolver
La información está fragmentada. No es un problema nuevo, pero en 2026 se ha vuelto más absurdo que nunca. Si quieres seguir un tema técnico necesitas revisar blogs, newsletters, RSS, Telegram, X, Reddit, Hacker News y probablemente tres o cuatro fuentes más que dependen de tu nicho.
Cada fuente tiene su formato, su frecuencia, su nivel de ruido. Y el resultado es que pasas más tiempo buscando y filtrando que leyendo y procesando.
Rolsfera nace de una frustración real: quiero un flujo donde la información llegue a mí, filtrada y resumida, sin tener que abrir quince pestañas cada mañana.
Pero no quiero un sistema completamente automático que publique sin supervisión. He visto demasiados bots de contenido que acaban vomitando basura o duplicando noticias irrelevantes. La idea es automatizar la parte mecánica (recoger, limpiar, resumir) y mantener el criterio editorial en manos humanas.
Diagrama de arquitectura
Antes de entrar en detalle, este es el flujo general del sistema:
┌─────────────────────────────────────────────────────────────────┐
│ FUENTES DE DATOS │
│ │
│ ┌─────────┐ ┌──────────┐ ┌─────────┐ ┌─────────────┐ │
│ │ RSS │ │ Scraping │ │ APIs │ │ Telegram │ │
│ │ Feeds │ │ (Python) │ │ (REST) │ │ Channels │ │
│ └────┬─────┘ └────┬─────┘ └────┬────┘ └──────┬──────┘ │
│ │ │ │ │ │
└────────┼──────────────┼──────────────┼───────────────┼──────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ INGESTA Y NORMALIZACIÓN │
│ │
│ n8n (orquestación) + Python (procesamiento) │
│ - Parseo de feeds │
│ - Extracción de contenido │
│ - Deduplicación por URL y hash de contenido │
│ - Normalización de formato │
│ │
└────────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ PROCESAMIENTO CON IA │
│ │
│ - Clasificación por categoría │
│ - Generación de resumen │
│ - Extracción de entidades y tags │
│ - Puntuación de relevancia │
│ │
└────────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ ALMACENAMIENTO │
│ │
│ PostgreSQL (artículos, metadatos, estado de publicación) │
│ │
└────────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ VALIDACIÓN EDITORIAL │
│ │
│ Panel interno: aprobar / descartar / editar antes de publicar │
│ │
└────────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ DISTRIBUCIÓN │
│ │
│ ┌───────────┐ ┌─────────┐ ┌─────────┐ ┌────────────┐ │
│ │ Telegram │ │ X │ │ Web │ │ Newsletter │ │
│ └───────────┘ └─────────┘ └─────────┘ └────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘No es un diagrama de libro de texto, pero refleja la realidad. Hay cuatro capas claras: ingesta, procesamiento, validación y distribución. Y entre ellas, n8n actúa como pegamento.
El stack técnico
Estas son las piezas principales y por qué las elegí:
Python es el lenguaje principal de procesamiento. Lo uso para los scrapers, los parsers de RSS, la lógica de deduplicación, la comunicación con APIs de LLMs y la generación de resúmenes. No necesito justificar mucho esta decisión: para tareas de extracción y procesamiento de datos, Python sigue siendo la opción más práctica. Las librerías están ahí, la comunidad está ahí y el tiempo de desarrollo es razonable.
n8n es el orquestador. Coordina los flujos: cuándo se ejecutan los scrapers, cuándo se procesan los artículos nuevos, cuándo se envían a revisión, cuándo se publican. Podría haber usado Airflow o un sistema de colas propio, pero n8n me da algo que para un proyecto personal es valioso: una interfaz visual donde veo qué ha pasado en cada ejecución sin abrir logs.
# Ejemplo simplificado: parser de RSS con feedparser
import feedparser
import hashlib
from datetime import datetime
def parse_feed(feed_url: str) -> list[dict]:
feed = feedparser.parse(feed_url)
articles = []
for entry in feed.entries:
content_hash = hashlib.sha256(
entry.get("link", "").encode()
).hexdigest()
articles.append({
"title": entry.get("title", ""),
"url": entry.get("link", ""),
"published": entry.get("published", ""),
"summary": entry.get("summary", ""),
"content_hash": content_hash,
"source": feed_url,
"ingested_at": datetime.utcnow().isoformat(),
})
return articlesPostgreSQL como base de datos. Almacena artículos, metadatos, estado de publicación y logs de procesamiento. Uso campos JSONB para guardar metadatos variables (tags extraídos por IA, puntuaciones, entidades detectadas). PostgreSQL aguanta esto sin pestañear y me evita tener que montar un sistema separado para datos semiestructurados.
BeautifulSoup y Playwright para scraping. BeautifulSoup para sitios con HTML estático y Playwright para los que renderizan con JavaScript. La mayoría de fuentes de noticias siguen sirviendo contenido estático, así que BeautifulSoup cubre el 80% de los casos. Playwright entra cuando no hay alternativa.
APIs de LLM para el procesamiento inteligente. Uso modelos a través de API para clasificar artículos por categoría, generar resúmenes cortos y extraer entidades relevantes. No entreno modelos propios; eso sería sobreingeniería para este caso de uso.
Decisiones técnicas que importan
Por qué RSS + scraping (y no solo uno de los dos)
RSS es estable, ético y fácil de parsear. Pero no todas las fuentes tienen RSS. Y las que lo tienen no siempre incluyen el contenido completo: muchas solo exponen título y un extracto.
El scraping complementa donde RSS no llega. Hay medios que no ofrecen feed, hay secciones específicas que no están en el RSS general y hay datos estructurados (autor, categoría, fecha exacta) que el feed omite.
La combinación de RSS como fuente primaria y scraping como fallback me da cobertura amplia sin depender de un solo método de extracción.
Por qué n8n y no Airflow
Airflow es una herramienta excelente para pipelines de datos en producción. Pero para un proyecto personal con flujos que modifico cada semana, n8n tiene ventajas prácticas:
- La interfaz visual reduce el tiempo de iteración. Puedo mover nodos, probar ejecuciones parciales y ver datos intermedios sin tocar código.
- El self-hosting es trivial. Un contenedor Docker y listo.
- Para flujos de orquestación (trigger → HTTP → procesar → guardar), n8n es más rápido de montar que escribir DAGs en Python.
Donde n8n flaquea es en procesamiento pesado. Por eso la lógica compleja (parseo, deduplicación, IA) la ejecuto en scripts Python que n8n invoca como servicios HTTP.
Por qué no solo APIs
Sería ideal que todos los medios expusieran APIs limpias con su contenido. Pero la realidad es que la mayoría no lo hacen, y los que sí lo hacen suelen tener limitaciones de rate, coste o acceso.
RSS y scraping me dan independencia. No dependo de que un tercero mantenga una API ni de que sus términos de servicio cambien de un día para otro. Obviamente, el scraping tiene sus propios riesgos (cambios de estructura, bloqueos), pero son riesgos que puedo gestionar técnicamente.
El flujo de datos en detalle
1. Ingesta
Cada fuente tiene un extractor dedicado. Los feeds RSS se procesan con feedparser. Los scrapers usan BeautifulSoup o Playwright según el sitio. Cada extractor devuelve un formato normalizado:
# Formato normalizado de artículo
{
"title": str,
"url": str,
"content": str, # texto limpio, sin HTML
"published_at": str, # ISO 8601
"source_name": str,
"source_type": str, # "rss" | "scraper" | "api"
"content_hash": str, # SHA-256 del contenido
"raw_metadata": dict, # datos originales sin procesar
}La deduplicación se hace en dos niveles: primero por URL exacta (lo más obvio) y luego por hash de contenido (para detectar el mismo artículo publicado en dos sitios diferentes o con URLs ligeramente distintas).
2. Procesamiento con IA
Una vez el artículo está normalizado y deduplicado, pasa por un pipeline de IA:
# Pipeline de procesamiento con LLM
def process_article(article: dict) -> dict:
prompt = f"""Analiza el siguiente artículo de noticias:
Título: {article['title']}
Contenido: {article['content'][:3000]}
Responde en JSON con:
- category: categoría principal (tech, política, economía, ciencia, etc.)
- summary: resumen de 2-3 frases
- entities: lista de entidades mencionadas (personas, empresas, tecnologías)
- relevance_score: puntuación de 1-10 según relevancia para una audiencia técnica
"""
response = call_llm(prompt)
enriched = article.copy()
enriched["ai_metadata"] = parse_json_response(response)
return enrichedEste paso no es gratis. Cada llamada a la API del LLM tiene un coste en tokens, y cuando procesas cientos de artículos al día, el gasto se acumula. Por eso aplico un primer filtro antes de la IA: si el artículo ya existe en la base de datos o su fuente tiene una tasa de relevancia históricamente baja, no lo proceso.
3. Almacenamiento
Todo va a PostgreSQL. La tabla principal de artículos tiene columnas fijas para los datos esenciales y un campo JSONB para los metadatos de IA:
CREATE TABLE articles (
id SERIAL PRIMARY KEY,
url TEXT UNIQUE NOT NULL,
title TEXT NOT NULL,
content TEXT,
published_at TIMESTAMP,
source_name TEXT NOT NULL,
source_type TEXT NOT NULL,
content_hash TEXT NOT NULL,
ai_metadata JSONB,
status TEXT DEFAULT 'pending', -- pending, approved, rejected, published
created_at TIMESTAMP DEFAULT NOW(),
published_to JSONB DEFAULT '[]'
);4. Validación editorial
Aquí es donde el sistema deja de ser automático. Los artículos procesados llegan con estado pending a un panel interno donde puedo revisarlos, editarlos si hace falta y aprobarlos o descartarlos.
No es un panel sofisticado. Es una interfaz simple que muestra el título, el resumen generado por IA, la puntuación de relevancia y el contenido original. Desde ahí decido qué se publica y qué no.
Este paso parece ineficiente, pero es el que marca la diferencia entre un bot de spam y un canal con criterio.
5. Distribución
Los artículos aprobados se publican en los canales configurados. Actualmente Telegram y X, con la web como tercer canal en desarrollo. Cada canal tiene su formateador: Telegram usa Markdown con emojis, X requiere versiones cortas con enlace, la web muestra el artículo completo.
n8n gestiona esta distribución. Cuando un artículo pasa a estado approved, un workflow se dispara, formatea el contenido para cada canal y lo publica. Si la publicación falla (rate limit, error de API), queda en cola para reintento.
Errores y limitaciones actuales
No todo es bonito. Estos son los problemas reales con los que convivo:
La deduplicación no es perfecta. Dos medios pueden publicar la misma noticia con textos suficientemente diferentes como para que el hash no coincida. Estoy experimentando con embeddings para detectar similitud semántica, pero añade complejidad y coste.
Los scrapers se rompen. Un medio cambia su HTML y el extractor deja de funcionar. Tengo alertas configuradas para detectar cuándo un scraper devuelve menos resultados de lo habitual, pero la respuesta sigue siendo manual: abrir el sitio, ver qué cambió y actualizar los selectores.
Los costes de IA escalan mal. Procesar 200 artículos diarios con un LLM no es caro. Pero si quiero escalar a 2000 o manejar artículos más largos, el coste se multiplica rápido. Estoy evaluando modelos más pequeños y fine-tuneados para las tareas de clasificación, que no necesitan el LLM más potente del mercado.
La validación editorial es un cuello de botella. Si no reviso los artículos, no se publican. Esto limita la frecuencia de publicación. Estoy trabajando en un sistema de confianza por fuente: si una fuente tiene un historial consistente de artículos aprobados, sus próximos artículos podrían publicarse automáticamente con menor supervisión.
El panel interno es precario. Funciona, pero no es cómodo. No tiene filtros avanzados, no permite agrupar artículos por tema y la interfaz es básicamente una tabla con botones. Es lo típico que en un proyecto personal siempre queda para después.
Próximos pasos
Rolsfera no está terminado ni lo estará pronto. Estos son los frentes abiertos:
Detección de duplicados semánticos. Pasar de comparación por hash a comparación por embeddings. La idea es que si dos artículos hablan de lo mismo con palabras distintas, el sistema los detecte como duplicados y presente solo el mejor.
Sistema de scoring por fuente. Asignar una puntuación de confianza a cada fuente basándose en el historial de aprobaciones y rechazos. Esto permitiría automatizar la publicación de fuentes de alta confianza.
Interfaz web pública. Sacar Rolsfera de mi panel interno y convertirlo en un producto que otros puedan usar. Esto implica autenticación, personalización de fuentes y una capa de presentación decente.
Diversificar los canales de distribución. Newsletter, RSS propio (irónico, lo sé) y quizás integración con lectores de feeds.
Optimizar costes de IA. Evaluar modelos más pequeños para clasificación y reservar los LLMs grandes solo para resúmenes y tareas que realmente lo necesiten.
Reflexión final
Rolsfera no es un proyecto revolucionario. Es un agregador de noticias con scraping e IA, un concepto que existe desde hace años. Lo que lo hace interesante para mí es que es un laboratorio real donde pruebo ideas de arquitectura, automatización y procesamiento de datos que luego aplico en otros contextos.
Si algo he aprendido construyéndolo es que la parte difícil no es montar el pipeline. Es mantenerlo funcionando cuando las fuentes cambian, los costes se acumulan y la vida real te deja poco tiempo para revisar artículos. La arquitectura tiene que absorber esa realidad, no ignorarla.
Y eso, creo, es lo que diferencia un side project que sobrevive de uno que muere en el tercer commit.


