CoderCastrov logo
CoderCastrov
Русский

Парсинг веб-страниц с помощью Rust

Парсинг веб-страниц с помощью Rust
просмотров
7 мин чтение
#Русский

В этой статье мы узнаем о парсинге веб-страниц с помощью Rust. Возможно, многие из вас еще не слышали о этом языке, но в этом руководстве мы постепенно изучим Rust. Это руководство будет сосредоточено на парсинге веб-страниц, а затем я расскажу о преимуществах и недостатках использования Rust.

Мы будем парсить этот веб-сайт с использованием двух популярных библиотек Rust - **reqwest** и **scraper**. Мы расскажем о этих библиотеках немного позже. По окончании этого руководства у вас будет базовое представление о том, как работает Rust и как его можно использовать для парсинга веб-страниц.

Что такое Rust?

Rust - это высокоуровневый язык программирования, разработанный самой Mozilla. Он создан с основным акцентом на создание программного обеспечения. Он отлично работает, когда речь идет о низкоуровневой манипуляции памятью, подобной указателям в C и C++. Конкурентные соединения также довольно стабильны в Rust. Несколько компонентов программного обеспечения могут работать независимо и одновременно без излишней нагрузки на сервер.

Обработка ошибок также на высоком уровне, поскольку ошибки конкурентности являются ошибками времени компиляции, а не времени выполнения. Это экономит время, и будет показано правильное сообщение об ошибке.

Этот язык также используется в разработке игр и инструментов на основе блокчейна. Многие крупные компании, такие как AWS, Microsoft и др., уже используют этот язык в своей архитектуре.

Настройка предварительных требований

Предполагается, что вы уже установили Rust и Cargo (менеджер пакетов Rust) на вашем компьютере, и если нет, то вы можете обратиться к этому руководству для получения дальнейших инструкций по установке Rust. Сначала нам нужно создать проект на Rust.

cargo new rust_tutorial

