1. Обзор
Jsoup — это библиотека Java с открытым исходным кодом, используемая в основном для извлечения данных из HTML. Он также позволяет вам манипулировать и выводить HTML. Он имеет постоянную линию разработки, отличную документацию и удобный и гибкий API. Jsoup также можно использовать для анализа и построения XML.
В этом уроке мы будем использовать блог Spring , чтобы проиллюстрировать упражнение по очистке, демонстрирующее несколько функций jsoup:
- Загрузка: извлечение и разбор HTML в
документ
- Фильтрация: выбор нужных данных в
Elements
и их обход - Извлечение: получение атрибутов, текста и 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 загружает 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, от самого недействительного до полностью проверенного, как это сделал бы современный браузер. Этого можно добиться, загрузив String
, InputStream
, File
или 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 в Document
, пришло время перемещаться по нему и находить то, что мы ищем. Здесь сходство с jQuery/JavaScript более очевидно, так как его селекторы и методы обхода аналогичны.
5.1. Выбор
Метод выбора
Document
получает строку
, представляющую селектор, используя тот же синтаксис селектора, что и в CSS или JavaScript , и извлекает соответствующий список Elements
. Этот список может быть пустым, но не нулевым
.
Давайте взглянем на некоторые выборки, используя метод 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 браузера, вместо универсального select
:
Element pag = doc.getElementById("pagination_control");
Elements desktopOnly = doc.getElementsByClass("desktopOnly");
Поскольку Element
является суперклассом Document
, вы можете узнать больше о работе с методами выбора в документах Document
и Element
Javadocs.
5.2. Пересечение
Обход означает навигацию по дереву DOM. Jsoup предоставляет методы, которые работают с Document
, набором Elements
или определенным Element
, позволяя вам переходить к родительским, одноуровневым или дочерним элементам узла.
Кроме того, вы можете перейти к первому, последнему и 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 или дочерний текст.
Взгляните на этот пример, который выбирает первую статью из блога и получает ее дату, текст ее первого раздела и, наконец, ее внутренний и внешний 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();
Вот несколько советов, которые следует учитывать при выборе и использовании селекторов:
- Положитесь на функцию «Просмотр исходного кода» вашего браузера, а не только на 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://foreach.com")
.attr("target", "_blank");
firstArticle.appendChild(link);
7.3. Удаление элементов
Чтобы удалить элементы, вам нужно сначала выбрать их и запустить метод удаления
.
Например, давайте удалим из документа все теги <li>
, содержащие класс « navbar-link»
,
и все изображения из первой статьи:
doc.select("li.navbar-link").remove();
firstArticle.select("img").remove();
7.4. Преобразование измененного документа в HTML
Наконец, поскольку мы меняли Document
, мы могли бы захотеть проверить нашу работу.
Для этого мы можем исследовать дерево документа
DOM, выбирая, перемещаясь и извлекая его с помощью представленных методов, или мы можем просто извлечь его HTML как строку
с помощью метода html()
:
String docHtml = doc.html();
Вывод String
представляет собой аккуратный HTML.
8. Заключение
Jsoup — отличная библиотека для парсинга любой страницы. Если вы используете Java и вам не требуется парсинг на основе браузера, следует принять во внимание эту библиотеку. Он знаком и прост в использовании, поскольку он использует знания, которые могут у вас быть в области разработки интерфейса, и следует передовым методам и шаблонам проектирования.
Вы можете узнать больше о парсинге веб-страниц с помощью jsoup, изучив API jsoup и прочитав кулинарную книгу jsoup .
Исходный код, используемый в этом руководстве, можно найти в проекте GitHub .