«1. Обзор

Jsoup — это библиотека Java с открытым исходным кодом, используемая в основном для извлечения данных из HTML. Он также позволяет вам манипулировать и выводить HTML. Он имеет постоянную линию разработки, отличную документацию и удобный и гибкий API. Jsoup также можно использовать для анализа и построения XML.

В этом руководстве мы будем использовать блог Spring, чтобы проиллюстрировать упражнение по очистке, демонстрирующее несколько функций jsoup:

    Загрузка: выборка и анализ HTML в документе Фильтрация: выбор нужных данных в элементах и ​​их обход Извлечение: получение атрибутов, текста и HTML узлов Модификация: добавление/редактирование/удаление узлов и редактирование их атрибутов

2. Зависимость Maven

Чтобы использовать библиотеку jsoup в своем проекте, добавьте зависимость в свой pom .xml:

<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.10.2</version>
</dependency>

Последнюю версию jsoup можно найти в репозитории Maven Central.

3. Обзор Jsoup

Jsoup загружает HTML-код страницы и строит соответствующее DOM-дерево. Это дерево работает так же, как DOM в браузере, предлагая методы, аналогичные jQuery и ванильному JavaScript, для выбора, перемещения, управления текстом/HTML/атрибутами и добавления/удаления элементов.

Если вы знакомы с селекторами на стороне клиента и перемещением/манипулированием DOM, вы найдете jsoup очень знакомым. Проверьте, насколько просто распечатать абзацы страницы:

Document doc = Jsoup.connect("http://example.com").get();
doc.select("p").forEach(System.out::println);

Имейте в виду, что jsoup интерпретирует только HTML — он не интерпретирует JavaScript. Поэтому изменения в DOM, которые обычно происходят после загрузки страницы в браузере с поддержкой JavaScript, не будут видны в jsoup.

4. Загрузка

Этап загрузки включает выборку и преобразование HTML в документ. Jsoup гарантирует синтаксический анализ любого HTML, от самого недействительного до полностью проверенного, как это сделал бы современный браузер. Этого можно добиться, загрузив строку, поток ввода, файл или URL-адрес.

Давайте загрузим документ из URL-адреса блога Spring:

String blogUrl = "https://spring.io/blog";
Document doc = Jsoup.connect(blogUrl).get();

Обратите внимание на метод get, он представляет собой вызов HTTP GET. Вы также можете выполнить HTTP POST с методом post (или вы можете использовать метод, который получает тип метода HTTP в качестве параметра).

Если вам нужно обнаружить аномальные коды состояния (например, 404), вы должны поймать исключение HttpStatusException:

try {
   Document doc404 = Jsoup.connect("https://spring.io/will-not-be-found").get();
} catch (HttpStatusException ex) {
   //...
}

Иногда соединение нужно настроить немного по-другому. Jsoup.connect(…) возвращает соединение, которое позволяет вам установить, среди прочего, пользовательский агент, реферер, время ожидания соединения, файлы cookie, данные публикации и заголовки:

Connection connection = Jsoup.connect(blogUrl);
connection.userAgent("Mozilla");
connection.timeout(5000);
connection.cookie("cookiename", "val234");
connection.cookie("cookiename", "val234");
connection.referrer("http://google.com");
connection.header("headersecurity", "xyz123");
Document docCustomConn = connection.get();

Поскольку соединение следует свободному интерфейс, вы можете связать эти методы перед вызовом нужного метода HTTP:

Document docCustomConn = Jsoup.connect(blogUrl)
  .userAgent("Mozilla")
  .timeout(5000)
  .cookie("cookiename", "val234")
  .cookie("anothercookie", "ilovejsoup")
  .referrer("http://google.com")
  .header("headersecurity", "xyz123")
  .get();

Вы можете узнать больше о настройках соединения, просмотрев соответствующий документ Javadoc.

5. Фильтрация

Теперь, когда мы преобразовали HTML в документ, пришло время перемещаться по нему и находить то, что мы ищем. Здесь сходство с jQuery/JavaScript более очевидно, так как его селекторы и методы обхода аналогичны.

5.1. Выбор

Метод выбора документа получает строку, представляющую селектор, используя тот же синтаксис селектора, что и в CSS или JavaScript, и извлекает соответствующий список элементов. Этот список может быть пустым, но не нулевым.

Давайте посмотрим на некоторые выборки, используя метод select:

Elements links = doc.select("a");
Elements sections = doc.select("section");
Elements logo = doc.select(".spring-logo--container");
Elements pagination = doc.select("#pagination_control");
Elements divsDescendant = doc.select("header div");
Elements divsDirect = doc.select("header > div");

Вы также можете использовать более явные методы, основанные на DOM браузера, вместо общего выбора:

Element pag = doc.getElementById("pagination_control");
Elements desktopOnly = doc.getElementsByClass("desktopOnly");

Поскольку Element является суперклассом документа, вы можете узнать больше о работе с методами выбора в документах Javadoc и Element.

