Parsing in Rust: schneller als Python und ohne Garbage Collector

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Warum Rust der neue König des Parsings ist

\n\n

Wenn Sie jemals einen Parser in Python geschrieben haben, kennen Sie diesen Moment: Das Skript läuft, die Daten werden geladen, aber plötzlich – Speicherfehler, oder der Garbage Collector beschließt, im ungünstigsten Moment eine „Pause“ einzulegen. Kommt Ihnen bekannt vor? Stellen Sie sich nun vor, Ihr Parser fliegt mit C-Geschwindigkeit, frisst keinen unnötigen Speicher und ist dabei sicher. Willkommen in der Welt des Parsings in Rust.

\n\n

Rust ist nicht nur eine modische Sprache. Für Datenscraping-Aufgaben bietet es das, was Python niemals bieten kann: vollständige Kontrolle über den Speicher, keine Gemeinkosten durch einen Garbage Collector und unglaubliche Geschwindigkeit. Gleichzeitig ist das Ökosystem für die Arbeit mit HTTP und HTML bereits ausgereift genug. In diesem Artikel zeige ich Ihnen, wie Sie einen echten Parser in Rust erstellen, den Sie für Preisüberwachung, Content-Sammlung oder SEO-Analyse nutzen können.

\n\n

Was wir brauchen: Rust-Werkzeuge für das Parsing

\n\n

Für Web Scraping in Rust gibt es drei Säulen:

\n\n
    \n
  • reqwest – HTTP-Client. Kann Websites besuchen, unterstützt Asynchronität und Proxys.
  • \n
  • scraper (oder select.rs) – Bibliothek zum Parsen von HTML. Ermöglicht die Verwendung von CSS-Selektoren.
  • \n
  • tokio – Asynchrone Laufzeitumgebung. Ohne sie wird Ihr Parser bei jeder Anfrage langsamer.
  • \n
\n\n

Lassen Sie uns ein neues Projekt erstellen und die Abhängigkeiten installieren:

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

Fertig. Jetzt haben wir alles, um einen Parser in Rust in 10 Minuten zu schreiben.

\n\n

Erster Parser: Überschriften von Habr abrufen

\n\n

Beginnen wir einfach: Wir parsen die Artikelüberschriften von Habr. Das ist ein Klassiker des Genres, wie „Hallo, Welt!“ für Scraping in Rust.

\n\n
use scraper::{Html, Selector};\nuse reqwest;\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    // 1. GET-Anfrage senden\n    let resp = reqwest::get("https://habr.com/ru/articles/")\n        .await?\n        .text()\n        .await?;\n\n    // 2. HTML parsen\n    let document = Html::parse_document(&resp);\n\n    // 3. Selektor für Überschriften erstellen\n    let selector = Selector::parse("h2.article-title a").unwrap();\n\n    // 4. Iterieren und ausgeben\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

Was passiert hier? Wir verwenden reqwest für die asynchrone Anfrage, scraper zum Parsen des HTML und den CSS-Selektor h2.article-title a, um alle Links in den Überschriften zu finden. Starten Sie cargo run – und Sie sehen die Artikelliste. Ziemlich schnell, oder?

\n\n

Asynchrones Parsing: 100 Seiten in einer Sekunde laden

\n\n

Das Hauptmerkmal des Parsings in Rust ist die Asynchronität. In Python würden Sie asyncio und aiohttp verwenden, aber Rust mit tokio bietet noch mehr Kontrolle. Lassen Sie uns mehrere Seiten parallel parsen.

\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

Buchempfehlungen