Zurück zum Blog
Anleitungen
Mihai MaximLast updated on Mar 31, 20266 min read

JSoup: HTML-Analyse in Java

JSoup: HTML-Analyse in Java

Einführung in JSoup

Web-Scraping lässt sich mit einer digitalen Schatzsuche vergleichen. Man durchforstet eine Website und gräbt alle benötigten Informationen aus. Diese Technik wird für die unterschiedlichsten Zwecke eingesetzt, beispielsweise um die günstigsten Preise zu finden, die Kundenstimmung zu analysieren oder Daten für Forschungszwecke zu sammeln.

Java gilt als hervorragende Programmiersprache für Web Scraping, da es über eine Vielzahl von Bibliotheken und Frameworks verfügt, die diesen Prozess unterstützen. Eine der bekanntesten Bibliotheken für Web Scraping in Java ist JSoup. Mit JSoup können Sie den HTML-Code einer Website durchsuchen und alle benötigten Daten extrahieren.

Durch die Kombination von Java mit JSoup können Sie großartige Web-Scraping-Anwendungen erstellen, die schnell und einfach Daten von Websites extrahieren können. In diesem Artikel werde ich Ihnen die Grundlagen des Web-Scrapings mit JSoup näherbringen.

Einrichten eines JSoup-Projekts

In diesem Abschnitt erstellen wir ein neues Java-Projekt mit Maven und konfigurieren es so, dass es über die Befehlszeile mit dem exec-maven-plugin ausgeführt werden kann. Dadurch können Sie Ihr Projekt einfach auf einem Server verpacken und ausführen, was die Automatisierung und Skalierbarkeit des Datenextraktionsprozesses ermöglicht. Anschließend installieren wir die JSoup-Bibliothek.

Erstellen eines Maven-Projekts

Maven ist ein Tool zur Build-Automatisierung für Java-Projekte. Es verwaltet Abhängigkeiten, Builds und Dokumentation und erleichtert so die Verwaltung komplexer Java-Projekte. Mit Maven können Sie den Build-Prozess, die Abhängigkeiten und die Dokumentation Ihres Projekts einfach verwalten und organisieren. Außerdem ermöglicht es eine einfache Integration mit Tools und Frameworks.

Die Installation von Maven ist ein einfacher Vorgang, der in wenigen Schritten erledigt werden kann.

