Существует много языков программирования. Естественно, практически любой из них можно использовать для web-скрейпинга: Java, Python, Go, C# и т.д. Вопрос не только в личных предпочтениях, но и в наборе уже существующих библиотек и фреймворков, так как последние часто используются для быстрого старта – ускорения написания прикладных программ.
Эта статья не о выборе лучшей платформы для разработки, а о конкретном языке: Java. А точнее о наиболее востребованных библиотеках, которые помогают в создании собственных web-парсеров на Java.
Почему Java является популярным выбором для веб-парсинга
Во-первых, Java является одним из первых кроссплатформенных языков программирования. Благодаря Java-машинам, программный код Java можно запустить практически в любой операционной системе. Все должны помнить игры на кнопочных телефонах. Так вот они были написаны на Java.
Во-вторых, Java – очень популярный язык. Он обладает хорошей производительностью и отлично показывает себя при работе со сложной логикой.
В-третьих, Java предлагает достаточный ассортимент готовых библиотек и фреймворков для парсинга HTML и XML документов.
В-четвёртых, не стоит забывать о многопоточности. Здесь у Java полный порядок. Он обеспечивает эффективное распределение задач между несколькими потоками одновременно и позволяет значительно ускорить процесс сбора данных с большого числа страниц или сайтов.
Обзор популярных библиотек Java для веб-скрапинга
Библиотеки – это набор готовых классов и методов для определённых задач. Так как Java используется в разных сферах, под него создано достаточно специфичных библиотек.
Ниже мы собрали только те, которые помогут вам с созданием парсеров. Начнём с самой популярной и практически незаменимой библиотеки – Jsoup. Это как BeautifulSoup для Python.
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

Это самодостаточный 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 выступает в роли прослойки, организующей 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

Это готовая реализация 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-адресам клиентов, логично их менять с определённой частотой или вообще при каждом новом запросе. Подробнее о ротируемых прокси. Качество и тип адресов имеют значение. Самыми надёжными для парсинга можно назвать мобильные и резидентные прокси.
Более подробный гайд о парсинге без блокировок
Заключение и рекомендации

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

