Analysieren von HTML in Java mit Jsoup

1. Übersicht

Jsoup ist eine Open-Source-Java-Bibliothek, die hauptsächlich zum Extrahieren von Daten aus HTML verwendet wird. Außerdem können Sie HTML bearbeiten und ausgeben. Es verfügt über eine stetige Entwicklungslinie, eine hervorragende Dokumentation und eine flüssige und flexible API. Jsoup kann auch zum Parsen und Erstellen von XML verwendet werden.

In diesem Tutorial verwenden wir den Frühlingsblog, um eine Scraping-Übung zu veranschaulichen, die verschiedene Funktionen von jsoup demonstriert:

  • Laden: Abrufen und Parsen des HTML-Codes in ein Dokument
  • Filtern: Wählen Sie die gewünschten Daten in Elemente aus und durchlaufen Sie sie
  • Extrahieren: Abrufen von Attributen, Text und HTML von Knoten
  • Ändern: Hinzufügen / Bearbeiten / Entfernen von Knoten und Bearbeiten ihrer Attribute

2. Maven-Abhängigkeit

Fügen Sie die Abhängigkeit zu Ihrer pom.xml hinzu, um die jsoup-Bibliothek in Ihrem Projekt zu verwenden :

 org.jsoup jsoup 1.10.2 

Sie finden die neueste Version von jsoup im Maven Central-Repository.

3. Suppe auf einen Blick

Jsoup lädt den Seiten-HTML-Code und erstellt den entsprechenden DOM-Baum. Dieser Baum funktioniert genauso wie das DOM in einem Browser und bietet ähnliche Methoden wie jQuery und Vanilla JavaScript, um Text / HTML / Attribute auszuwählen, zu durchlaufen, zu bearbeiten und Elemente hinzuzufügen / zu entfernen.

Wenn Sie mit clientseitigen Selektoren und DOM-Traversing / Manipulation vertraut sind, ist jsoup sehr vertraut. Überprüfen Sie, wie einfach es ist, die Absätze einer Seite zu drucken:

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

Denken Sie daran, dass jsoup nur HTML interpretiert - es interpretiert kein JavaScript. Daher werden Änderungen am DOM, die normalerweise nach dem Laden der Seite in einem JavaScript-fähigen Browser vorgenommen werden, in jsoup nicht angezeigt.

4. Laden

Die Ladephase umfasst das Abrufen und Parsen des HTML-Codes in ein Dokument . Jsoup garantiert das Parsen von HTML, von den ungültigsten bis zu den vollständig validierten, wie es ein moderner Browser tun würde. Dies kann durch Laden eines Strings , eines InputStreams , einer Datei oder einer URL erreicht werden.

Laden wir ein Dokument von der Spring Blog-URL:

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

Beachten Sie die get- Methode, die einen HTTP-GET-Aufruf darstellt. Sie können auch einen HTTP-POST mit der post- Methode ausführen (oder Sie können eine Methode verwenden, die den HTTP-Methodentyp als Parameter empfängt).

Wenn Sie abnormale Statuscodes erkennen müssen (z. B. 404), sollten Sie die HttpStatusException- Ausnahme abfangen :

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

Manchmal muss die Verbindung etwas individueller gestaltet werden. Jsoup.connect (…) gibt eine Verbindung zurück , mit der Sie unter anderem den Benutzeragenten, den Referrer, das Verbindungszeitlimit, Cookies, Postdaten und Header festlegen können:

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();

Da die Verbindung einer fließenden Schnittstelle folgt, können Sie diese Methoden verketten, bevor Sie die gewünschte HTTP-Methode aufrufen:

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

Weitere Informationen zu den Verbindungseinstellungen erhalten Sie im entsprechenden Javadoc.

5. Filtern

Nachdem wir den HTML-Code in ein Dokument konvertiert haben , ist es Zeit, darin zu navigieren und das zu finden, wonach wir suchen. Hier wird die Ähnlichkeit mit jQuery / JavaScript deutlicher, da die Selektoren und Durchlaufmethoden ähnlich sind.

