Jsoup и Stream API в Java: парсинг HTML и анализ данных

Сбор информации с веб-страниц остаётся частой задачей: от мониторинга цен до наполнения контентом. Jsoup — это Java-библиотека, которая берёт на себя всю рутину парсинга HTML, а Stream API позволяет элегантно обработать извлечённые данные. В этой статье мы разберём, как подключить jsoup java к проекту, извлечь нужные элементы и превратить их в осмысленный результат с помощью цепочек фильтрации и преобразования.


Добавление Jsoup в проект

Для проектов на Maven или Gradle подключение занимает одну строку. Ниже пример для Gradle (Kotlin DSL), который чаще всего используется в современных Java-проектах на Android Studio, но подойдёт и для любого другого окружения.

dependencies {
    implementation("org.jsoup:jsoup:1.17.2")
}

Для Maven-проекта артефакт указывается в pom.xml. После синхронизации можно сразу начинать работу — Jsoup не требует настройки, поскольку работает напрямую с HTTP-соединениями и HTML-парсером.


Загрузка HTML-документа

Главный класс библиотеки — Jsoup (обратите внимание на заглавную «J» и строчную «soup»). Он предоставляет статический метод connect, который возвращает объект Document — готовую модель страницы.

Document doc = Jsoup.connect("https://example.com").get();

Этот короткий вызов отправляет GET-запрос, получает ответ и строит DOM-дерево. Для работы с файлами или строками есть методы Jsoup.parse().


Извлечение данных через CSS-селекторы

Jsoup поддерживает CSS-селекторы, что делает код интуитивно понятным для фронтенд-разработчиков. Метод select() возвращает список элементов Elements, который можно сразу преобразовать в коллекцию объектов.

Elements titles = doc.select("h2.product-title");
for (Element title : titles) {
    System.out.println(title.text());
}

Но цикл — это лишь первый шаг. Дальше мы подключим Stream API, чтобы работать с данными в декларативном стиле.


Обработка спарсенного через Stream API

Класс Elements наследует ArrayList<Element>, поэтому к нему можно сразу применить потоковые операции. Например, отфильтруем товары, в названии которых встречается слово «скидка», и соберём их в список строк.

List<String> discounted = titles.stream()
    .filter(e -> e.text().toLowerCase().contains("скидка"))
    .map(Element::text)
    .collect(Collectors.toList());

Такой код читается как последовательность действий: отобрать, выделить текст, собрать. В реальных проектах цепочки могут быть длиннее — с сортировкой, группировкой и преобразованием в объекты.


Практический пример: сбор курсов валют

Допустим, мы хотим с определённого сайта получить курсы валют и отфильтровать только те, что выше порогового значения. Сначала получаем строки таблицы, а затем обрабатываем их через стрим.

Document doc = Jsoup.connect("https://example.com/courses").get();
Elements rows = doc.select("table.rates tr");
List<Double> highRates = rows.stream()
    .skip(1) // пропускаем заголовок
    .map(row -> row.select("td").get(2).text()) // третья колонка
    .map(Double::parseDouble)
    .filter(rate -> rate > 90.0)
    .collect(Collectors.toList());

Мы объединили парсинг, потоковую обработку и фильтрацию в несколько строк. При этом Jsoup гарантирует, что HTML распознан корректно, а Stream API делает код лаконичным.


Основные операции Stream API для парсинга

Ниже перечислены наиболее употребимые методы потоков, которые пригодятся при работе с данными, полученными через jsoup java:

  • filter — отсеивает элементы по условию.
  • map — преобразует каждый элемент в другой объект.
  • sorted — сортирует (можно передать компаратор).
  • distinct — убирает дубликаты.
  • limit — оставляет только первые N элементов.
  • collect — собирает результат в коллекцию (Collectors.toList, toSet, joining).
  • forEach — выполняет действие для каждого элемента.

Обработка ошибок при парсинге

Сеть нестабильна, сайт может вернуть 404 или поменять вёрстку. Jsoup выбрасывает проверяемые исключения, поэтому любой запрос нужно оборачивать в try-catch. Stream API здесь не поможет — обработку ошибок лучше выполнять на уровне получения документа.

try {
    Document doc = Jsoup.connect(url).timeout(5000).get();
    // обработка
} catch (IOException e) {
    e.printStackTrace();
}

Также полезно использовать ignoreHttpErrors(true), если вы хотите получать тело ответа даже при ошибке (например, для анализа содержимого 404-страницы).


Итоговые мысли

Связка Jsoup и Stream API — мощный инструмент для любого Java-разработчика, который работает с данными из интернета. Библиотека решает проблему загрузки и навигации по HTML, а потоки позволяют писать чистый и быстрый код обработки. Освоив этот подход, вы сможете легко создавать парсеры для мониторинга, агрегации контента и аналитики, не прибегая к громоздким решениям.