rs-trafilatura: Una Biblioteca de Extracción de Contenido Web en Rust

Murrough Foley
Murrough Foley
Author·17 min read

Construí rs-trafilatura porque necesitaba extraer contenido limpio de páginas web a gran escala — no solo artículos, sino páginas de productos, foros, documentación, páginas de destino, todo el conjunto. Las herramientas existentes eran solo de Python (demasiado lentas para mi flujo de trabajo), o crates de Rust que manejaban bien las páginas de artículos pero fallaban en cualquier otra cosa.

Comenzó como una conversión directa a Rust de la excelente biblioteca Python Trafilatura de Adrien Barbaresi. Necesitaba la velocidad — procesar miles de páginas a través de un flujo de trabajo en Python era un cuello de botella en mi análisis de SEO. Pero mientras probaba en diferentes tipos de páginas, seguía encontrando el mismo problema: la extracción única para todo no funciona en la web moderna.

Así que creció. Clasificación de tipos de página. Perfiles de extracción específicos por tipo. Una puntuación de confianza. Salida en Markdown. Un clasificador de ML cuando la heurística basada en reglas alcanzaba su límite.

Qué hace

rs-trafilatura extrae el contenido principal de cualquier página web — título, autor, fecha y el cuerpo completo del artículo — mientras elimina la navegación, anuncios, barras laterales, banners de cookies y otra información repetitiva. Lo que lo diferencia de otras bibliotecas de extracción:

  • Clasificación de tipo de página: Un clasificador de tres etapas (heurística de URL, análisis de señales HTML, XGBoost con 181 características) detecta 7 tipos de página con un 87% de precisión — artículo, foro, producto, colección, listado, documentación y servicio. Cada tipo obtiene un perfil de extracción especializado.

  • Confianza de extracción: Cada extracción incluye una puntuación de calidad (0.0-1.0) de un modelo de regresión XGBoost con 27 características que predice el puntaje F1 esperado. Las páginas con puntuación inferior a 0.80 son candidatas para un respaldo con LLM — más sobre esto a continuación.

  • Salida en Markdown: Markdown al estilo de GitHub que conserva encabezados, enlaces, tablas, negrita/cursiva, bloques de código y citas en bloque. Esto es lo que realmente necesito para el análisis SEO — las señales estructurales importan tanto como el texto.

  • Velocidad: 44ms por página en CPU. Eso son 22 páginas por segundo en hardware común, comparado con 1.570ms por página para MinerU-HTML en una GPU A100.

use rs_trafilatura::{extract_with_options, Options};

let html = std::fs::read_to_string("page.html")?;
let result = extract_with_options(&html, &Options::default())?;

println!("Title: {:?}", result.metadata.title);
println!("Author: {:?}", result.metadata.author);
println!("Content: {}", result.content_text);
println!("Page type: {:?}", result.metadata.page_type);
println!("Confidence: {:.2}", result.extraction_quality);
import rs_trafilatura

html = open("page.html").read()
result = rs_trafilatura.extract(html, url="https://example.com")

print(f"Title: {result.title}")
print(f"Content: {result.main_content[:200]}...")
print(f"Page type: {result.page_type}")
print(f"Confidence: {result.extraction_quality:.2f}")

El paquete de Python empaqueta cuatro crates de Rust en una sola extensión nativa vía PyO3 — sin sobrecarga de subproceso, simplemente Rust compilado llamado directamente desde Python.

Para quién es esto

Honestamente, construí esto para mí. Quería entender qué ve Google cuando evalúa una página web, y para hacer eso necesitaba extraer contenido limpio y estructurado de miles de páginas en los resultados de búsqueda — no solo artículos, sino la mezcla completa de tipos de página que encuentras en un SERP real. Las herramientas existentes no servían para eso, así que construí una que sí.

Pero resulta que la extracción de contenido a gran escala es un problema que mucha gente está tratando de resolver — y algunos lo han convertido en negocios serios:

Empresas de búsqueda y datos venden contenido web extraído como servicio. Jina AI construyó ReaderLM-v2 y su API Reader específicamente para esto — dales una URL, obtén markdown limpio. Firecrawl hace lo mismo con renderizado JS y manejo anti-bots. Tavily empaqueta búsqueda + extracción como una API para agentes de IA. Diffbot ha estado haciendo extracción estructurada de datos web por más de una década. Zyte (anteriormente ScrapingHub — el mismo equipo detrás del benchmark de extracción de artículos) vende extracción a escala empresarial. El mercado existe porque el problema es difícil y todos necesitan que se resuelva.

