HTML mit Hilfe Jsoup einlesen

Guten Tag,

ich bin gerade dran mit Hilfe des Jsoup Parsers einige Informationen aus einer HTML Datei zu extrahieren.

Leider komme ich noch nicht ganz mit der Referenzierung klar. Und zwar möchte ich aus der folgenden Datei folgende Informationen in folgendem Schema am Besten in einer Liste oder Map abspeichern, falls möglich.

SVR_53, 33, 0, 0 ,33
SVR_152, 12, 4, 0, 16
usw.

HTML:
<td class="passed-cell">
<span> SVR_53</span>
</td>
<td class="number-cell">
<span>33</span>
</td>
<td class="number-cell"/>
<span>0</span>
</td>
<td class="number-cell"/>
<span>0</span>
</td>
<td class="number-cell">
<span>33</span>
<td class="passed-cell">
<span> SVR_152</span>
</td>
<td class="number-cell">
<span>12</span>
</td>
<td class="number-cell"/>
<span>4</span>
</td>
<td class="number-cell"/>
<span>0</span>
</td>
<td class="number-cell">
<span>16</span>
</td>
Könnt Ihr mir sagen wie ich die jeweiligen Bereiche auslesen kann?

Besten Dank
 
Ich hatte angefangen mit

Code:
Element masthead = doc.select("td.passed-cell")
Hier könnte ich iterieren und mit Hilfe eines Integer der innerhalb der Schleife inkrementiert wird alle Werte unter passed-cell speichern.

Java:
ArrayList passedList = new ArrayList();
int iD = 0;

for (Element e : masthead)
{
     passedList(iD, e.text());
     iD++;
}
Aber wie schaffe ich es, die 4 nachfolgenden "number-cells" dem entsprechenden SVR zuzuordnen?

Vielen Dank
 
Bevor man jetzt groß versucht zu parsen: Ist es gewollt oder Teil des Problems, dass das HTML nicht valide ist?
 
Was meinst du in dem Fall mit nicht valide?

Ich habe lokal eine .html Datei und aus der möchte ich wie oben beschrieben jeweils die Zellen der Tabelle auslesen. Ich habe ja lediglich den relevanten Ausschnitt geposted.

HTML:
<table class="overview-new">
<tr>
<td class="passed-cell">
<span>SVR_52</span>
</td>
<td class="number-cell">
<span>33</span>
</td>
<td class="number-cell"/>
<td class="number-cell"/>
<td class="number-cell">
<span>33</span>
</td>
</tr>
<tr>
<td class="passed-cell">
<span>SVR_53</span>
</td>
<td class="number-cell">
<span>33</span>
</td>
<td class="number-cell"/>
<td class="number-cell"/>
<td class="number-cell">
<span>33</span>
</td>
</tr>
</table>
Wie schaffe ich es nun hier sequentiell auszulesen was zusammengehört? Vor allem an der Stelle, in der die html-File nichts einträgt, was für mich aber gleichbedeutend mit 0 ist

Beispiel neuer Code-Schnipsel
SVR_52, 33, 0, 0, 0, 33
SVR_53, 33, 0, 0, 0, 33

Vielen Dank
 
Zuletzt bearbeitet:
Ich beziehe mich auf das HTML im ersten Beitrag:
Bsp. kein <table>, <tr>
Bsp. Eine leere Zelle, danach ein span und dann eine nicht-geöffnete Zelle schließen
HTML:
<td class="number-cell"/>
<span>0</span>
</td>
 