5.1. Auswählen

Das Dokument auszuwählen Methode erhält einen String die Wähler darstellt, unter Verwendung desselben Selektors Syntax wie in einem CSS oder JavaScript, und ruft die passende Liste der Elemente . Diese Liste kann leer, aber nicht null sein .

Schauen wir uns einige Auswahlen einen Blick darauf werfen , die unter Verwendung von Auswahlmethode:

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");

Sie können anstelle der generischen Auswahl auch explizitere Methoden verwenden, die vom Browser-DOM inspiriert sind :

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

Da Element eine Superklasse von Dokumenten ist , können Sie mehr über die Arbeit mit den Auswahlmethoden in den Dokument- und Element- Javadocs erfahren.

5.2. Durchqueren

Durchqueren bedeutet, über den DOM-Baum zu navigieren. Jsoup bietet Methoden, die mit dem Dokument , einer Reihe von Elementen oder einem bestimmten Element arbeiten und es Ihnen ermöglichen, zu den Eltern, Geschwistern oder Kindern eines Knotens zu navigieren.

Sie können auch zum ersten, letzten und n-ten Element (unter Verwendung eines 0-basierten Index) in einer Reihe von Elementen springen :

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();

Sie können auch durch Auswahlen iterieren. Tatsächlich kann alles vom Typ Elemente iteriert werden:

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

Sie können eine Auswahl auf eine vorherige Auswahl beschränken (Unterauswahl):

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

6. Extrahieren

Wir wissen jetzt, wie man bestimmte Elemente erreicht, daher ist es Zeit, deren Inhalt abzurufen - nämlich deren Attribute, HTML oder untergeordneten Text.

Schauen Sie sich dieses Beispiel an, in dem der erste Artikel aus dem Blog ausgewählt und das Datum, der Text des ersten Abschnitts und schließlich der innere und äußere HTML-Code abgerufen werden:

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();

Hier sind einige Tipps, die Sie bei der Auswahl und Verwendung von Selektoren beachten sollten:

  • Verlassen Sie sich auf die Funktion "Quelltext anzeigen" Ihres Browsers und nicht nur auf das Seiten-DOM, da es sich möglicherweise geändert hat (die Auswahl an der Browserkonsole führt möglicherweise zu anderen Ergebnissen als jsoup).
  • Kennen Sie Ihre Selektoren, da es viele von ihnen gibt und es immer gut ist, sie zumindest schon einmal gesehen zu haben. Das Beherrschen von Selektoren braucht Zeit
  • Verwenden Sie einen Spielplatz, auf dem Selektoren mit ihnen experimentieren können (fügen Sie dort ein Beispiel-HTML ein).
  • Seien Sie weniger abhängig von Seitenänderungen: Streben Sie nach den kleinsten und am wenigsten kompromittierenden Selektoren (z. B. bevorzugen Sie ID-basiert)

7. Ändern

Das Ändern umfasst das Festlegen von Attributen, Text und HTML von Elementen sowie das Anhängen und Entfernen von Elementen. Dies erfolgt mit dem DOM-Baum, der zuvor von jsoup - dem Dokument - generiert wurde .

7.1. Festlegen von Attributen und innerem Text / HTML

Wie in jQuery tragen die Methoden zum Festlegen von Attributen, Text und HTML denselben Namen, erhalten jedoch auch den einzustellenden Wert:

  • attr () - legt die Werte eines Attributs fest (es erstellt das Attribut, wenn es nicht vorhanden ist)
  • text () - Legt den inneren Text des Elements fest und ersetzt den Inhalt
  • html () - Legt das innere HTML des Elements fest und ersetzt den Inhalt

Schauen wir uns ein kurzes Beispiel für diese Methoden an:

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

7.2. Elemente erstellen und anhängen

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

  • tags that contain the “navbar-link” class from Document, and all images from the first article:

    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.