Затем нам нужно установить две библиотеки Rust, которые будут использоваться в ходе этого учебника.

  • [**_reqwest_**](https://docs.rs/reqwest/latest/reqwest/): Она будет использоваться для установления HTTP-соединения с веб-сайтом-хостом.
  • [**_scraper_**](https://docs.rs/scraper/latest/scraper/)_: _Она будет использоваться для выбора элементов DOM и разбора HTML.

Обе эти библиотеки можно установить, добавив их в файл cargo.toml.

[dependencies]

reqwest = "0.10.8"
scraper = "0.12.0"

Обе версии 0.10.8 и 0.12.0 являются последними версиями библиотек. Теперь, наконец, вы можете получить к ним доступ в вашем основном файле проекта src/main.rs.

Что мы парсим?

Всегда лучше решить, что вы хотите спарсить. Мы будем парсить названия и цены отдельных книг с страницы.

Процесс будет довольно простым. Сначала мы проверим Chrome, чтобы определить точное местоположение этих элементов в DOM, а затем мы будем использовать библиотеку scraper для их парсинга.

Парсинг данных отдельных книг

Давайте спарсим названия книг и цены пошагово. Сначала вам нужно определить местоположение элемента в DOM.

Как вы можете видеть на приведенном выше изображении, название книги хранится внутри атрибута title тега a. Теперь давайте посмотрим, где хранится цена.

Цена хранится внутри тега p с классом price_color. Теперь давайте напишем код на Rust и извлечем эти данные.

Первый шаг - импортировать все необходимые библиотеки в основной файл src/main.rs.

use reqwest::Client;
use scraper::{Html, Selector};

С помощью reqwest мы собираемся установить HTTP-соединение с веб-сайтом-хостом, а с помощью библиотеки scraper мы собираемся разобрать HTML-контент, который мы получим, сделав GET-запрос через библиотеку reqwest.

Теперь нам нужно создать клиент, который можно будет использовать для отправки запросов на соединение с помощью reqwest.

let client = Client::new();

Затем, наконец, мы отправим GET-запрос на наш целевой URL с использованием только что созданного client.

let mut res = client.get("http://books.toscrape.com/")
    .send()
    .unwrap();

Здесь мы использовали модификатор mut, чтобы привязать значение к переменной. Это улучшает читаемость кода, и если вы измените это значение в будущем, вам может потребоваться изменить и другие части кода.

После отправки запроса вы получите ответ в формате HTML. Но вам нужно извлечь эту строку HTML из переменной res с помощью .text().unwrap(). .unwrap() похож на try-catch, где он просит программу предоставить результаты, и если возникнет ошибка, он просит программу остановить выполнение как можно скорее.

let body = res.text().unwrap();

Здесь res.text().unwrap() вернет строку HTML, и мы сохраняем эту строку в переменной body.

Теперь у нас есть строка, через которую мы можем извлечь все данные, которые нам нужны. Прежде чем мы будем использовать библиотеку scraper, нам нужно преобразовать эту строку в объект scraper::Html с помощью Html::parse_document.

let document = Html::parse_document(&body);

Теперь этот объект можно использовать для выбора элементов и навигации к нужному элементу.

Сначала давайте создадим селектор для названия книги. Мы собираемся использовать функцию Selector::parse для создания объекта scraper::Selector.

let book_title_selector = Selector::parse("h3 > a").unwrap();

Теперь этот объект можно использовать для выбора элементов из HTML-документа. Мы передали h3 > a в качестве аргументов в функцию parse. Это CSS-селектор для элементов, которые нас интересуют. h3 > a означает, что он будет выбирать все теги a, которые являются дочерними элементами тегов h3.

Как вы можете видеть на изображении, целевой тег a является дочерним элементом тега h3. Поэтому мы использовали h3 > a в вышеприведенном коде.

Поскольку книг так много, мы будем перебирать их все с помощью цикла for.

for book_title in document.select(&book_title_selector) {
    let title = book_title.text().collect::<Vec<_>>();
    println!("Title: {}", title[0]);
}

Метод select предоставит нам список элементов, которые соответствуют селектору book_title_selector. Затем мы перебираем этот список, чтобы найти атрибут title и, наконец, вывести его.

Здесь Vec<_> представляет собой динамический массив. Это вектор, в котором вы можете получить доступ к любому элементу по его позиции в векторе.

Следующий и последний шаг - извлечение цены.

let book_price_selector = Selector::parse(".price_color").unwrap();

Опять же, мы использовали функцию Selector::parse для создания объекта scraper::Selector. Как уже обсуждалось выше, цена хранится внутри класса price_color. Поэтому мы передали это в качестве CSS-селектора в функцию parse.

Затем мы снова будем использовать цикл for, как мы делали выше, чтобы перебрать все элементы цены.

for book_price in document.select(&book_price_selector) {
    let price = book_price.text().collect::<Vec<_>>();
    println!("Price: {}", price[0]);
}

Как только вы найдете соответствие селектора, он получит текст и выведет его в консоль.

Наконец, мы завершили код, который может извлекать название и цену с целевого URL. Теперь, когда вы сохраните это и запустите код с помощью cargo run, вы получите вывод, который выглядит примерно так.

Title: A Light in the Attic
Price: £51.77
Title: Tipping the Velvet
Price: £53.74
Title: Soumission
Price: £50.10
Title: Sharp Objects
Price: £47.82
Title: Sapiens: A Brief History of Humankind
Price: £54.23
Title: The Requiem Red
Price: £22.65
Title: The Dirty Little Secrets of Getting Your Dream Job
Price: £33.34
Title: The Coming Woman: A Novel Based on the Life of the Infamous Feminist, Victoria Woodhull
Price: £17.93
Title: The Boys in the Boat: Nine Americans and Their Epic Quest for Gold at the 1936 Berlin Olympics
Price: £22.60
Title: The Black Maria
Price: £52.15

Полный код

Вы можете внести изменения в код, чтобы извлечь другую информацию, такую как рейтинги, изображения книг и т. д. Вы можете использовать ту же технику, сначала осмотрев и нашедя местоположение элемента, а затем извлекая их с помощью функции Selector.

Но пока код будет выглядеть так.

use reqwest::Client;
use scraper::{Html, Selector};

// Создаем нового клиента
let client = Client::new();

// Отправляем GET-запрос на веб-сайт
let mut res = client.get("http://books.toscrape.com/")
    .send()
    .unwrap();

// Извлекаем HTML из ответа
let body = res.text().unwrap();

// Разбираем HTML в документ
let document = Html::parse_document(&body);

// Создаем селектор для названий книг
let book_title_selector = Selector::parse("h3 > a").unwrap();

// Перебираем названия книг
for book_title in document.select(&book_title_selector) {
    let title = book_title.text().collect::<Vec<_>>();
    println!("Название: {}", title[0]);
}

// Создаем селектор для цен книг
let book_price_selector = Selector::parse(".price_color").unwrap();

// Перебираем цены книг
for book_price in document.select(&book_price_selector) {
    let price = book_price.text().collect::<Vec<_>>();
    println!("Цена: {}", price[0]);
}

Преимущества использования Rust

  • Rust - эффективный язык программирования, подобный C++. Вы можете создавать сложные игры и программное обеспечение с его помощью.
  • Он может обрабатывать большой объем одновременных вызовов, в отличие от Python.
  • Rust даже может взаимодействовать с языками программирования, такими как C и Python.

Недостатки использования Rust

  • Rust - новый язык, если сравнивать его с Nodejs и Python. Из-за небольшого сообщества начинающим очень сложно решить даже небольшую ошибку.
  • Синтаксис Rust не так прост для понимания, как Python или Nodejs. Поэтому становится очень сложно читать и понимать код.

Заключение

Мы узнали, как использовать Rust для парсинга веб-страниц. Используя Rust, вы также можете парсить множество других динамических веб-сайтов. Даже в приведенном выше коде вы можете внести несколько изменений, чтобы парсить изображения и рейтинги. Это наверняка улучшит ваши навыки парсинга веб-страниц с помощью Rust.

Надеюсь, вам понравился этот небольшой учебник, и если да, то пожалуйста, не забудьте поделиться им с друзьями и в социальных сетях.

Дополнительные ресурсы

Вот несколько дополнительных ресурсов, которые могут быть полезными во время вашего путешествия по парсингу веб-страниц: