Вход Регистрация

Парсинг

Обзор лучших библиотек для веб-скрапинга на Java

Узнайте о лучших библиотеках Java для веб-скрапинга, их возможностях, применении и преимуществах. Найдите подходящие инструменты для эффективного сбора данных.

Команда Froxy 16 янв 2025 8 мин
Обзор лучших библиотек для веб-скрапинга на Java

Существует много языков программирования. Естественно, практически любой из них можно использовать для web-скрейпинга: Java, Python, Go, C# и т.д. Вопрос не только в личных предпочтениях, но и в наборе уже существующих библиотек и фреймворков, так как последние часто используются для быстрого старта – ускорения написания прикладных программ.

Эта статья не о выборе лучшей платформы для разработки, а о конкретном языке: Java. А точнее о наиболее востребованных библиотеках, которые помогают в создании собственных web-парсеров на Java.

Почему Java является популярным выбором для веб-парсинга

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

Во-вторых, Java – очень популярный язык. Он обладает хорошей производительностью и отлично показывает себя при работе со сложной логикой.

В-третьих, Java предлагает достаточный ассортимент готовых библиотек и фреймворков для парсинга HTML и XML документов.

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

Обзор популярных библиотек Java для веб-скрапинга

Библиотеки – это набор готовых классов и методов для определённых задач. Так как Java используется в разных сферах, под него создано достаточно специфичных библиотек.

Ниже мы собрали только те, которые помогут вам с созданием парсеров. Начнём с самой популярной и практически незаменимой библиотеки – Jsoup. Это как BeautifulSoup для Python.

Jsoup

jsoup

Java-библиотека с открытым исходным кодом, которая предназначена для анализа структуры HTML-кода. А ведь именно HTML-код передаётся в ответ на любой HTTP/HTTPS-запрос. Напомним, HTTP расшифровывается как HyperText Transfer Protocol (протокол передачи гипертекста). Благодаря тому, что jsoup поддерживает актуальную спецификацию WHATWG HTML5, вы можете получать и рендерить код страницы так, как это делают современные браузеры (ведь они работают с той же спецификацией).

Разработка библиотеки ведётся с 2009 года. С помощью jsoup можно получать HTML-код с конкретных URL-адресов, а также из файлов, извлекать данные на основе HTML-тегов и CSS-селекторов, устанавливать свои атрибуты, перемещаться по странице, заполнять и отправлять формы, и многое другое. Jsoup имеет хорошо документированный API.

Преимущества

  • Открытый исходный код и регулярные обновления.
  • Поддержка спецификации WHATWG HTML5 (как в современных браузерах).
  • Удобный синтаксис для web-парсинга на Java.
  • Поддержка XML и ASCII.
  • Подробная документация и сборник рецептов для типовых задач.
  • Встроенный клинер для проверки и очистки небезопасных файлов/HTML-кода.
  • Большой набор методов на все случаи жизни (API для парсинга, работы с DOM-структурой и CSS-селекторами).
  • Минимальный размер (менее 1 Мб).
  • Онлайн-версия библиотеки – для проверки её в работе.
  • Jsoup полностью самодостаточен и не имеет зависимостей.
  • Библиотека работает на Java 8 и всех более поздних версиях.
  • Поддерживается подключение через прокси.

Недостатки

  • Набор методов очень большой, поэтому на их изучение может уйти много времени.
  • Jsoup не умеет обрабатывать динамические сайты, подразумевается только анализ статичных HTML-страниц.
  • При работе с большими документами или частых операциях поиска по DOM-дереву производительность может падать.
  • Хотя библиотека поддерживает базовые CSS-селекторы, она не охватывает все возможности современных селекторов, такие как псевдоклассы.

Примеры кода

// Импортируем библиотекиimport org.jsoup.Jsoup;import org.jsoup.nodes.Document;import org.jsoup.nodes.Element;import org.jsoup.select.Elements;import java.io.IOException;// Простой пример парсинга Википедии, сначала создаём классpublic class Wikipedia {public static void main(String[] args) throws IOException {// Создаём документ и наполняем содержимым с главной страницы ВикипедииDocument doc = Jsoup.connect("http://en.wikipedia.org/").get();// в лог выводим тайтлlog(doc.title());// Получение списка новостейElements newsHeadlines = doc.select("#mp-itn b a");for (Element headline : newsHeadlines) {// Собираем в цикле заголовки с атрибутом title и ссылки с атрибутом hreflog("%s\n\t%s", headline.attr("title"), headline.absUrl("href"));}}// Печатаем свой списокprivate static void log(String msg, String... vals) {System.out.println(String.format(msg, vals));}}

