Как использовать Java для скрейпинга данных в Сети
Содержание:
- Обзор инструментов от сайта прокси сервера
- Основы CSS-селекторов для тех, кого интересует аренда прокси от Dexodata
- Пошаговый гайд по созданию Java-скрейпера
- Тонкости запросов
- Заключение
Dexodata, сайт прокси сервер, предлагающий аренду прокси по цене от 3.65 долларов за 1 Гб, работает с пользователями, которым нужно регулярно собирать данные в интернете. Наша команда наработала в этой сфере экспертный опыт. И мы знаем, что Java — не единственный вариант языка программирования для скриптов дата-харвестинга.
С этими целями люди обращаются и к PHP, и к Node.js, и к C#, и к Python. И все же Java в особенности популярна. В этом материале наша команда расскажет о потенциале данного языка на практических примерах. В дальнейшем читатели смогут обратиться к данному гайду, чтобы применить эти знания на практике, попробовав прокси бесплатно или купив приватные прокси Dexodata.
Обзор инструментов от сайта прокси сервера
Когда речь заходит о парсинге при помощи Java, зачастую упоминаются эти инструменты: JSoup и HtmlUnit.
JSoup работает как действенная и при этом относительно несложная библиотека, способная работать с деформированными документами HTML. Ее потому и называют «JSoup», ведь обозначение «tag soup» применяется как раз к бессистемным блокам данных.
Что касается HtmlUnit, то его можно описать как headless-браузер (т. е. браузер без графического интерфейса), приспособленный для инструментов на основе Java. Он способен имитировать действия, характерные для браузера и, как следует из названия, применяется для юнит-тестирования. То есть, он «симулирует» действия браузера в рамках тестового сценария.
В этом качестве он способен выделять фрагменты, заполнять формы, кликать по элементам и прочее. Для автоматизированного сбора информации в интернете через прокси подобные способности — в самый раз. HtmlUnit на деле упрощает взаимодействие со страницей. Это мы подтверждаем с точки зрения сайта прокси сервера для аренды прокси из пулов адресов с геотаргетингом и ротацией (с нами можно не только купить приватные прокси, но и попробовать прокси бесплатно).
Дополнительный аргумент в пользу HtmlUnit применительно к просмотру веб-страниц и сбору данных: пользователю требуется одна строка кода, чтобы деактивировать как JS, так и CSS.
Важно: Этот гайд предполагает, что читатели уже в какой-то степени освоили Java, а также на достаточном уровне знают Maven. В дополнение к основам Java они должны иметь представление о том, как функционируют веб-страницы с точки зрения HTML. Знакомство с селекторами XPath или CSS также желательно.
Основы CSS-селекторов для тех, кого интересует аренда прокси от Dexodata
Остановимся на секунду, чтобы освежить в памяти релевантные CSS-селекторы:
- #firstname — берет каждый элемент, id которого соответствует «firstname»;
- .blue — берет каждый элемент, класс которого имеет отношение к «.blue»;
- p — берет каждый тег <p>;
- div#firstname — берет базовые элементы <div>, id которых соответствует «firstname»;
- p.link.new — обратите внимание на отсутствие пробелов. Эта часть ответственна за выбор <p class="link new">;
- p.link .new — а вот тут пробел есть. Эта часть ответственна за выбор каждого компонента, относящегося к классу «new», который можно найти внутри <p class="link">.
Пошаговый гайд по созданию Java-скрейпера
На базе опыта, который мы наработали в качестве сайта прокси сервера, Dexodata начинает процесс разработки Java-скрейпера. Делать это мы будем при помощи Maven, JSoup и HtmlUnit.
Результат наших усилий, собственно скрейпер, лучше использовать в комбинации с арендованными прокси с ротацией IP. У новых пользователей, в дополнение к возможности купить приватные прокси, есть право запросить пробный период и попробовать прокси бесплатно.
1. Для начала раздобудем библиотеки.
Здесь поможет Maven. Если она по какой-то причине не подходит, то пройдите на данную веб-страницу, тут есть альтернативы. Мы же работаем с Maven, скачать его можно тут.
Как только установка закончена, запустите там новый проект посредством команды:
mvn archetype:generate -DgroupId=com.mycompany.parser -DartifactId=java-parser -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
Поступив так, пользователи создадут новую проектную папку под названием «java-parser». Это предоставит в их распоряжение все нужные файлы Maven и базовую структуру.
2. Теперь добавим зависимости к файлу pom.xml.
В файле pom.xml («pom» означает «Project Object Model») надо добавить новый раздел для работы с зависимостями в рамках JSoup. Идем к папке «java-parser» и открываем файл pom.xml. Включаем зависимости под тегом <dependencies>:
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.14.3</version>
</dependency>
<dependency>
<groupId>net.sourceforge.htmlunit</groupId>
<artifactId>htmlunit</artifactId>
<version>2.56.0</version>
</dependency>
Сохраняем pom.xml и продолжаем наш маршрут с Dexodata, сайтом прокси сервером и сегодняшним инструктором по созданию скрейперов.
3. Генерируем новый класс Java.
В папке src/main/java/com/mycompany/parser создаем новый файл Java под названием «HtmlParser.java». Данный элемент послужит точкой сборки и входа для будущего парсера.
4. Импортируем нужные библиотеки в «HtmlParser.java».
Откроем файл в текстовом редакторе или же в выбранной среде разработки, а затем проставим эти строки в самом начале файла «HtmlParser.java»:
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
Мы уже проделали немалый путь, продолжаем следовать по заданному маршруту с нашим сайтом прокси сервером.
5. Запустите объект «WebClient» и деактивируйте JS и CSS.
Внутри класса «HtmlParser» задайте методы для создания объекта «WebClient», извлечения HTML с помощью HtmlUnit, анализа содержимого HTML с помощью JSoup и сбора узко определенных данных (таких, как заголовок, описание и изображение) в нужной последовательности.
public class HtmlParser {
private static WebClient createWebClient() {
WebClient webClient = new WebClient();
webClient.getOptions().setJavaScriptEnabled(false);
webClient.getOptions().setCssEnabled(false);
return webClient;
}
}
6. Создаем метод для извлечения HTML посредством HtmlUnit:
public static HtmlPage fetchHtmlPage(String url) {
try (WebClient webClient = createWebClient()) {
return webClient.getPage(url);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
7. Создаем метод для парсинга HTML-контента с JSoup:
public static Document parseHtmlContent(String htmlContent) {
return Jsoup.parse(htmlContent);
}
8. Продолжаем работать с HTML:
public static void extractInformation(Document document) {
// Extract information from the parsed HTML document using JSoup methods
// e.g., document.select("a[href]"), document.select("img[src$=.png]")
// For more details, refer to the JSoup documentation: https://jsoup.org/cookbook/
}
9. Создаем метод для «извлечения» информации из HTML:
public static void main(String[] args) {
String url = "https://www.example.com";
HtmlPage htmlPage = fetchHtmlPage(url);
if (htmlPage != null) {
String htmlContent = htmlPage.asXml();
Как видно, все эти шаги — отнюдь не бином Ньютона. По меньшей мере, если положиться на опыт сайта прокси сервера Dexodata с пулом адресов для аренды прокси по всему миру.
Предыдущая часть охватывала подготовительные меры общего порядка: извлечению HTML-содержимого при помощи HtmlUnit и работе с ним посредством JSoup.
Теперь сосредоточимся на «вытягивании» более конкретных и специфических данных, например, заголовков, описаний и изображений. Чтобы это сделать, надо для начала идентифицировать HTML-теги и атрибуты, связанные с этими компонентами. То есть, необходимо воспользоваться инструментами разработчика, содержащимися в веб-браузерах, и «просканировать» исходный HTML на предмет расположения и оформления таких компонентов.
10. Вообразим типичную ситуацию с веб-магазином. После того как идентифицированы все требуемые компоненты HTML, приходит время использовать расширенные возможности JSoup для получения таких данных.
Предположим, что заголовок находится в теге <h1>, описание — в теге <div> с классом «product-description», а изображение — в теге <img> с классом «product-image». Проставьте эти атрибуты в коде, как сделано во фрагменте ниже. Как видно, применяется метод extractInformation():
public static void extractInformation(Document document) {
// Extract the title
String title = document.select("h1").text();
System.out.println("Title: " + title);
// Extract the description
String description = document.select("div.product-description").text();
System.out.println("Description: " + description);
// Extract the image URL
String imageUrl = document.select("img.product-image").attr("src");
System.out.println("Image URL: " + imageUrl);
}
11. Если сайт, с которым происходит работа, завязан на JavaScript для динамической загрузки контента, надо активировать в HtmlUnit поддержку JS. Сделать это можно за счет вот такой манипуляции с методом «createWebClient()»:
private static WebClient createWebClient() {
WebClient webClient = new WebClient();
webClient.getOptions().setJavaScriptEnabled(true);
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.waitForBackgroundJavaScript(5000); // Wait for JavaScript to finish loading
return webClient;
}
Обратите внимание: включение JavaScript может увеличить время загрузки и создать риск ошибок. Dexodata, как сайт прокси сервер, в курсе регулярных жалоб пользователей на проблемы из-за JS, однако подобные ситуации неизбежны при работе с динамическими страницами.
12. После получения заголовков, описаний и изображений может возникнуть потребность сохранить эту информацию для дальнейшего анализа или обработки.
Распространенным методом является хранение собранной информации в файлах CSV, JSON или XML. В этом сценарии команда сайта прокси сервера Dexodata сохранит информацию в файле CSV. Это происходит следующим образом.
Создаем метод трансформации в CSV:
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public static void writeToCSV(String title, String description, String imageUrl, String outputFilePath) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(outputFilePath, true))) {
String csvLine = String.join(",", "\"" + title.replace("\"", "\"\"") + "\"",
"\"" + description.replace("\"", "\"\"") + "\"",
"\"" + imageUrl.replace("\"", "\"\"") + "\"");
writer.write(csvLine);
writer.newLine();
} catch (IOException e) {
e.printStackTrace();
}
}
Данный подход использует заголовок, описание, imageUrl, а также outputFilePath в качестве входных параметров.
13. Обновите «extractInformation()», чтобы вызвать метод «writeToCSV()» для работы с извлеченной ранее информацией:
public static void extractInformation(Document document, String outputFilePath) {
// Extract the title, description, and image URL as before
// Write the extracted data to the CSV file
writeToCSV(title, description, imageUrl, outputFilePath);
}
14. Также модифицируйте основной метод, чтобы охватить путь к выходному файлу и передать его «extractInformation()»
:
public static void main(String[] args) {
String url = "https://www.example.com";
String outputFilePath = "output.csv";
HtmlPage htmlPage = fetchHtmlPage(url);
if (htmlPage != null) {
String htmlContent = htmlPage.asXml();
Document document = parseHtmlContent(htmlContent);
extractInformation(document, outputFilePath);
}
}
Теперь при запуске парсер берет заголовок, описание и URL-адрес изображения со страницы интернет-магазина и записывает данные в указанный CSV-файл. Есть также возможность дополнительно настроить формат вывода файла, добавить подзаголовки или же сохранить информацию в JSON или XML.
Протестируйте свой парсер, применив главный метод на URL-адреса интернет-магазина. Обязательно настройте селекторы JSoup в соответствии с реальной структурой его страниц. Парсер всегда можно проапгрейдить, чтобы извлечь дополнительную информацию: цены, спецификации или отзывы пользователей.
Анализ бизнес-данных в сфере e-commerce является одним из ключевых сценариев для аренды прокси с геотаргетингом от сайта прокси сервера Dexodata. Так что наша команда знает, насколько полезным может быть такой инструмент.
Тонкости запросов
Посылать запросы на извлечение информации — базовая цель скрейпинговых программ на Java. Применительно к библиотеке JSoup, существует несколько способов получения интересующих нас компонентов. Эти методы включают getElementByID или getElementsByTag. С их помощью серьезно упрощается работы на базе DOM-методов.
Наш сценарий позволяет использовать как getElementByID, так и getElementsByClass. Обратите внимание на важное отличие. В то время как getElementByID (в единственном числе) предназначен для выдачи одного объекта Element, то с getElementsByClass (число уже множественное) будет выдан Array-список, содержащий все подходящие объекты Element.
Удобно, что в JSoup есть класс Elements. Благодаря ему, Array-список <Element> может быть расширен. В результате код станет аккуратнее и чище и обеспечит дополнительные функции.
Так, отрывок, показанный ниже, применит технику first() для выдачи первого компонента в Array-список. Как только этот шаг сделан, метод text() вытащит для нас из него требуемый текстовый контент.
Element firstHeading = document.getElementsByClass("firstHeading").first();
System.out.println(firstHeading.text());
Параллельно, не стоит также сбрасывать со счетов метод selectFirst(), который выдаст нам первое же совпадение:
Element firstHeading= document.selectFirst(".firstHeading");
Заключение
Результативность автоматизированного сбора онлайн-данных — основной критерий процедуры, к которой время от времени прибегает каждая компания. Иметь необходимый уровень знаний для создания парсеров на основе Java — серьезное преимущество в конкурентной борьбе. И как могут видеть читатели, ничего сверхсложного в написании кода нет.
Напоследок подчеркнем, что созданный Java-парсер лучше использовать в комбинации с сайтом прокси сервером, предлагающим адекватный пул адресов для аренды прокси. С командой Dexodata пользователи могут купить приватные прокси для сбора данных, ну а новичкам доступна возможность попробовать прокси бесплатно благодаря пробному периоду. Наша экосистема предлагает все типы IP-адресов прокси: серверные, резидентные и мобильные.