Dev.to WebDev 🛠 Dev 👁 0 📖 5 min read

HTML-Tabellen mit versteckten Daten: Scrapen, was man nicht sieht

Die Tabelle zeigt 10 Spalten. Man exportiert sie. Die CSV hat 10 Spalten. Aber die Seite hat 15 Spalten an Daten. Wo sind die anderen 5 geblieben? HTML-Tabellen enthalten oft mehr Daten als sichtbar. Versteckte Spalten

Die Tabelle zeigt 10 Spalten. Man exportiert sie. Die CSV hat 10 Spalten.

Aber die Seite hat 15 Spalten an Daten. Wo sind die anderen 5 geblieben?

HTML-Tabellen enthalten oft mehr Daten als sichtbar. Versteckte Spalten, Data-Attribute, eingeklappte Zeilen — alles unsichtbar für einfache Extraktionsmethoden.

So findet und extrahiert man die Daten, die man nicht sieht.

Arten versteckter Daten

1. CSS-versteckte Spalten

Der einfachste Fall: Spalten existieren im DOM, sind aber per CSS versteckt.

<th style="display: none;">Interne ID</th>
<td style="display: none;">12345</td>

Oder über Klassen:

.hidden-column { display: none; }

Warum Websites das machen: Mobile Responsiveness (Spalten auf kleinen Bildschirmen ausblenden), interne Daten für JavaScript, schrittweise Offenlegung.

Wie man es erkennt: DevTools öffnen, die Tabelle inspizieren, nach Zellen mit display: none oder visibility: hidden suchen.

2. Data-Attribute

HTML5 erlaubt benutzerdefinierte data-* Attribute auf jedem Element. Tabellen nutzen diese, um Metadaten zu speichern, auf die JavaScript zugreift, die der Nutzer aber nicht sieht.

<tr data-id="12345" data-category="elektronik" data-stock="47">
  <td>Laptop</td>
  <td>999 €</td>
</tr>

Die sichtbare Tabelle zeigt „Laptop" und „999 €". Aber die Zeile trägt drei zusätzliche Datenpunkte.