А вот так может выглядеть код парсинга через прокси:

URL url = new URL("http://www.your-taget-site.com/");// здесь данные вашего подключения к проксиProxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 8080));// открываем соединениеHttpURLConnection uc = (HttpURLConnection)url.openConnection(proxy);hc.setRequestProperty("User-Agent", " Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 YaBrowser/24.10.0.0 Safari/537.36");uc.setRequestProperty("Content-Language", "ru-RU");uc.setRequestMethod("GET");uc.connect();// Создаём документ и далее переходим к логике парсингаDocument doc = Jsoup.parse(uc.getInputStream());

HtmlUnit

htmlunit

Это самодостаточный headless-браузер, который изначально написан на Java, чтобы быть кроссплатформенным и легко сочетаться с другими скриптами и программами, написанными на Java. Но благодаря высокоуровневому API, может работать с любыми другими языками программирования. В отличие от более популярных безголовых браузеров, вообще не имеет графического интерфейса. Но зато потребляет минимум ресурсов и обеспечивает обработку сайтов с максимальной скоростью.

Умеет обрабатывать JavaScript и Ajax, а также куки, поддерживает HTTPS-протокол, отправку форм и адекватно эмулирует поведение пользователей. Разработка ведётся с 2002 года. Код открыт по лицензии Apache 2.0. Библиотека идеальна для автоматизирования тестов (при веб-разработке), а также для скрапинга контента.

Преимущества

  • Высокоуровневое API и кроссплатформенность (за счёт запуска в Java-машинах).
  • Возможность имитации любых реальных браузеров (Chrome, Edge, Firefox и т.п.).
  • Обработка JavaScript (динамических сайтов) и Ajax.
  • Возможность скачивания файлов и отправки данных через формы. Поддерживаются все стандартные http-методы (POST, GET, DELETE, HEAD и т.п.).
  • Работа с куками.
  • Библиотека портирована на .Net + есть специальная версия для интеграции c Android-приложениями.
  • Есть готовый web-драйвер для интеграции с Selenium.
  • Прокси поддерживаются из коробки.
  • Встроенный парсер HTML.

Недостатки

  • За рендеринг JavaScript отвечает модифицированная версия движка Rhino (разрабатывается Mozilla). Этот движок сам по себе имеет массу проблем из-за обеспечения обратной совместимости и уже устарел. В новых версиях Firefox Mozilla использует другой движок (SeaMonkey), поэтому Rhino поддерживается не так активно, как раньше.
  • HtmlUnit не имеет графического интерфейса, поэтому вы не сможете обнаружить проблемы с рендерингом (а неправильный рендеринг, например, шрифтов, может использоваться для блокировки ботов).
  • В этот браузер нельзя установить плагины. А они могут быть важны для определённых задач.
  • HtmlUnit не использует при рендеринге аппаратное ускорение, как все современные браузеры с графическим интерфейсом. Что может приводить к существенным задержкам в обработке сайтов с большим количеством внешних JS-скриптов.

Примеры кода

Вот так может выглядеть процесс подключения через прокси с авторизацией:

