1. Общ преглед
Jsoup е Java библиотека с отворен код, използвана главно за извличане на данни от HTML. Също така ви позволява да манипулирате и извеждате HTML. Той има стабилна линия за разработка, страхотна документация и плавен и гъвкав API. Jsoup може да се използва и за анализ и изграждане на XML.
В този урок ще използваме Spring Blog, за да илюстрираме упражнение за изстъргване, което демонстрира няколко характеристики на jsoup:
- Зареждане: извличане и анализиране на HTML в документ
- Филтриране: избор на желаните данни в Елементи и обхождането им
- Извличане: получаване на атрибути, текст и HTML на възли
- Модифициране: добавяне / редактиране / премахване на възли и редактиране на техните атрибути
2. Зависимост на Maven
За да използвате библиотеката jsoup във вашия проект, добавете зависимостта към вашия pom.xml :
org.jsoup jsoup 1.10.2
Можете да намерите най-новата версия на jsoup в хранилището на Maven Central.
3. Jsoup с един поглед
Jsoup зарежда HTML страницата и изгражда съответното DOM дърво. Това дърво работи по същия начин като DOM в браузъра, предлагайки методи, подобни на jQuery и ванилия JavaScript за избор, пресичане, манипулиране на текст / HTML / атрибути и добавяне / премахване на елементи.
Ако се чувствате удобно с селектори от страна на клиента и DOM обхождане / манипулация, ще намерите jsoup много познат. Проверете колко лесно е да отпечатате абзаците на страница:
Document doc = Jsoup.connect("//example.com").get(); doc.select("p").forEach(System.out::println);
Имайте предвид, че jsoup интерпретира само HTML - не интерпретира JavaScript. Следователно промени в DOM, които обикновено се извършват след зареждане на страницата в браузър с активиран JavaScript, няма да се видят в jsoup.
4. Зареждане
Фазата на зареждане включва извличане и анализиране на HTML в документ . Jsoup гарантира анализирането на всеки HTML, от най-невалидния до напълно валидирания, както би направил съвременният браузър. Това може да се постигне чрез зареждане на String , InputStream , файл или URL адрес.
Нека да заредим документ от URL адреса на пролетния блог:
String blogUrl = "//spring.io/blog"; Document doc = Jsoup.connect(blogUrl).get();
Забележете метода get , той представлява HTTP GET повикване. Можете също така да направите HTTP POST с метода post (или можете да използвате метод, който получава HTTP тип метод като параметър).
Ако трябва да откриете необичайни кодове на състоянието (например 404), трябва да хванете изключението HttpStatusException :
try { Document doc404 = Jsoup.connect("//spring.io/will-not-be-found").get(); } catch (HttpStatusException ex) { //... }
Понякога връзката трябва да бъде малко по-персонализирана. Jsoup.connect (...) връща Connection която ви позволява да сет, наред с други неща, на потребителския агент, референт, изчакване връзка, бисквити, публикуване на данни, както и заглавията:
Connection connection = Jsoup.connect(blogUrl); connection.userAgent("Mozilla"); connection.timeout(5000); connection.cookie("cookiename", "val234"); connection.cookie("cookiename", "val234"); connection.referrer("//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("//google.com") .header("headersecurity", "xyz123") .get();
Можете да научите повече за настройките на връзката, като разгледате съответния Javadoc.
5. Филтриране
Сега, след като преобразуваме HTML в документ , е време да навигираме в него и да намерим това, което търсим. Тук приликата с jQuery / JavaScript е по-очевидна, тъй като селекторите и методите за обхождане са сходни.
5.1. Избиране
Методът за избор на документ получава String, представляващ селектора, използвайки същия синтаксис на селектора, както в 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 е суперклас на Document , можете да научите повече за работата с методите за подбор в Javadocs на Document и Element .
5.2. Преминаване
Преминаването означава навигация през DOM дървото. Jsoup предоставя методи, които действат върху Документа , върху набор от Елементи или върху определен Елемент , което Ви позволява да навигирате до родители, братя и сестри на възел или деца.
Също така, можете да преминете към първата, най-накрая, и кой ли (с помощта на 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 - Документа .
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(" ");
7.2. Създаване и добавяне на елементи
To add a new element, you need to build it first by instantiating Element. Once the Element has been built, you can append it to another Element using the appendChild method. The newly created and appended Element will be inserted at the end of the element where appendChild is called:
Element link = new Element(Tag.valueOf("a"), "") .text("Checkout this amazing website!") .attr("href", "//baeldung.com") .attr("target", "_blank"); firstArticle.appendChild(link);
7.3. Removing Elements
To remove elements, you need to select them first and run the remove method.
For example, let's remove all
doc.select("li.navbar-link").remove(); firstArticle.select("img").remove();
7.4. Converting the Modified Document to HTML
Finally, since we were changing the Document, we might want to check our work.
To do this, we can explore the Document DOM tree by selecting, traversing, and extracting using the presented methods, or we can simply extract its HTML as a String using the html() method:
String docHtml = doc.html();
The String output is a tidy HTML.
8. Conclusion
Jsoup is a great library to scrape any page. If you're using Java and don't require browser-based scraping, it's a library to take into account. It's familiar and easy to use since it makes use of the knowledge you may have on front-end development and follows good practices and design patterns.
You can learn more about scraping web pages with jsoup by studying the jsoup API and reading the jsoup cookbook.
The source code used in this tutorial can be found in the GitHub project.