Parseo en Rust: más rápido que Python y sin recolector de basura

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

¿Por qué Rust es el nuevo rey del parseo?

\n\n

Si alguna vez has escrito un parser en Python, conoces ese momento: el script funciona, los datos se descargan, pero de repente — error de memoria, o el recolector de basura decide «descansar» en el momento más inoportuno. ¿Te suena? Ahora imagina que tu parser vuela a la velocidad de C, no consume memoria extra y además es seguro. Bienvenido al mundo del parseo en Rust.

\n\n

Rust no es solo un lenguaje de moda. Para tareas de scraping de datos ofrece lo que Python nunca podrá: control total sobre la memoria, cero sobrecarga del recolector de basura y una velocidad increíble. Además, el ecosistema para trabajar con HTTP y HTML ya es bastante maduro. En este artículo te mostraré cómo construir un parser real en Rust que podrás usar para monitoreo de precios, recolección de contenido o análisis SEO.

\n\n

Lo que necesitaremos: herramientas de Rust para parseo

\n\n

Para web scraping en Rust hay tres pilares:

\n\n
    \n
  • reqwest — cliente HTTP. Puede navegar por sitios web, soporta asincronía y proxies.
  • \n
  • scraper (o select.rs) — biblioteca para parsear HTML. Permite usar selectores CSS.
  • \n
  • tokio — runtime asíncrono. Sin él, tu parser se ralentizará en cada solicitud.
  • \n
\n\n

Vamos a crear un nuevo proyecto e instalar las dependencias:

\n\n
cargo new rust_parser\ncd rust_parser\ncargo add reqwest --features json\ncargo add scraper tokio
\n\n

Listo. Ahora tenemos todo para escribir un parser en Rust en 10 minutos.

\n\n

Primer parser: obtenemos títulos de Habr

\n\n

Empecemos con algo simple: parsearemos los títulos de artículos de Habr. Es un clásico del género, como el «Hello, World!» del scraping en Rust.

\n\n
use scraper::{Html, Selector};\nuse reqwest;\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    // 1. Enviamos una solicitud GET\n    let resp = reqwest::get("https://habr.com/ru/articles/")\n        .await?\n        .text()\n        .await?;\n\n    // 2. Parseamos el HTML\n    let document = Html::parse_document(&resp);\n\n    // 3. Creamos un selector para los títulos\n    let selector = Selector::parse("h2.article-title a").unwrap();\n\n    // 4. Iteramos y mostramos\n    for element in document.select(&selector) {\n        let title = element.text().collect::<Vec<_>>().join("");\n        println!("{}", title.trim());\n    }\n\n    Ok(())\n}
\n\n

¿Qué sucede aquí? Usamos reqwest para la solicitud asíncrona, scraper para analizar el HTML y el selector CSS h2.article-title a para encontrar todos los enlaces en los títulos. Ejecutamos cargo run — y vemos la lista de artículos. Rápido, ¿verdad?

\n\n

Parseo asíncrono: descargamos 100 páginas en un segundo

\n\n

La principal ventaja del parseo en Rust es la asincronía. En Python usarías asyncio y aiohttp, pero Rust con tokio ofrece aún más control. Vamos a parsear varias páginas en paralelo.

\n\n
use scraper::{Html, Selector};\nuse reqwest;\nuse tokio::task;\n\nasync fn fetch_page(url: &str) -> Result<String, reqwest::Error> {\n    let resp = reqwest::get(url).await?.text().await?;\n    Ok(resp)\n}\n\nfn parse_titles(html: &str) -> Vec<String> {\n    let document = Html::parse_document(html);\n    let selector = Selector::parse("h2.article-title a").unwrap();\n    document\n        .select(&selector)\n        .map(|el| el.text().collect::<Vec<_>>().join("").trim().to_string())\n        .collect()\n}\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let urls: Vec<String> = (1..=5)\n        .map(|i| format!("https://habr.com/ru/articles/page{}/", i))\n        .coll                

Blogs

Book Recommendations