JSoup: HTML-Parsing in Java

Mihai Maxim am 31. Januar 2023

blog-image

Einführung in JSoup

Web Scraping kann man sich wie eine digitale Schatzsuche vorstellen. Sie gehen durch eine Website und graben alle Informationen aus, die Sie brauchen. Diese Technik wird für alle möglichen Dinge eingesetzt, z. B. um die günstigsten Preise zu finden, die Stimmung der Kunden zu analysieren oder Daten für die Forschung zu sammeln.

Java gilt als hervorragende Programmiersprache für Web-Scraping, da sie über eine Vielzahl von Bibliotheken und Frameworks verfügt, die bei diesem Prozess helfen können. Eine der bekanntesten Bibliotheken für Web Scraping in Java ist JSoup. Mit JSoup können Sie durch den HTML-Code einer Website navigieren und suchen und alle benötigten Daten extrahieren.

Durch die Kombination von Java mit JSoup können Sie großartige Web-Scraping-Anwendungen erstellen, mit denen Sie schnell und einfach Daten aus Websites extrahieren können. In diesem Artikel führe ich Sie durch die Grundlagen des Web Scraping mit JSoup.

Einrichten eines JSoup-Projekts

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

Erstellen eines Maven-Projekts

Maven ist ein Build-Automatisierungswerkzeug 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 Prozess, der in wenigen Schritten durchgeführt 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 bin-Ordner der Maven-Installation zur PATH-Variablen hinzu.

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

export JAVA_HOME=pfad/zu/der/jdk

export PATH=$PATH:pfad/zu/maven/bin

Bestätigen Sie die Maven-Installation, indem Sie mvn --version in einem Terminal ausführen.

Wenn Sie Maven installiert haben, 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) wird im Paket "com.project.scraper" liegen.

Ausführen des Projekts über die Befehlszeile

Um ein Maven-Java-Projekt von der Kommandozeile aus zu starten, werden wir das exec-maven-plugin verwenden.

To install the plugin, you need to add it to the project's pom.xml file. This can be done by adding the following code snippet to the <build><plugins> section of the pom.xml file:

<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 prüfen.

Parsing von HTML in Java mit JSoup

In diesem Abschnitt werden wir die Website https://www.scrapethissite.com/pages/forms/ untersuchen und sehen, wie wir die 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 der HTML-Datei

Um den HTML-Code von der Website abzurufen, müssen Sie eine HTTP-Anfrage an die Website stellen. In JSoup wird die Methode connect() verwendet, um eine Verbindung zu einer bestimmten URL herzustellen. Sie gibt ein Connection-Objekt zurück, das zur Konfiguration der Anfrage und zum Abrufen der Antwort vom Server verwendet werden kann.

Sehen wir uns an, wie wir die Methode connect() verwenden 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();

}

}

}

Jetzt können wir die Datei öffnen und die Struktur der HTML-Datei mit den Entwicklertools untersuchen:

blog-image

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

Selektoren schreiben

Die Selektoren in JSoup haben Ähnlichkeiten mit den Selektoren in JavaScript. Beide haben eine ähnliche Syntax und ermöglichen die Auswahl von Elementen aus einem HTML-Dokument auf der Grundlage ihres Tag-Namens, ihrer Klasse, ihrer id und ihrer CSS-Eigenschaften.

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 basierend auf einem CSS-Selektor aus (ähnlich wie querySelectorAll)

Verwenden wir nun einige von ihnen, 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 Zeile den Namen der Mannschaft mit dem Klassenselektor "name" ausgegeben.

Das letzte Beispiel unterstreicht die Flexibilität und die Möglichkeit, Selektormethoden mehrfach auf die extrahierten Elemente anzuwenden. Dies ist besonders nützlich, wenn es um komplexe und große HTML-Dokumente geht.

Hier ist eine andere Version, die Java-Streams und die select()-Methode verwendet, um alle Teamnamen zu drucken:

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

...

Drucken wir nun alle Tabellenköpfe 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 zum Speichern der Zeilen Streams verwendet haben. Hier ist eine einfachere Möglichkeit, dies mit for-Schleifen zu tun:

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;

}