Laden Sie zunächst die neueste Version von Maven von der offiziellen Website (https://maven.apache.org/download.cgi) herunter.

Sobald der Download abgeschlossen ist, entpacken Sie den Inhalt des Archivs in ein Verzeichnis Ihrer Wahl.

Als Nächstes müssen Sie die Umgebungsvariablen einrichten.

Unter Windows setzen Sie die Variable JAVA_HOME auf den Speicherort Ihres JDK und fügen den Ordner „bin“ der Maven-Installation zur PATH-Variable hinzu.

Unter Linux/macOS müssen Sie die folgenden Zeilen zu Ihrer ~/.bashrc- oder ~/.bash_profile-Datei hinzufügen:

export JAVA_HOME=path/to/the/jdk

export PATH=$PATH:path/to/maven/bin

Überprüfen Sie die Maven-Installation, indem Sie in einem Terminal mvn --version ausführen.

Nachdem Maven installiert ist, können Sie nun ein neues Java-Maven-Projekt erstellen:

mvn archetype:generate -DgroupId=com.project.scraper

-DartifactId=jsoup-scraper-project

-DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

Dadurch wird ein neuer Ordner namens „jsoup-scraper-project“ erstellt, der den Inhalt des Projekts enthält.


Der Einstiegspunkt für die Anwendung (die Hauptklasse) befindet sich im Paket „com.project.scraper“.

Ausführen des Projekts über die Befehlszeile

Um ein Maven-Java-Projekt über die Befehlszeile auszuführen, verwenden wir das exec-maven-plugin.

Um das Plugin zu installieren, müssen Sie es zur pom.xml-Datei des Projekts hinzufügen. Dies geschieht, indem Sie den folgenden Codeausschnitt in den Abschnitt <build><plugins> der pom.xml-Datei einfügen:

<build>

 <plugins>

   <plugin>

     <groupId>org.codehaus.mojo</groupId>

     <artifactId>exec-maven-plugin</artifactId>

     <version>3.1.0</version>

     <executions>

       <execution>

         <goals>

           <goal>java</goal>

         </goals>

       </execution>

     </executions>

     <configuration>

       <mainClass>com.project.scraper.App</mainClass>

     </configuration>

   </plugin>

 </plugins>

</build>

Stellen Sie sicher, dass Sie den richtigen Pfad für die Hauptklasse des Projekts auswählen.

Verwenden Sie mvn package exec:java im Terminal (im Projektverzeichnis), um das Projekt auszuführen.

Installation der JSoup-Bibliothek

Um die JSoup-Bibliothek zu installieren, fügen Sie die folgende Abhängigkeit zur pom.xml-Datei Ihres Projekts hinzu:

<dependency>

 <groupId>org.jsoup</groupId>

 <artifactId>jsoup</artifactId>

 <version>1.14.3</version>

</dependency>

Besuchen Sie https://mvnrepository.com/artifact/org.jsoup/jsoup, um die neueste Version zu überprüfen.

HTML-Parsing in Java mit JSoup

In diesem Abschnitt werden wir die Website https://www.scrapethissite.com/pages/forms/ untersuchen und sehen, wie wir Informationen über Eishockeymannschaften extrahieren können. Durch die Untersuchung einer realen Website werden Sie die Konzepte und Techniken verstehen, die beim Web-Scraping mit JSoup verwendet werden, und wie Sie diese auf Ihre eigenen Projekte anwenden können.

Abrufen des HTML-Codes

Um den HTML-Code von der Website abzurufen, müssen Sie eine HTTP-Anfrage an diese senden. In JSoup wird die Methode connect() verwendet, um eine Verbindung zu einer angegebenen URL herzustellen. Sie gibt ein Connection-Objekt zurück, mit dem Sie die Anfrage konfigurieren und die Antwort vom Server abrufen können.

Schauen wir uns an, wie wir die Methode connect() nutzen können, um den HTML-Code von unserer URL abzurufen und ihn dann in eine lokale HTML-Datei (hockey.html) zu schreiben:

package com.project.scraper;

import org.jsoup.Jsoup;

import org.jsoup.nodes.Document;

import java.io.*;

import java.io.IOException;

public class App

{

   public static void main( String[] args )

   {

       String RAW_HTML;

       try {

           Document document = Jsoup.connect("https://www.scrapethissite.com/pages/forms/")

                   .get();

           RAW_HTML = document.html();

           FileWriter writer = new FileWriter("hockey.html");

           writer.write(RAW_HTML);

           writer.close();

       } catch (IOException e) {

           e.printStackTrace();

       }

   }

}

Nun können wir die Datei öffnen und die Struktur des HTML-Codes mit den Entwicklertools untersuchen:

Die benötigten Daten befinden sich in einer HTML-Tabelle auf der Seite. Nachdem wir nun auf die Seite zugegriffen haben, können wir den Inhalt mithilfe von Selektoren aus der Tabelle extrahieren.

Selektoren schreiben

Die Selektoren in JSoup weisen Ähnlichkeiten mit den Selektoren in JavaScript auf. Beide haben eine ähnliche Syntax und ermöglichen es Ihnen, Elemente aus einem HTML-Dokument anhand ihres Tag-Namens, ihrer Klasse, ihrer ID und ihrer CSS-Eigenschaften auszuwählen.

Hier sind einige der wichtigsten Selektoren, die Sie mit JSoup verwenden können:

  • getElementsByTag(): Wählt Elemente anhand ihres Tag-Namens aus.
  • getElementsByClass(): Wählt Elemente anhand ihres Klassennamens aus.
  • getElementById(): Wählt ein Element anhand seiner ID aus.
  • select(): Wählt Elemente anhand eines CSS-Selektors aus (ähnlich wie querySelectorAll)

Verwenden wir nun einige davon, um alle Teamnamen zu extrahieren:

try {

   Document document = Jsoup.connect("https://www.scrapethissite.com/pages/forms/")

           .get();

   Elements rows = document.getElementsByTag("tr");

   for(Element row : rows) {

      

       Elements teamName = row.getElementsByClass("name");

      

       if(teamName.text().compareTo("") != 0)

           System.out.println(teamName.text());

      

   }

} catch (IOException e) {

   e.printStackTrace();

}

// Prints the team names:

Boston Bruins

Buffalo Sabres

Calgary Flames

Chicago Blackhawks

Detroit Red Wings

Edmonton Oilers

Hartford Whalers

...

Wir haben jede Zeile durchlaufen und für jede den Teamnamen mithilfe des Klassenselektors „name“ ausgegeben.

Das letzte Beispiel verdeutlicht die Flexibilität und die Möglichkeit, Selektormethoden mehrfach auf die extrahierten Elemente anzuwenden. Dies ist besonders nützlich beim Umgang mit komplexen und umfangreichen HTML-Dokumenten.

Hier ist eine weitere Version, die Java-Streams und die select()-Methode verwendet, um alle Teamnamen auszugeben:

try {

   Document document = Jsoup.connect("https://www.scrapethissite.com/pages/forms/")

           .get();

   Elements teamNamesElements = document.select("table .team .name");

   String[] teamNames = teamNamesElements.stream()

                                         .map(element -> element.text())

                                         .toArray(String[]::new);

   for (String teamName : teamNames) {

       System.out.println(teamName);

   }

} catch (IOException e) {

   e.printStackTrace();

}

// Also prints the team names:

Boston Bruins

Buffalo Sabres

Calgary Flames

...

Nun geben wir alle Tabellenüberschriften und Zeilen aus:

try {

   Document document = Jsoup.connect("https://www.scrapethissite.com/pages/forms/")

           .get();

   Elements tableHeadersElements = document.select("table th");

   Elements tableRowsElements = document.select("table .team");

   String[] tableHeaders =

   tableHeadersElements.stream()

                       .map(element -> element.text())

                       .toArray(String[]::new);

   String[][] tableRows =

   tableRowsElements.stream()

            .map(

                table_row -> table_row

                .select("td")

                .stream()

                .map(row_element -> row_element.text())

                .toArray(String[]::new)

               )

            .toArray(String[][]::new);

   for (int i = 0; i < tableHeaders.length; i++) {

       System.out.print(tableHeaders[i] + " ");

   }

   for (int i = 0; i < tableRows.length; i++) {

       for (int j = 0; j < tableRows[i].length; j++) {

           System.out.print(tableRows[i][j] + " ");

       }

       System.out.println();

   }

} catch (IOException e) {

   e.printStackTrace();

}

// Prints

Team Name Year Wins Losses OT Losses Win ...

Boston Bruins 1990 44 24  0.55 299 264 35 

Buffalo Sabres 1990 31 30  0.388 292 278 14 

Calgary Flames 1990 46 26  0.575 344 263 81 

Chicago Blackhawks 1990 49 23  0.613 284 211 73 

Detroit Red Wings 1990 34 38  0.425 273 298 -25

...

Beachten Sie, dass wir Streams verwendet haben, um die Zeilen zu speichern. Hier ist eine einfachere Methode, bei der for-Schleifen zum Einsatz kommen:

String[][] tableRows = new String[tableRowsElements.size()][];

for (int i = 0; i < tableRowsElements.size(); i++) {

   Element table_row = tableRowsElements.get(i);

   Elements tableDataElements = table_row.select("td");

   String[] rowData = new String[tableDataElements.size()];

   for (int j = 0; j < tableDataElements.size(); j++) {

       Element row_element = tableDataElements.get(j);

       String text = row_element.text();

       rowData[j] = text;

   }

   tableRows[i] = rowData;

}

Umgang mit Paginierung

Beim Extrahieren von Daten aus einer Website ist es üblich, dass die Informationen auf mehrere Seiten verteilt sind. Um alle relevanten Daten zu scrapen, ist es notwendig, Anfragen an jede Seite der Website zu stellen und die Informationen von jeder einzelnen zu extrahieren. Wir können diese Funktion ganz einfach in unser Projekt implementieren.

Wir müssen lediglich den Abfrageparameter `page_num` in der URL ändern und eine weitere HTTP-Anfrage mit der Methode `connect()` stellen.

int pageLimit = 25;

String [] tableHeaders = new String[0];

Vector<String[][]> rowsGroups = new Vector<String [][]>();

for (int currentPage=1; currentPage<pageLimit; currentPage++) {

   try {

       Document document = Jsoup.connect("https://www.scrapethissite.com/pages/forms/?page_num=" + currentPage)

               .get();

       if(currentPage == 1) {

           Elements tableHeadersElements = document.select("table th");

           tableHeaders = tableHeadersElements.stream()

                   .map(element -> element.text())

                   .toArray(String[]::new);

       }

       Elements tableRowsElements = document.select("table .team");

       String[][] tableRows = new String[tableRowsElements.size()][];

       for (int i = 0; i < tableRowsElements.size(); i++) {

           Element table_row = tableRowsElements.get(i);

           Elements tableDataElements = table_row.select("td");

           String[] rowData = new String[tableDataElements.size()];

           for (int j = 0; j < tableDataElements.size(); j++) {

               Element row_element = tableDataElements.get(j);

               String text = row_element.text();

               rowData[j] = text;

           }

           tableRows[i] = rowData;

       }

       rowsGroups.add(tableRows);

   } catch (IOException e) {

       e.printStackTrace();

   }

   // do something with the headers and the the table rows groups

}

Da die Tabellen auf jeder Seite dieselben Kopfzeilen haben, sollten Sie darauf achten, sie nicht mehrfach zu scrapen.

Der vollständige Code

Hier ist der vollständige Code, der alle Tabellen von der Website https://www.scrapethissite.com/pages/forms/ extrahiert. Ich habe auch eine Funktion hinzugefügt, die die Daten als CSV-Datei speichert:

package com.project.scraper;

import org.jsoup.Jsoup;

import org.jsoup.nodes.Document;

import org.jsoup.nodes.Element;

import org.jsoup.select.Elements;

import java.io.*;

import java.io.IOException;

import java.util.Vector;

public class App

{

   public static void main( String[] args )

   {

       int pageLimit = 25;

       String [] tableHeaders = new String[0];

       Vector<String[][]> rowsGroups = new Vector<String [][]>();

       for (int currentPage=1; currentPage<pageLimit; currentPage++) {

           try {

               Document document = Jsoup.connect("https://www.scrapethissite.com/pages/forms/?page_num=" + currentPage)

                       .get();

               if(currentPage == 1) {

                   Elements tableHeadersElements = document.select("table th");

                   tableHeaders = tableHeadersElements.stream()

                           .map(element -> element.text())

                           .toArray(String[]::new);

               }

               Elements tableRowsElements = document.select("table .team");

               String[][] tableRows = new String[tableRowsElements.size()][];

               for (int i = 0; i < tableRowsElements.size(); i++) {

                   Element table_row = tableRowsElements.get(i);

                   Elements tableDataElements = table_row.select("td");

                   String[] rowData = new String[tableDataElements.size()];

                   for (int j = 0; j < tableDataElements.size(); j++) {

                       Element row_element = tableDataElements.get(j);

                       String text = row_element.text();

                       rowData[j] = text;

                   }

                   tableRows[i] = rowData;

               }

               rowsGroups.add(tableRows);

           } catch (IOException e) {

               e.printStackTrace();

           }

       }

       writeFullTableToCSV(rowsGroups, tableHeaders, "full_table.csv");

   }

   public static void writeFullTableToCSV(Vector<String[][]> rowsGroups, String[] headers, String fileName) {

       File file = new File(fileName);

       try {

           FileWriter writer = new FileWriter(file);

           // write the headers first

           for (int i = 0; i < headers.length; i++) {

               writer.append(headers[i]);

               if (i != headers.length - 1) {

                   writer.append(",");

               }

           }

           writer.append("\n");

           // write all the rows groups

           for (String [][] rowsGroup : rowsGroups) {

               for (String[] row : rowsGroup) {

                   for (int i = 0; i < row.length; i++) {

                       writer.append(row[i]);

                       if (i != row.length - 1) {

                           writer.append(",");

                       }

                   }

                   writer.append("\n");

               }

           }

           writer.flush();

           writer.close();

       } catch (IOException e) {

           e.printStackTrace();

       }

   }

}

Zusammenfassung

In diesem Artikel haben wir behandelt, wie man Maven installiert und ein neues Java-Maven-Projekt erstellt sowie wie man das Projekt über die Befehlszeile ausführt. Wir haben außerdem besprochen, wie man die JSoup-Bibliothek installiert, indem man die Abhängigkeit zur pom.xml-Datei des Projekts hinzufügt. Abschließend haben wir ein Beispiel dafür durchgesprochen, wie man JSoup verwendet, um HTML zu parsen und Daten von einer Website zu extrahieren. Wenn Sie die im Artikel beschriebenen Schritte befolgen, sollten Sie über eine solide Grundlage verfügen, um ein JSoup-Projekt einzurichten und mit der Datenextraktion aus Websites zu beginnen. JSoup bietet eine Vielzahl von Optionen und Möglichkeiten für das Web-Scraping, und ich empfehle Ihnen, diese zu erkunden und in Ihren eigenen Projekten anzuwenden.

Wie Sie gesehen haben, werden Daten oft über mehrere Webseiten hinweg geteilt. Das schnelle Absenden von Anfragen an dieselbe Domain kann dazu führen, dass Ihre IP-Adresse gesperrt wird. Mit unserem Produkt WebScrapingAPI müssen Sie sich um solche Probleme keine Sorgen machen. Unsere API stellt sicher, dass Sie so viele Anfragen stellen können, wie Sie benötigen. Und das Beste daran ist, dass Sie es kostenlos ausprobieren können.

Über den Autor
Mihai Maxim, Full-Stack-Entwickler @ WebScrapingAPI
Mihai MaximFull-Stack-Entwickler

Mihai Maxim ist Full-Stack-Entwickler bei WebScrapingAPI, wo er in verschiedenen Bereichen des Produkts mitwirkt und an der Entwicklung zuverlässiger Tools und Funktionen für die Plattform mitarbeitet.

Los geht’s

Sind Sie bereit, Ihre Datenerfassung zu erweitern?

Schließen Sie sich den über 2.000 Unternehmen an, die WebScrapingAPI nutzen, um Webdaten im Unternehmensmaßstab ohne zusätzlichen Infrastrukturaufwand zu extrahieren.