Существует много языков программирования. Естественно, практически любой из них можно использовать для web-скрейпинга: Java, Python, Go, C# и т.д. Вопрос не только в личных предпочтениях, но и в наборе уже существующих библиотек и фреймворков, так как последние часто используются для быстрого старта – ускорения написания прикладных программ.
Эта статья не о выборе лучшей платформы для разработки, а о конкретном языке: Java. А точнее о наиболее востребованных библиотеках, которые помогают в создании собственных web-парсеров на Java.
Во-первых, Java является одним из первых кроссплатформенных языков программирования. Благодаря Java-машинам, программный код Java можно запустить практически в любой операционной системе. Все должны помнить игры на кнопочных телефонах. Так вот они были написаны на Java.
Во-вторых, Java – очень популярный язык. Он обладает хорошей производительностью и отлично показывает себя при работе со сложной логикой.
В-третьих, Java предлагает достаточный ассортимент готовых библиотек и фреймворков для парсинга HTML и XML документов.
В-четвёртых, не стоит забывать о многопоточности. Здесь у Java полный порядок. Он обеспечивает эффективное распределение задач между несколькими потоками одновременно и позволяет значительно ускорить процесс сбора данных с большого числа страниц или сайтов.
Библиотеки – это набор готовых классов и методов для определённых задач. Так как Java используется в разных сферах, под него создано достаточно специфичных библиотек.
Ниже мы собрали только те, которые помогут вам с созданием парсеров. Начнём с самой популярной и практически незаменимой библиотеки – Jsoup. Это как BeautifulSoup для Python.
Java-библиотека с открытым исходным кодом, которая предназначена для анализа структуры HTML-кода. А ведь именно HTML-код передаётся в ответ на любой HTTP/HTTPS-запрос. Напомним, HTTP расшифровывается как HyperText Transfer Protocol (протокол передачи гипертекста). Благодаря тому, что jsoup поддерживает актуальную спецификацию WHATWG HTML5, вы можете получать и рендерить код страницы так, как это делают современные браузеры (ведь они работают с той же спецификацией).
Разработка библиотеки ведётся с 2009 года. С помощью jsoup можно получать HTML-код с конкретных URL-адресов, а также из файлов, извлекать данные на основе HTML-тегов и CSS-селекторов, устанавливать свои атрибуты, перемещаться по странице, заполнять и отправлять формы, и многое другое. Jsoup имеет хорошо документированный API.
Преимущества
Недостатки
Примеры кода
// Импортируем библиотеки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());…
Это самодостаточный headless-браузер, который изначально написан на Java, чтобы быть кроссплатформенным и легко сочетаться с другими скриптами и программами, написанными на Java. Но благодаря высокоуровневому API, может работать с любыми другими языками программирования. В отличие от более популярных безголовых браузеров, вообще не имеет графического интерфейса. Но зато потребляет минимум ресурсов и обеспечивает обработку сайтов с максимальной скоростью.
Умеет обрабатывать JavaScript и Ajax, а также куки, поддерживает HTTPS-протокол, отправку форм и адекватно эмулирует поведение пользователей. Разработка ведётся с 2002 года. Код открыт по лицензии Apache 2.0. Библиотека идеальна для автоматизирования тестов (при веб-разработке), а также для скрапинга контента.
Преимущества
Недостатки
Примеры кода
Вот так может выглядеть процесс подключения через прокси с авторизацией:
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 выступает в роли прослойки, организующей API-интерфейс через специальные web-драйверы. Драйверы разработаны для всех известных браузеров и платформ: Firefox, Chrome, Safari, Edge и т.д. Поддерживается даже обозначенный выше HtmlUnit и интеграция с большинством антидетект-браузеров. Selenium работает во всех десктопных операционных системах: Windows, Linux, MacOS. Специально для оригинальной IDE-системы был создан свой собственный язык команд – Selenese.
Проект существует с 2004 года. В настоящее время предоставляются не только веб-драйверы, но и IDE-система, docker-контейнеры, а также система управления большим количеством браузеров (в том числе на удалённых серверах) – Selenium Grid. Поддерживается одновременно несколько языков программирования, в том числе Java.
Читайте также: Cравнение инструментов для тестирования сайтов (Selenium, Playwright, Puppeteer, Lighthouse).
Преимущества
Недостатки
Примеры кода
Типовое использование вебдрайвера 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 можно найти в официальном репозитории.
Это готовая реализация web-парсера на Java, написанная и поддерживаемая под крылом команды Apache. Позиционируется как web-краулер с открытым исходным кодом. В отдельных источниках систему называют фреймворком для построения своих поисковых систем (теоретически можно создать свой аналог Google). Имеет модульную расширяемую структуру. Итоговый проект может работать как на одной машине, так и в распределённой среде – в кластере Hadoop. Собранные данные могут индексироваться такими поисковыми движками, как Elasticsearch и Apache Solr.
Обратите внимание, была попытка разработки Apache Nutch 2.0, которая предназначалась для работы с абстрактными хранилищами данных, но от неё отказались. Получается, что первая ветка является наиболее актуальной (она развивается и по сей день).
Преимущества
Недостатки
Примеры кода
Если вы справитесь с установкой базового окружения, то останется только:
При желании к 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()); } }
Это ещё один готовый java-фреймворк, предназначенный для ускорения создания своих собственных парсеров. В отличие от Apache Nutch намного проще как в реализации, так и в настройке.
Преимущества
Недостатки
Примеры кода
Вот так может выглядеть код 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 весьма неплохо показывает себя при написании парсеров. Но есть и проблемы, с которыми можно столкнуться в процессе разработки. Наиболее существенные ограничения опишем ниже:
Плюс, не стоит забывать об особенностях написания web-парсеров (как класса ПО).
Более подробный гайд о парсинге без блокировок
Необходимость написания своих парсеров возникает по разным причинам. Но какими бы ни были причины, всегда хочется упростить и без того сложную работу. Как раз для этого можно использовать профильные библиотеки и фреймворки.
Так как Java популярный язык программирования, для него существует достаточно готовых решений и библиотек. Все самые популярные и функциональные мы перечислили выше.
Если вам не хватает качественных ротируемых прокси с глобальным охватом, чтобы запустить свой парсер, обратите внимание на Froxy. Наш сервис предлагает более 10 млн. IP адресов: мобильных, резидентных и серверных. Таргетинг до города и оператора связи. Оплачивается только трафик. Количество портов может быть очень большим – до 1000 штук.