Handhabung der Paginierung

Bei der Extraktion von Daten aus einer Website ist es üblich, dass die Informationen über mehrere Seiten verteilt sind. Um alle relevanten Daten abzurufen, müssen Anfragen an jede Seite der Website gestellt und die Informationen von jeder Seite extrahiert werden. Wir können diese Funktion problemlos in unser Projekt integrieren.

blog-image

Alles, was wir tun müssen, ist, den Abfrageparameter page_num in der URL zu ändern und eine weitere HTTP-Anfrage mit der Methode connect() zu 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 die gleichen Überschriften haben, sollten Sie darauf achten, dass Sie sie nicht mehrfach abrufen.

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 im CSV-Format 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();

}

}

}

Einpacken

In diesem Artikel haben wir uns mit der Installation von Maven und der Erstellung eines neuen Java-Maven-Projekts sowie mit der Ausführung des Projekts von der Kommandozeile aus beschäftigt. Wir haben auch besprochen, wie man die JSoup-Bibliothek installiert, indem man die Abhängigkeit zur pom.xml-Datei des Projekts hinzufügt. Schließlich haben wir uns ein Beispiel für die Verwendung von JSoup zum Parsen von HTML und Extrahieren von Daten aus einer Website angesehen. Wenn Sie die in diesem Artikel beschriebenen Schritte befolgen, sollten Sie eine solide Grundlage für die Einrichtung eines JSoup-Projekts haben und mit der Extraktion von Daten aus Websites beginnen können. JSoup bietet eine breite Palette von Optionen und Möglichkeiten für Web Scraping, und ich möchte Sie ermutigen, sie zu erforschen und auf Ihre eigenen Projekte anzuwenden.

Wie Sie gesehen haben, werden Daten oft über mehrere Webseiten verteilt. Schnelle Anfragen an dieselbe Domain können dazu führen, dass Ihre IP gesperrt wird. Mit unserem Produkt, WebScrapingAPI, müssen Sie sich über solche Probleme keine Gedanken machen. Unsere API sorgt dafür, dass Sie so viele Anfragen stellen können, wie Sie benötigen. Und das Beste daran ist, dass Sie es kostenlos ausprobieren können.

Nachrichten und Aktualisierungen

Bleiben Sie auf dem Laufenden mit den neuesten Web Scraping-Anleitungen und Nachrichten, indem Sie unseren Newsletter abonnieren.

We care about the protection of your data. Read our <l>Privacy Policy</l>.Privacy Policy.

Ähnliche Artikel

Vorschaubild
AnwendungsfälleNutzung von Web Scraping für alternative Daten im Finanzwesen: Ein umfassender Leitfaden für Investoren

Erforschen Sie die transformative Kraft des Web Scraping im Finanzsektor. Von Produktdaten bis zur Stimmungsanalyse bietet dieser Leitfaden Einblicke in die verschiedenen Arten von Webdaten, die für Investitionsentscheidungen zur Verfügung stehen.

Mihnea-Octavian Manolache
Autorenavatar
Mihnea-Octavian Manolache
13 Minuten lesen
Vorschaubild
Wissenschaft des Web ScrapingWeb Scraping leicht gemacht: Die Bedeutung von Data Parsing

Erfahren Sie, wie Sie mit Hilfe von Datenparsing, HTML-Parsing-Bibliotheken und schema.org-Metadaten effizient Daten für Web-Scraping und Datenanalysen extrahieren und organisieren können.

Suciu Dan
Autorenavatar
Suciu Dan
12 Minuten lesen
Vorschaubild
AnwendungsfälleXPath vs. CSS-Selektoren

Sind XPath-Selektoren besser als CSS-Selektoren für Web Scraping? Erfahren Sie mehr über die Stärken und Grenzen der einzelnen Methoden und treffen Sie die richtige Wahl für Ihr Projekt!

Mihai Maxim
Autorenavatar
Mihai Maxim
8 Minuten lesen