Desarrolladores de RAG y pipelines de LLM necesitan contenido limpio para alimentar modelos de embedding y ventanas de contexto. La información repetitiva en tu contexto de recuperación significa tokens desperdiciados y peores respuestas. Cada pipeline de RAG tiene un paso de extracción, y la mayoría usa Readability o BeautifulSoup obteniendo resultados mediocres en páginas que no son artículos.

Equipos de datos de entrenamiento para LLM procesan miles de millones de páginas web. La calidad de la extracción impacta directamente en la calidad del modelo. Common Crawl provee el HTML crudo — pero convertir eso en texto de entrenamiento limpio es donde importa la calidad de extracción. Unos pocos puntos porcentuales de F1 a lo largo de miles de millones de páginas significa millones de páginas de ruido eliminadas o contenido real preservado. El equipo detrás de MinerU-HTML demostró un enfoque con su corpus AICC — agrupando páginas de Common Crawl por similitud de plantilla DOM, ejecutando un LLM en una página representativa por clúster, luego destilando esas decisiones en reglas ligeras aplicadas al 99.6% restante de páginas. Arquitectura inteligente.

Profesionales de SEO usan la extracción para aproximar lo que los motores de búsqueda ven. Auditorías de contenido, análisis de competidores, puntuación de calidad SERP, análisis de brechas de contenido — todo esto comienza extrayendo el contenido real de una página. Si tu herramienta de extracción incluye menús de navegación y banners de cookies en el "contenido", tu análisis es erróneo antes de empezar.

Investigadores académicos en recuperación de información, minería web y NLP necesitan extracción reproducible para experimentos. El benchmark WCXB existe en parte porque no pude encontrar un benchmark decente que probara la extracción entre tipos de página — y estoy seguro de que no fui el único buscándolo.

Si procesas páginas web a gran escala y te importa lo que realmente estás extrayendo, esto es para ti.

Resultados del benchmark

Evalué rs-trafilatura contra otros sistemas de extracción en dos conjuntos de datos: el benchmark de ScrapingHub (181 artículos) y el benchmark WCXB que construí (2.008 páginas en 7 tipos de página, dividido en un conjunto de desarrollo de 1.497 páginas y un conjunto de prueba reservado de 511 páginas).

Benchmark de ScrapingHub (181 artículos)

BibliotecaPuntaje F1PrecisiónRecuperación
rs-trafilatura0.9660.9420.991
trafilatura (Python)0.9480.9330.983

Conjunto de desarrollo WCXB (1.497 páginas, 7 tipos de página)

BibliotecaPuntaje F1PrecisiónRecuperación
rs-trafilatura0.8590.8630.890
MinerU-HTML (LLM 0.6B)0.8270.8450.840
Trafilatura (Python)0.7910.8520.793
dom-smoothie0.7620.8060.768
ReaderLM-v2 (LLM 1.5B)0.7410.7410.790

Conjunto de prueba reservado WCXB (511 páginas, nunca usado durante el desarrollo)

BibliotecaPuntaje F1PrecisiónRecuperación
rs-trafilatura0.8930.9000.910
Trafilatura (Python)0.8330.8860.828

rs-trafilatura supera la implementación original en Python por 6.8 puntos F1 en el conjunto de desarrollo y 6.0 puntos en el conjunto reservado. También supera a ambos extractores basados en LLM mientras se ejecuta a 44ms por página en CPU — comparado con 1.570ms (MinerU-HTML) y 10.410ms (ReaderLM-v2) en una GPU A100.

Cómo se comparan los crates de extracción en Rust

Para contexto, así es como se comparan los principales crates de extracción de Rust en el benchmark WCXB:

Extractores de contenido principal (filtran información repetitiva):

BibliotecaPuntaje F1Mejor para
rs-trafilatura0.859Extracción completa con metadatos, 7 tipos de página
dom_smoothie0.762Extracción estilo Readability
dom-content-extraction0.731Algoritmo CETD, respaldado por investigación

Extractores de texto completo (extraen todo, sin filtrar):