5.2. Обход

Обход означает навигацию по дереву DOM. Jsoup предоставляет методы, которые работают с документом, набором элементов или конкретным элементом, позволяя вам переходить к родительским, одноуровневым или дочерним элементам узла.

Кроме того, вы можете перейти к первому, последнему и n-му (используя индекс, начинающийся с 0) Элементу в наборе Элементов:

Element firstSection = sections.first();
Element lastSection = sections.last();
Element secondSection = sections.get(2);
Elements allParents = firstSection.parents();
Element parent = firstSection.parent();
Elements children = firstSection.children();
Elements siblings = firstSection.siblingElements();

Вы также можете перебирать выборки. На самом деле, все элементы типа Elements могут быть итерированы:

sections.forEach(el -> System.out.println("section: " + el));

«

Elements sectionParagraphs = firstSection.select(".paragraph");

«Вы можете сделать выбор, ограниченный предыдущим выбором (подвыбор):

6. Извлечение

Теперь мы знаем, как получить доступ к определенным элементам, поэтому пришло время получить их содержимое, а именно их атрибуты. , HTML или дочерний текст.

Element firstArticle = doc.select("article").first();
Element timeElement = firstArticle.select("time").first();
String dateTimeOfFirstArticle = timeElement.attr("datetime");
Element sectionDiv = firstArticle.select("section div").first();
String sectionDivText = sectionDiv.text();
String articleHtml = firstArticle.html();
String outerHtml = firstArticle.outerHtml();

Взгляните на этот пример, который выбирает первую статью из блога и получает ее дату, текст первого раздела и, наконец, ее внутренний и внешний HTML:

    Вот несколько советов, которые следует иметь в виду. при выборе и использовании селекторов:

полагайтесь на функцию «Просмотр исходного кода» вашего браузера, а не только на DOM страницы, поскольку она могла измениться (выбор в консоли браузера может дать результаты, отличные от jsoup). Знайте свои селекторы, поскольку они их много, и всегда хорошо хотя бы увидеть их раньше; освоение селекторов требует времени Используйте игровую площадку для селекторов, чтобы экспериментировать с ними (вставьте туда образец HTML) Будьте менее зависимы от изменений страницы: стремитесь к самым маленьким и наименее компрометирующим селекторам (например, предпочитайте селекторы на основе идентификатора)

7. Модификация ~~ ~ Модификация включает в себя настройку атрибутов, текста и HTML элементов, а также добавление и удаление элементов. Это делается для дерева DOM, ранее сгенерированного jsoup — Document.

7.1. Установка атрибутов и внутреннего текста/HTML

Как и в jQuery, методы для установки атрибутов, текста и HTML имеют одинаковые имена, но также получают устанавливаемое значение:

    attr() — устанавливает значения атрибута (он создает атрибут, если он не существует) text() — устанавливает внутренний текст элемента, заменяя содержимое html() — устанавливает внутренний HTML элемента, заменяя содержимое

Давайте рассмотрим краткий пример этих методов:

timeElement.attr("datetime", "2016-12-16 15:19:54.3");
sectionDiv.text("foo bar");
firstArticle.select("h2").html("<div><span></span></div>");

7.2. Создание и добавление элементов

Чтобы добавить новый элемент, вам нужно сначала создать его, создав экземпляр Element. После создания элемента вы можете добавить его к другому элементу с помощью метода appendChild. Вновь созданный и добавленный элемент будет вставлен в конец элемента, где вызывается appendChild:

Element link = new Element(Tag.valueOf("a"), "")
  .text("Checkout this amazing website!")
  .attr("href", "http://baeldung.com")
  .attr("target", "_blank");
firstArticle.appendChild(link);

7.3. Удаление элементов

Чтобы удалить элементы, вам нужно сначала выбрать их и запустить метод удаления.

Например, давайте удалим из документа все теги \u003cli\u003e, содержащие класс «navbar-link», и все изображения из первой статьи:

doc.select("li.navbar-link").remove();
firstArticle.select("img").remove();

7.4. Преобразование измененного документа в HTML

Наконец, поскольку мы изменяли документ, мы могли бы захотеть проверить нашу работу.

Для этого мы можем исследовать DOM-дерево документа, выбирая, перемещаясь и извлекая его с помощью представленных методов, или мы можем просто извлечь его HTML как строку с помощью метода html():

String docHtml = doc.html();

Строковый вывод представляет собой аккуратный HTML.

8. Заключение

Jsoup — отличная библиотека для очистки любой страницы. Если вы используете Java и вам не требуется парсинг на основе браузера, следует принять во внимание эту библиотеку. Он знаком и прост в использовании, поскольку он использует знания, которые могут у вас быть в области разработки интерфейса, и следует передовым методам и шаблонам проектирования.

Вы можете узнать больше об очистке веб-страниц с помощью jsoup, изучив API jsoup и прочитав кулинарную книгу jsoup.

Исходный код, используемый в этом руководстве, можно найти в проекте GitHub.