Häufige Data-Attribute:

  • data-id — interner Bezeichner
  • data-sort-value — numerischer Wert zum Sortieren (wenn die Anzeige „Jan 2024" zeigt, aber die Sortierung 202401 braucht)
  • data-raw — unformatierter Wert (wenn die Anzeige „1,2 Mio. €" zeigt, aber der Wert 1200000 ist)
  • data-href — Link-URL

3. Title- und Tooltip-Attribute

Das title-Attribut liefert Hover-Text, der oft zusätzliche Informationen enthält.

<td title="Aktualisiert: 2024-01-15 14:32:00 UTC">15. Jan</td>

Die Zelle zeigt „15. Jan". Der vollständige Zeitstempel steckt im Tooltip.

4. Eingeklappte/Erweiterbare Zeilen

Tabellen mit Drill-Down-Funktionalität verstecken Detailzeilen, bis man klickt.

<tr class="parent-row">
  <td>Kategorie A</td>
  <td>50.000 €</td>
</tr>
<tr class="child-row" style="display: none;">
  <td>— Unterkategorie A1</td>
  <td>30.000 €</td>
</tr>
<tr class="child-row" style="display: none;">
  <td>— Unterkategorie A2</td>
  <td>20.000 €</td>
</tr>

Die Daten existieren. Sie sind nur nicht aufgeklappt.

5. Lazy-Loaded-Inhalte

Manche Tabellen zeigen eine Teilmenge und laden mehr per JavaScript, wenn man scrollt oder auf „Mehr laden" klickt.

<table id="results">
  <!-- Erste 20 Zeilen gerendert -->
</table>
<button onclick="loadMore()">Mehr Ergebnisse anzeigen</button>

Die restlichen Daten sind nicht im DOM, bis man das Laden auslöst.

Versteckte Daten extrahieren

CSS-versteckte Spalten extrahieren

Mit JavaScript (in der Browser-Konsole):

// display:none von allen Zellen entfernen
document.querySelectorAll('td, th').forEach(el => {
  el.style.display = '';
});

Jetzt normal exportieren — die Spalten sind sichtbar.

Mit Python + BeautifulSoup:

BeautifulSoup ignoriert CSS. Es extrahiert alle Elemente unabhängig von der Sichtbarkeit.

from bs4 import BeautifulSoup

soup = BeautifulSoup(html, 'html.parser')
table = soup.find('table')

for row in table.find_all('tr'):
    cells = [td.get_text(strip=True) for td in row.find_all(['td', 'th'])]
    print(cells)  # Enthält versteckte Spalten

Data-Attribute extrahieren

JavaScript-Ansatz:

const rows = document.querySelectorAll('table tr');
const data = [];

rows.forEach(row => {
  const rowData = {
    // Sichtbarer Text
    cells: Array.from(row.querySelectorAll('td')).map(td => td.textContent),
    // Data-Attribute
    id: row.dataset.id,
    category: row.dataset.category,
    stock: row.dataset.stock
  };
  data.push(rowData);
});

console.log(JSON.stringify(data, null, 2));

Python-Ansatz:

for row in table.find_all('tr'):
    # Data-Attribute holen
    attrs = {k: v for k, v in row.attrs.items() if k.startswith('data-')}

    # Zellentext holen
    cells = [td.get_text(strip=True) for td in row.find_all('td')]

    print(f"Daten: {attrs}, Zellen: {cells}")

Title-Attribute extrahieren

const cells = document.querySelectorAll('table td');
cells.forEach(cell => {
  if (cell.title) {
    console.log(`Anzeige: ${cell.textContent}, Voll: ${cell.title}`);
  }
});

Eingeklappte Zeilen expandieren

Option 1: Alle Expander klicken

// Alle Expand-Buttons finden und klicken
document.querySelectorAll('.expand-btn, .toggle-row').forEach(btn => {
  btn.click();
});

// Auf DOM-Update warten, dann exportieren
setTimeout(() => {
  // Export-Logik hier
}, 1000);

Option 2: Hidden-Klasse entfernen

document.querySelectorAll('.child-row, .detail-row').forEach(row => {
  row.style.display = '';
  row.classList.remove('hidden', 'collapsed');
});

Lazy Load auslösen

Das ist kniffliger — man muss die Aktion simulieren, die das Laden auslöst.

// Zum Ende scrollen, um Infinite Scroll auszulösen
window.scrollTo(0, document.body.scrollHeight);

// Oder "Mehr laden" wiederholt klicken
const loadMore = document.querySelector('.load-more-btn');
while (loadMore && !loadMore.disabled) {
  loadMore.click();
  await new Promise(r => setTimeout(r, 500)); // Auf Laden warten
}

Praxisbeispiel: Sort-Werte

Sportstatistik-Tabellen zeigen oft formatierte Zahlen, sortieren aber nach Rohwerten.

<td data-sort="1234567">1,23 Mio.</td>
<td data-sort="20240115">15. Jan 2024</td>
<td data-sort="0.347">34,7 %</td>

Wenn man nur den sichtbaren Text extrahiert, bekommt man formatierte Strings, die sich nicht sortieren oder berechnen lassen.

Extraktion mit beiden Werten:

const cells = document.querySelectorAll('table td');
const data = Array.from(cells).map(cell => ({
  display: cell.textContent.trim(),
  sortValue: cell.dataset.sort || cell.textContent.trim()
}));

Wann Browser-Erweiterungen helfen

Gute Tabellenexport-Tools erledigen einiges davon automatisch:

  • CSS-versteckte Spalten können per Option einbezogen werden
  • Data-Attribute können als zusätzliche Spalten extrahiert werden
  • Zahlennormalisierung kann „1,23 Mio. €" in 1230000 umwandeln

HTML Table Exporter extrahiert sichtbare Inhalte mit korrekter Behandlung zusammengeführter Zellen und Formatierung. Für komplexere Extraktionsanforderungen ohne Code siehe unseren Leitfaden zu HTML-Tabellen-Scrapern für Chrome.

Für Data-Attribute und tief versteckte Inhalte benötigt man möglicherweise die oben gezeigten JavaScript-Ansätze.

Der Inspektions-Workflow

Vor dem Extrahieren jeder Tabelle:

  1. DevTools öffnen (F12)
  2. Das Tabellenelement inspizieren
  3. Prüfen auf:
    • display: none bei Spalten
    • data-* Attribute auf Zeilen/Zellen
    • title-Attribute mit Zusatzinfos
    • Versteckte Kindzeilen
    • „Mehr laden"-Buttons
  4. Entscheiden: Reichen die sichtbaren Daten, oder braucht man die versteckten Daten?

Meistens reichen die sichtbaren Daten. Aber wenn nicht, macht das Wissen, wie man versteckte Daten findet und extrahiert, den entscheidenden Unterschied.

Zusammenfassung

HTML-Tabellen können mehrere Datenschichten enthalten:

Schicht Zugriffsmethode
Sichtbarer Text Standard-Export
CSS-versteckte Spalten display:none entfernen oder BeautifulSoup verwenden
Data-Attribute JavaScript dataset oder Python attrs
Title/Tooltips title-Attribut extrahieren
Eingeklappte Zeilen Expandieren oder Hidden-Klasse entfernen
Lazy-Loaded Laden zuerst auslösen

Die Daten sind meistens da. Man muss nur wissen, wo man suchen muss.

Sichtbare Daten exportieren? Erfahren Sie mehr auf gauchogrid.com/de/html-table-exporter oder probieren Sie HTML Table Exporter kostenlos im Chrome Web Store.

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.