BibliotecaPuntaje F1Compensación
nanohtml2text0.670Rápido (606us) pero incluye información repetitiva
fast_html2md0.664Salida en Markdown, incluye información repetitiva

La distinción importa: los extractores de texto completo capturan todo, incluida la navegación y pies de página. Los extractores de contenido principal identifican y devuelven solo el cuerpo del artículo. Para análisis SEO, agregación de contenido o datos de entrenamiento de LLM, quieres lo último.

Una nota sobre dom_smoothie: es un crate excelente y que estudié de cerca mientras construía rs-trafilatura. También es más rápido — 27ms/página vs 44ms de rs-trafilatura — porque hace extracción estilo Readability sin la sobrecarga de clasificación y perfiles específicos por tipo. Si trabajas principalmente con artículos y blogs, dom_smoothie es una opción sólida. rs-trafilatura es más lento porque clasifica el tipo de página y aplica una lógica de extracción diferente en cada página — esa es la compensación por manejar contenido que no son artículos.

Tanto dom_smoothie como rs-trafilatura están construidos sobre dom_query de niklak — una biblioteca de manipulación DOM para Rust que hace que el recorrido basado en selectores CSS sea sencillo. Es uno de esos crates fundamentales que no reciben suficiente crédito.

Para un análisis profundo de los crates de análisis HTML en Rust (html5ever, scraper, select.rs, dom_query), recomendaría la comparación exhaustiva de Evan Schwartz de 13 crates de Rust para extraer texto de HTML.

Por qué importan los tipos de página

Esta es la parte que más me sorprendió. En artículos, cada extractor converge — F1 entre 0.88 y 0.93. En todo lo demás, divergen enormemente:

Tipo de PáginaNrs-trafilaturaMinerU-HTMLTrafilaturaReaderLM-v2
Artículo7930.9320.9280.9260.878
Documentación910.9310.8380.8880.776
Servicio1650.8430.8240.7630.703
Foro1130.7920.7940.5850.589
Colección1170.7130.5060.5530.417
Listado990.7040.7100.5890.559
Producto1190.6700.6190.5670.463

Foros: una diferencia de 33 puntos entre el mejor y el peor. Colecciones: 30 puntos. Productos: 26 puntos. Los benchmarks solo de artículos ocultan todo esto.

La razón es estructural. Las publicaciones de usuario en un hilo de foro coinciden con class="comment" — que la mayoría de extractores tratan como información repetitiva. Una página de servicio distribuye contenido en 10 elementos <section> diferentes — la extracción de un solo nodo captura uno y pierde el resto. Una página de producto almacena su descripción en datos estructurados JSON-LD — invisible para extractores solo de DOM.

rs-trafilatura maneja esto clasificando la página primero, luego aplicando una estrategia de extracción específica por tipo. Los perfiles de foro tratan los elementos de comentario como contenido. Los perfiles de página de servicio fusionan contenido de múltiples secciones DOM. Los perfiles de producto recurren a JSON-LD cuando falla la extracción DOM.## Puntuación de confianza y canalizaciones híbridas

El predictor de calidad de extracción es la característica que más me interesa seguir desarrollando. Actualmente es un modelo XGBoost de 27 características que analiza señales disponibles en el momento de la extracción: proporción de extracción a HTML, estructura de párrafos, densidad de enlaces, longitud del contenido en relación con las expectativas del tipo de página, palabras clave de texto repetitivo en el texto inicial. Con un umbral de 0.80, identifica correctamente aproximadamente el 35% de las páginas mal extraídas manteniendo una precisión del 97% en el resto.

El uso práctico está en las canalizaciones híbridas. Ejecuta rs-trafilatura en todo a 44ms/página. Para el ~8% de páginas donde la confianza es baja, enrútalas a un extractor neuronal. En el conjunto de prueba WCXB reservado, esto aumenta el F1 de 0.893 a 0.910 — lo mejor de ambos mundos.

Pero el enrutamiento debe ser consciente del tipo de página. MinerU-HTML ayuda en artículos, foros y páginas de servicio, pero en realidad rinde peor que rs-trafilatura en colecciones (0.506 vs 0.713) y productos (0.619 vs 0.670). Enviar páginas de colecciones con baja confianza a MinerU-HTML empeora las cosas, no las mejora.

