Существует много языков программирования. Естественно, практически любой из них можно использовать для 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 и ссылки с атрибутом href
log("%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 Chrome
WebDriver 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 {
// Инициализируем экземпляр Nutch
String 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);
@Override
public 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());
// А тут поле «Имя» - на основе заголовка H1
page.putField("name", page.getHtml().xpath("//h1[@class='entry-title public']/strong/a/text()").toString());
// Если имя пустое
if (page.getResultItems().get("name")==null){
// Игнорировать страницы с пустыми именами
page.setSkip(true);
}
// А тут описываем логику заполнения поля readme
page.putField("readme", page.getHtml().xpath("//div[@id='readme']/tidyText()"));
}
@Override
public 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 штук.