HTML:
<table>
    <tr>
        <td class="passed-cell">
            <span> SVR_53</span>
        </td>
    </tr>
    <tr>
        <td class="number-cell">
            <span>33</span>
        </td>
    </tr>
    <tr>
        <td class="number-cell">
            <span>0</span>
        </td>
    </tr>
    <tr>
        <td class="number-cell">
            <span>0</span>
        </td>
    </tr>
    <tr>
        <td class="number-cell">
            <span>33</span>
    <tr>
        <td class="passed-cell">
            <span> SVR_152</span>
        </td>
    </tr>
    <tr>
        <td class="number-cell">
            <span>12</span>
        </td>
    </tr>
    <tr>
        <td class="number-cell">
            <span>4</span>
        </td>
    </tr>
    <tr>
        <td class="number-cell">
            <span>0</span>
        </td>
    </tr>
    <tr>
        <td class="number-cell">
            <span>16</span>
        </td>
    </tr>
</table>
Hier ein Ansatz ohne Fehlerbehandlung. Ich hole mir alle Zeilen und bestimme den Index der "passed-cell"'s. Per index kann ich mir die Zeile holen und die nächsten 4:
Java:
 private void extract(Document doc) {
        Elements rows = doc.select("tr");
        final List<Integer> indexOfPassedCells = rows
                                          .stream()
                                          .map(e->e.select("td"))
                                          .filter(e-> e.hasClass("passed-cell"))
                                          .map(e->rows.indexOf(e.parents().get(0)))
                                          .collect(Collectors.toList());

        for (int indexOfPassedCell : indexOfPassedCells) {
            Element svr = rows.get(indexOfPassedCell);
            Element element1 = rows.get(indexOfPassedCell + 1);
            Element element2 = rows.get(indexOfPassedCell + 2);
            Element element3 = rows.get(indexOfPassedCell + 3);
            Element element4 = rows.get(indexOfPassedCell + 4);
            printElement(svr);
            printElement(element1);
            printElement(element2);
            printElement(element3);
            printElement(element4);
        }
    }

    private void printElement(Element e) {
        System.out.println(e.text());
    }
Ausgabe:
Code:
SVR_53
33
0
0
33
SVR_152
12
4
0
16
Hängt stark davon ab wie statisch dein Eingangs-HTML ist, ob dieser Zugriff per Index-gefrickel solide genug ist. Je nachdem ob noch andere Elemente dazwischen sein können kann man vielleicht auch einfach per Index "abzählen" (bspw. liegt an jedem Index, wenn man über alle tr iteriert bei i + i % 5 == 0 eine "passed-cell" usw.).
 
Zuletzt bearbeitet:
Danke für die schnelle Hilfe.
Die Eingangs html bleibt so statisch...immer SVR + die 4 Spalten
Meine Ausgabe ist aber leider mit dem kompletten hmtl-tags

HTML:
<tr>
<td class="passed-cell"> <span>SVR</span> </td>
<td class="number-cell"> <span>1</span> </td>
<td class="number-cell"></td>
<td class="number-cell"></td>
<td class="number-cell"> <span>1</span> </td>
</tr>
Und am Ende ein out of range Fehler
Java:
java.lang.IndexOutOfBoundsException: Index: 63, Size: 63
    at java.util.ArrayList.rangeCheck(Unknown Source)
    at java.util.ArrayList.get(Unknown Source)
Evtl eine Idee?

ps. Lässt sich anstatt der hasClass auch mit contains(SVR) nur danach suchen oder geht das nicht?
 
Ich habe wie gesagt mit dem angegebenen HTML gearbeitet, das eine andere Struktur hat als dein neues.Plötzlich sind mehrere Zellen in einer Zeile. Wenn sich die Struktur Ändern muss man auch den Parser anpassen:
Java:
 private void extract_bak(Document doc) {
    Elements cells = doc.select("tr td");
    final List<Integer> indexOfPassedCells = cells
                                      .stream()
                                      .filter(e-> e.hasClass("passed-cell"))
                                      .map(e->cells.indexOf(e))
                                      .collect(Collectors.toList());

    for (int indexOfPassedCell : indexOfPassedCells) {
        final Element svr = cells.get(indexOfPassedCell);
        final Element element1 = cells.get(indexOfPassedCell + 1);
        final Element element2 = cells.get(indexOfPassedCell + 2);
        final Element element3 = cells.get(indexOfPassedCell + 3);
        final Element element4 = cells.get(indexOfPassedCell + 4);
        printElement(svr);
        printElement(element1);
        printElement(element2);
        printElement(element3);
        printElement(element4);
    }
}
ps. Lässt sich anstatt der hasClass auch mit contains(SVR) nur danach suchen oder geht das nicht?
Java:
 final List<Integer> indexOfPassedCells = cells
                                          .stream()
                                          .filter(e-> e.text().contains("SVR"))
                                          .map(e->cells.indexOf(e))
                                          .collect(Collectors.toList());