Hacia donde me gustaría llevar esto: en lugar de enrutar todas las páginas de baja confianza a un único LLM de propósito general, enrutarlas a modelos específicos del tipo de página entrenados para esa tarea de extracción exacta. Un modelo pequeño ajustado específicamente para la extracción de páginas de productos. Otro entrenado en hilos de foro. El clasificador de tipo de página ya te dice qué modelo llamar — la infraestructura solo necesita modelos especializados al otro extremo. Esa es la arquitectura que creo que gana a largo plazo: heurísticas rápidas para el 90%+ de las páginas, modelos neuronales especializados para los tipos de página donde las heurísticas alcanzan su techo.

Aún no he construido esto. Pero el evaluador de confianza y el clasificador de tipo de página son la base para ello.

Encabezados, SEO y los límites de la extracción HTML

Un hallazgo interesante del trabajo de evaluación comparativa: solo una buena porción de los títulos de sección visualmente prominentes en las páginas web usan etiquetas semánticas <h1>-<h6>. El resto usa elementos <strong>, <span> con estilo o font-weight: bold en CSS para crear encabezados visuales sin marcado semántico.

Esto es importante tanto para el SEO como para la extracción:

  • La Patente de Vectores de Encabezado de Google asigna vectores numéricos a los encabezados <h1>-<h6> para la comprensión temática.
  • La Patente de Segmentación de Páginas de Google describe el pseudo-renderizado de páginas para detectar texto visualmente prominente independientemente de las etiquetas HTML.
  • La extracción solo por HTML (lo que hacen rs-trafilatura y todos los extractores heurísticos) solo puede detectar encabezados que usan etiquetas <h>. Un <strong>Título de Sección</strong> se convierte en texto en negrita, no en un encabezado.

Si controlas el HTML: usa siempre etiquetas de encabezado semánticas. Un título de sección <strong> que parece un encabezado es invisible para la mayoría de las herramientas de extracción y proporciona señales más débiles a los motores de búsqueda.

Para canalizaciones de extracción: esta brecha es un techo teórico para cualquier convertidor puro de HTML a markdown — incluyendo rs-trafilatura. Un <strong>Título de Sección</strong> aparecerá como texto en negrita en la salida markdown, no como un encabezado. No hay forma de evitar esto sin renderizado visual o interpretación por LLM. Es un argumento más a favor de las canalizaciones híbridas que combinan extracción heurística rápida con respaldo de LLM en páginas donde la detección estructural es incierta.

Lo que aún necesita trabajo

Quiero ser claro sobre dónde esto aún no es lo suficientemente bueno.

La clasificación del tipo de página se sitúa en el 87%. Eso significa que aproximadamente 1 de cada 8 páginas obtiene el perfil de extracción incorrecto. Para artículos, foros y productos, la precisión está en los bajos 90 — bien. Pero los listados (53% de recuperación) y las páginas de servicio (71%) se clasifican erróneamente con demasiada frecuencia, generalmente como artículos. Me gustaría llevar la precisión general a los bajos 90, lo que probablemente signifique mejores características para distinguir contenido editorial de índices de contenido.

La extracción de productos (F1 = 0.670) y páginas de colección (0.713) no están donde quiero que estén. Los productos son difíciles porque mucho contenido reside en JSON-LD e interfaces con pestañas. Las colecciones son difíciles porque el "contenido" es una mezcla de fichas de producto e interfaz de filtros. Estos son los tipos de página donde el enfoque heurístico alcanza su techo con más fuerza.

Este es un proyecto secundario. Soy consultor de SEO — el trabajo remunerado tiene prioridad, y hay semanas en las que rs-trafilatura no recibe atención alguna. El progreso viene en ráfagas cuando tengo tiempo entre proyectos de clientes. Menciono esto no como excusa sino para calibrar las expectativas — esto no está respaldado por un equipo o una empresa, es una persona trabajando en ello cuando puede.

Si alguna de estas limitaciones es un impedimento para tu caso de uso, MinerU-HTML es una alternativa sólida para cargas de trabajo con muchos artículos, y Firecrawl maneja el lado de la infraestructura si prefieres no ejecutar tu propia extracción.

Primeros pasos

Rust — instalar desde crates.io:

[dependencies]
rs-trafilatura = "0.2"

Python — instalar desde PyPI:

