Parsing HTML in Rust: Libraries and Examples for Web Scraping

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Parsing HTML in Rust: Overview of Tools and Practical Examples



Rust is a modern systems programming language that is increasingly used for creating high-performance web scrapers and parsers. Thanks to its strict type system, memory safety, and asynchronous capabilities, Rust is ideal for tasks where you need to quickly and reliably extract data from HTML documents. In this article, we will look at the key libraries for parsing HTML in Rust, their features, and provide working code examples.



Main Libraries for Parsing HTML in Rust



The Rust ecosystem offers several mature solutions for working with HTML. The most popular are:



  • scraper — a high-level library with CSS selector support, built on top of select.rs and html5ever.
  • select.rs — a library for extracting data from the DOM using CSS selectors.
  • html5ever — a low-level parser compliant with the HTML5 standard (used internally by Servo).
  • quick-xml — a fast XML/HTML parser based on streaming reading, suitable for simple tasks.


For most web scraping tasks, scraper is recommended as it provides a convenient API and active community support.



Installation and Setup



Add the dependency to your Cargo.toml file:



[dependencies]scraper = "0.20"reqwest = { version = "0.12", features = ["blocking"] }


The reqwest library is used for HTTP requests. If you prefer an asynchronous approach, use reqwest with tokio.



Example 1: Extracting Page Titles



Let's write a simple parser that gets the <title> tag and all <h1> headings from a web page:



use scraper::{Html, Selector};

fn main() -> Result<(), Box<dyn std::error::Error>> { let html = r#" <html> <head><title>Example Page</title></head> <body> <h1>First Heading</h1> <h1>Second Heading</h1> </body> </html> "#;

let document = Html::parse_document(html);

// Extract title let title_selector = Selector::parse("title").unwrap(); if let Some(title_element) = document.select(&title_selector).next() { let title_text = title_element.text().collect::().join(""); println!("Page title: {}", title_text); }

// Extract all h1 let h1_selector = Selector::parse("h1").unwrap(); for element in document.select(&h1_selector) { let text = element.text().collect::().join(""); println!("H1: {}", text); }

Ok(())}


In this example, we parse static HTML. For real websites, HTML is typically obtained via an HTTP request.



Example 2: Parsing a Real Website with an HTTP Request



Now let's use reqwest to load a page and extract links:



use scraper::{Html, Selector};

fn main() -> Result<(), Box<dyn std::error::Error>> { let response = reqwest::blocking::get("https://www.rust-lang.org")?; let html = response.text()?;

let document = Html::parse_document(&html); let link_selector = Selector::parse("a[href]").unwrap();

println!("Links on the page:"); for link in document.select(&link_selector) { if let Some(href) = link.value().attr("href") { let text = link.text().collect::(); println!(" Text: '{}' -> URL: {}", text.trim(), href); } }

Ok(())}


Note the attr("href") method — it allows you to get the va

Recommendations