Da du gesagt hast das HTML bleibt statisch kann man auch direkt den index berechnen statt abzufragen:
Java:
 private void extract(Document doc) {
    Elements cells = doc.select("tr td");
    for (int i = 0; i < cells.size(); i+=5) {
        int pos = i + i % 5;
        final Element svr = cells.get(pos);
        final Element element1 = cells.get(pos + 1);
        final Element element2 = cells.get(pos + 2);
        final Element element3 = cells.get(pos + 3);
        final Element element4 = cells.get(pos + 4);
        printElement(svr);
        printElement(element1);
        printElement(element2);
        printElement(element3);
        printElement(element4);
    }
}
 
Zuletzt bearbeitet:
Danke aber ich stehe vor einem anderen Problem mit dem parser.

Ausgehend von deinem CODE

Java:
private void extract_bak([URL='http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+document']Document[/URL] doc) {
        Elements cells = doc.select("tr td");
        final List<Integer> indexOfPassedCells = cells
                                          .stream()
                                          .filter(e-> e.hasClass("passed-cell"))
                                          .map(e->cells.indexOf(e))
                                          .collect(Collectors.toList());

        for (int indexOfPassedCell : indexOfPassedCells) {
            final [URL='http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+element']Element[/URL] svr = cells.get(indexOfPassedCell);
            final [URL='http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+element']Element[/URL] element1 = cells.get(indexOfPassedCell + 1);
            final [URL='http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+element']Element[/URL] element2 = cells.get(indexOfPassedCell + 2);
            final [URL='http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+element']Element[/URL] element3 = cells.get(indexOfPassedCell + 3);
            final [URL='http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+element']Element[/URL] element4 = cells.get(indexOfPassedCell + 4);
            printElement(svr);
            printElement(element1);
            printElement(element2);
            printElement(element3);
            printElement(element4);
        }
    }
Wie schaffe ich es, das er nach gewissen Kriterien die Tabelle durchsucht.
Beispielsweise nur die Elemente nimmt die SVR im Namen tragen?

Ich möchte verhindern, falls ein anderer Name auftaucht, dieser gelesen wird. Es sollen nur die Tabellenzeilen und Spalten mit dem Namen SVR ausgelesen werden
HTML:
<td class="passed-cell">
<span>Ergebniss</span>
</td>
<td class="number-cell">
<span>33</span>
</td>
<td class="number-cell"/>
<td class="number-cell"/>
<td class="number-cell">
<span>33</span>
</td>
Folgendes funktioniert nicht
Java:
if(svr .text().contains("SVR"))
 
Keine Ahnung, was du mit Eintragen meinst.
Aber filtern nach einem bestimmten SVR geht doch:
Java:
svr.text().contains("SVR_53")
Ah, inzwischen ist ein HTML in deiner bearbeiteten Antwort:
Auch nur die SVR filtern, wenn es noch anderen Typen gibt.
Java:
for (int indexOfPassedCell : indexOfPassedCells) {
    final Element svr = cells.get(indexOfPassedCell);
    if(svr.text().contains("SVR_")) {
        // ...
    } else {
       // Unknown type    
    }
}
 
Zuletzt bearbeitet:
Passende Stellenanzeigen aus deiner Region:

Oben