public void homePage_proxy() throws Exception {try (final WebClient webClient = new WebClient(BrowserVersion.CHROME, PROXY_HOST, PROXY_PORT)) {//Использование прокси с авторизациейfinal DefaultCredentialsProvider credentialsProvider = (DefaultCredentialsProvider) webClient.getCredentialsProvider();credentialsProvider.addCredentials("логин", "пароль", PROXY_HOST, PROXY_PORT);final HtmlPage page = webClient.getPage("https://целевой-домен.зона");Assert.assertEquals("Заголовок страницы: ", page.getTitleText());}}

Selenium

selenium

Это набор библиотек и инструментов для автоматизации практически любых браузеров. Selenium выступает в роли прослойки, организующей API-интерфейс через специальные web-драйверы. Драйверы разработаны для всех известных браузеров и платформ: Firefox, Chrome, Safari, Edge и т.д. Поддерживается даже обозначенный выше HtmlUnit и интеграция с большинством антидетект-браузеров. Selenium работает во всех десктопных операционных системах: Windows, Linux, MacOS. Специально для оригинальной IDE-системы был создан свой собственный язык команд – Selenese.

Проект существует с 2004 года. В настоящее время предоставляются не только веб-драйверы, но и IDE-система, docker-контейнеры, а также система управления большим количеством браузеров (в том числе на удалённых серверах) – Selenium Grid. Поддерживается одновременно несколько языков программирования, в том числе Java.

Читайте также: Cравнение инструментов для тестирования сайтов (Selenium, Playwright, Puppeteer, Lighthouse).

Преимущества

  • Вы получаете возможность удалённого управления любыми реальными браузерами (даже если у них нет своего API-интерфейса).
  • Так как сайт загружается в полноценном браузере, то весь код и скрипты отрабатывают максимально корректно, в том числе с поддержкой аппаратного ускорения.
  • Для Chrome вместо веб-драйвера можно использовать обращения по оригинальному API (DevTools Protocol, примерно, как это делает библиотека chromedp).
  • Можно имитировать любые действия пользователя: перемещать указатель, заполнять поля, отправлять и скачивать файлы, кликать и т.п.
  • Исчерпывающая кроссплатформенность и поддержка разных языков программирования.
  • Готовое решение для управления браузерами на удалённых ПК/серверах.
  • Поддержка асинхронных запросов и возможность ожидания определённых элементов на странице.
  • Поиск элементов на странице и взаимодействие с ними.
  • Возможность создания скриншотов и PDF-версий страниц.

Недостатки

  • Официально поддерживаемых браузеров только пять: Chrome, Safari, Edge, Internet Explorer и Firefox. Вебдрайвера к остальным нужно искать отдельно (обычно их можно найти в GitHub-хранилищах самих браузеров).
  • Порог входа достаточно высокий. Не каждый сможет разобраться с процессами установки и настройки веб-драйверов.
  • Синтаксис встроенного парсера слабый, поэтому в сложных задачах нужно задействовать синтаксис других библиотек и анализаторов (XPath).

Примеры кода

Типовое использование вебдрайвера Selenium для Java-парсера:

package dev.selenium.hello;// Импорт библиотекimport org.openqa.selenium.WebDriver;import org.openqa.selenium.chrome.ChromeDriver;// Запуск экземпляра Headless-браузераpublic class HelloSelenium {public static void main(String[] args) {// Подключение к Google ChromeWebDriver driver = new ChromeDriver();// Открытие страницыdriver.get("https://selenium.dev");// Закрытие браузераdriver.quit();}}

А это пример кода для сбора текстового содержимого из элемента:

// В примере находим первый элемент с тегом H1 и копируем его содержимоеString text = driver.findElement(By.tagName("h1")).getText();System.out.println(text);

Больше предметных примеров веб-скраперов на Java можно найти в официальном репозитории.

Apache Nutch

Apache Nutch

Это готовая реализация web-парсера на Java, написанная и поддерживаемая под крылом команды Apache. Позиционируется как web-краулер с открытым исходным кодом. В отдельных источниках систему называют фреймворком для построения своих поисковых систем (теоретически можно создать свой аналог Google). Имеет модульную расширяемую структуру. Итоговый проект может работать как на одной машине, так и в распределённой среде – в кластере Hadoop. Собранные данные могут индексироваться такими поисковыми движками, как Elasticsearch и Apache Solr.

Обратите внимание, была попытка разработки Apache Nutch 2.0, которая предназначалась для работы с абстрактными хранилищами данных, но от неё отказались. Получается, что первая ветка является наиболее актуальной (она развивается и по сей день).

Преимущества

  • Вы получаете готовый Java-парсер, которым можно управлять из командной строки.
  • При желании парсер расширяется и дополняется. Есть официальные и неофициальные плагины.
  • Задания на парсинг можно составлять на основе регулярных выражений и больших списков URL (можно спарсить хоть весь Интернет).
  • Система сама может находить дубликаты и избавляться от них.
  • Данные по результатам краулинга хранятся в индексированном виде, что облегчает их поиск и выгрузку.
  • Nutch может устанавливаться на сервер или в распределённых кластерах.
  • Поддерживается REST API. Есть готовые docker-контейнеры.
  • Возможна работа через прокси (достаточно правильно отредактировать конфиги).
  • Поддерживается работа через web-драйвер Selenium.

Недостатки

  • Nutch достаточно сложный в управлении. Фактически нужно предварительно изучить возможности API системы. Всё делается только из консоли (графических интерфейсов нет).
  • Не менее сложная установка и настройка. Особенно, если вы хотите интегрировать краулер с локальным поисковым движком.
  • Встроенный парсер не умеет работать с динамическими сайтами (написанными на JavaScript). А интеграцию с Selenium нужно ещё уметь настроить.
  • Объём кода нереально большой. Использование Nutch в качестве парсера чем-то напоминает стрельбу из пушки по воробьям.
  • Вся документация хранился в Atlassian. А сервис блокирует весь трафик из РФ, соответственно, разработчикам с российскими IP потребуются прокси для доступа.

Примеры кода

Если вы справитесь с установкой базового окружения, то останется только:

  • Изменить настройка краулера (делается это в конфиге conf/nutch-site.xml).
  • Поправить фильтры на основе регулярных выражений (файл conf/regex-urlfilter.txt).
  • Добавить списки URL на парсинг (для этого создаётся каталог urls/ и в нём файл seed.txt, адреса записываются каждый на новой строке).
  • Запустить краулер (команда для консоли может выглядеть так - bin/nutch crawl urls -dir crawl -depth 3 -topN 5).

При желании к nutch можно обращаться из своего Java-кода:

import org.apache.hadoop.conf.Configuration;import org.apache.nutch.crawl.Crawl;import org.apache.nutch.fetcher.Fetcher;import org.apache.nutch.util.NutchConfiguration;public class NutchScraper { public static void main(String[] args) throws Exception { // Инициализируем экземпляр NutchString url = "https://здесь.целевой.url/";// Создаём конфигурациюConfiguration conf = NutchConfiguration.create(); Crawl nutch = new Crawl(conf);// Передаём URL на краулинг nutch.crawl(url); Fetcher fetcher = new Fetcher(conf); fetcher.fetch(url); // Выводим в консоли Тайтл сайтаSystem.out.println("Тайтл сайта: " + fetcher.getPage().getTitle()); }

WebMagic

Это ещё один готовый java-фреймворк, предназначенный для ускорения создания своих собственных парсеров. В отличие от Apache Nutch намного проще как в реализации, так и в настройке.

Преимущества

  • Из коробки есть поддержка многопоточности.
  • Легко настраивается интеграция с Selenium.
  • Простой синтаксис для извлечения данных с сайта – поддерживается XPath и селекторы CSS.
  • Максимально быстрый старт и простая настройка.
  • Готовые примеры применения.
  • Лёгкая интеграция со своими java-программами.
  • Асинхронность из коробки.
  • Удобная конвейерная обработка запросов и настраиваемый планировщик.

Недостатки

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

Примеры кода

Вот так может выглядеть код Java-парсера:

public static void main(String[] args) {Spider.create(new GithubRepoPageProcessor())// здесь указывается стартовая страница.addUrl("https://целевой.url").addPipeline(new JsonFilePipeline("D:\\site-files\\"))// Открываем 2 потока.thread(2)// Запускаем паука.run();}

А вот так выглядит полный код для создания парсера, который приводится в официальной документации (скрипт парсит раздел на GitHub):

import us.codecraft.webmagic.Page;import us.codecraft.webmagic.Site;import us.codecraft.webmagic.Spider;import us.codecraft.webmagic.processor.PageProcessor;// Тут создаётся обработчик со всей важной логикой и регулярными выражениямиpublic class GithubRepoPageProcessor implements PageProcessor {// Определяем числа попыток коннекта и таймер ожиданияprivate Site site = Site.me().setRetryTimes(3).setSleepTime(100);@Overridepublic void process(Page page) {// Тут описывается структура запросов – URL-адресов и получается HTML-кодpage.addTargetRequests(page.getHtml().links().regex("(https://github\\.com/\\w+/\\w+)").all());// Тут формируется поле «Автор»page.putField("author", page.getUrl().regex("https://github\\.com/(\\w+)/.*").toString());// А тут поле «Имя» - на основе заголовка H1page.putField("name", page.getHtml().xpath("//h1[@class='entry-title public']/strong/a/text()").toString());// Если имя пустоеif (page.getResultItems().get("name")==null){// Игнорировать страницы с пустыми именамиpage.setSkip(true);}// А тут описываем логику заполнения поля readmepage.putField("readme", page.getHtml().xpath("//div[@id='readme']/tidyText()"));}@Overridepublic Site getSite() {return site;}// Тут задача запускается и передаётся обработчику – для парсинга конкретного раздела сайта в 5 потоковpublic static void main(String[] args) {Spider.create(new GithubRepoPageProcessor()).addUrl("https://github.com/code4craft").thread(5).run();}}

 

Резидентные прокси

Идеальные прокси для получения ценных данных со всего мира.

Начать с триала

Проблемы и ограничения веб-скрапинга на Java

Как мы уже упомянули выше, язык Java весьма неплохо показывает себя при написании парсеров. Но есть и проблемы, с которыми можно столкнуться в процессе разработки. Наиболее существенные ограничения опишем ниже:

  • Java-приложения выполняются в специальной среде – JVM (Java Virtual Machine). С одной стороны, это позволяет отвязаться от программной платформы (операционной системы), а с другой, накладывает свои ограничения и подразумевает определённые технические требования. У JVM много версий и у каждой свои технические особенности.
  • Автоматическое управление памятью идёт на пользу новичкам, но, если объём данных, с которыми работает скрипт, увеличивается (что нельзя назвать редкостью при парсинге), могут случаться утечки. Чтобы исправить такую ошибку, придётся кардинально пересмотреть архитектуру программы. Такое под силу только настоящим профи. В частности, утечки часто бывают в браузере HtmlUnit, там обычно виноват движок рендеринга. Поэтому в случае ошибок его советуют отключить.
  • Строгая типизация и оригинальные требования к подключению сторонних модулей/библиотек, могут оттолкнуть начинающих разработчиков. Погружение в Java намного сложнее, если сравнивать язык с Python или Go.
  • Количество готовых библиотек и фреймворков для web-парсинга на Java не такое впечатляющее, как для Python. Так исторически сложилось, что Питон оказался востребованнее при работе с данными и скрейпингом.

Плюс, не стоит забывать об особенностях написания web-парсеров (как класса ПО).

  • Многие сайты защищаются от мусорного трафика, чтобы снизить нагрузку на свои серверы. В результате проверяется множество параметров сессии и браузера, в котором работает пользователь. По этой причине нужно уделять особое внимание не только HTTP-заголовкам и юзер-агенту, но и уметь имитировать другие параметры. Всё это требует профильных знаний и глубокого погружения.
  • Некоторые системы защиты не получится обойти такими решениями, как HtmlUnit. Дело в том, что у упомянутого браузера нет полноценного аппаратного рендеринга, что неизбежно приводит к специфическим смещениям и несовпадениям в итоговой структуре документа. Этим активно пользуются системы защиты сайтов.
  • Не менее важна поддержка JavaScript. Многие современные сайты представляют собой полноценные web-приложения. Если в браузере отключена поддержка JavaScript, то сайты могут просто перестать работать. Вывод – нужно использовать headless-браузеры, которые могут задействовать аппаратный рендеринг.
  • Работа через headless-браузеры приводит к серьёзному потреблению ресурсов и к дополнительным задержкам. Соответственно, в скриптах важно заботиться об асинхронности.
  • Ещё одна сложность – проверка цифровых отпечатков. Чтобы обойти такую защиту, нужно качественно имитировать действия пользователя, правдоподобно наполнять его куки, историю просмотра и другие параметры. А если у вас многопоточное сканирование, то у каждого пользователя должен быть свой цифровой отпечаток. Чтобы хранить и обрабатывать большое число независимых браузерных профилей, нужен качественный антидетект-браузер.
  • Так как многие механизмы защиты привязываются к IP-адресам клиентов, логично их менять с определённой частотой или вообще при каждом новом запросе. Подробнее о ротируемых прокси. Качество и тип адресов имеют значение. Самыми надёжными для парсинга можно назвать мобильные и резидентные прокси.

Более подробный гайд о парсинге без блокировок

Заключение и рекомендации

conclusion

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

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

Если вам не хватает качественных ротируемых прокси с глобальным охватом, чтобы запустить свой парсер, обратите внимание на Froxy. Наш сервис предлагает более 10 млн. IP адресов: мобильных, резидентных и серверных. Таргетинг до города и оператора связи. Оплачивается только трафик. Количество портов может быть очень большим – до 1000 штук.

Получайте уведомления о новых функциях и обновлениях Froxy

Узнайте первыми о новых функциях Froxy, чтобы оставаться в курсе событий происходящих на рынке цифровых технологий и получать новости о новых функциях Froxy.

Статьи по Теме