pip install rs-trafilatura

O usar el binario CLI:

curl -s https://example.com/article | extract_stdin

La salida es JSON con título, autor, fecha, contenido principal, tipo de página, confianza de clasificación y confianza de extracción.

Relacionado


Citas y referencias

Patentes de Google sobre extracción de contenido y segmentación de páginas

  • Segmentación de Páginas — Mehta, B., et al. (2011). "Segmenting Web Pages." US Patent 7,930,307. Google. — Describe el pseudo-renderizado de páginas para identificar regiones de contenido visualmente distintas, independientes de la estructura de etiquetas HTML. Análisis de SEO by the Sea
  • Vectores de Encabezado — Patente de Google sobre asignar vectores numéricos a encabezados <h1><h6> para comprensión temática y análisis de estructura de documentos. Análisis de MarketBrew
  • DOM Distiller — El sistema de extracción de contenido en producción de Google que impulsa el Modo Lector de Chrome. Basado en Boilerpipe con respaldo al estilo Readability. Código fuente

Investigación fundamental sobre extracción

  • Boilerpipe — Kohlschutter, C., Fankhauser, P., Nejdl, W. (2010). "Boilerplate Detection using Shallow Text Features." WSDM 2010. — El artículo fundamental sobre extracción de contenido basada en densidad de texto. Trata la extracción como clasificación binaria de bloques de texto.
  • Trafilatura — Barbaresi, A. (2021). "Trafilatura: A Web Scraping Library and Command-Line Tool for Text Discovery and Retrieval." ACL 2021. GitHub — La biblioteca de extracción en Python más utilizada. rs-trafilatura comenzó como un port de esta.
  • Readability — Mozilla (2010). El algoritmo detrás de la Vista de Lector de Firefox. Puntúa nodos DOM por densidad de texto y proporción de enlaces. GitHub
  • jusText — Pomikalek, J. (2011). "Removing Boilerplate and Duplicate Content from Web Corpora." PhD thesis, Masaryk University. GitHub

Extracción neuronal / con LLM

  • MinerU-HTML (Dripper) — Liu, M., et al. (2025). "Dripper: Token-Efficient Main HTML Extraction with a Lightweight LM." arXiv:2511.23119 | GitHub — Ajusta Qwen3-0.6B para clasificación binaria de elementos.
  • ReaderLM-v2 — Jina AI (2025). "ReaderLM-v2: HTML to Markdown with a Small Language Model." arXiv:2503.01151 | HuggingFace — Modelo de 1.5B parámetros que genera Markdown directamente desde HTML.
  • BoilerNet — Leonhardt, J., Anand, A., Khosla, M. (2020). "Boilerplate Removal using a Neural Sequence Labeling Model." WWW 2020 Companion.
  • Web2Text — Vogels, T., Ganea, O.E., Eickhoff, C. (2018). "Web2Text: Deep Structured Boilerplate Removal." ECIR 2018.

Estudios comparativos y evaluaciones comparativas

  • Bevendorff et al. — Bevendorff, J., Gupta, S., Kiesel, J., Stein, B. (2023). "An Empirical Comparison of Web Content Extraction Algorithms." SIGIR 2023. GitHub — La comparación existente más completa. Combinó 8 conjuntos de datos, evaluó 14 extractores. Hallazgo clave: "el rendimiento depende bastante del género".
  • ScrapingHub — (2019). Evaluación comparativa de extracción de artículos. 181 páginas. GitHub
  • Evan Schwartz — (2024). "Comparing 13 Rust Crates for Extracting Text from HTML." Blog — Comparación exhaustiva de opciones de análisis HTML en Rust.

Este trabajo

  • WCXB — Foley, M. (2026). Evaluación comparativa de extracción de contenido web. 2,008 páginas, 7 tipos de página. Sitio web | DOI: 10.5281/zenodo.19316874
  • rs-trafilatura — Foley, M. (2026). Extracción de contenido web consciente del tipo de página. crates.io | PyPI | GitHub

Murrough Foley (ORCID: 0009-0008-3127-2101) es consultor de SEO y autor de rs-trafilatura. La evaluación comparativa WCXB está disponible con DOI 10.5281/zenodo.19316874.

Murrough Foley
Conectemos

¿Tienes alguna pregunta o quieres colaborar? Contáctame en redes sociales.