Beleg zu Daten & Prozesse

378 Bilddatensätze, acht Prüfabfragen

Wer Bilder aus einer fremden Quelle übernimmt, übernimmt deren Lücken mit: fehlende Lizenzangaben, Dubletten, Dateien, die im Verzeichnis nie ankommen. Auffallen tut das erst, wenn jemand ein Bild veröffentlicht, das er nicht veröffentlichen darf. Diese Arbeitsprobe zeigt den ganzen Weg – von der Schnittstelle über die Datenbank bis zu acht Abfragen, die den eigenen Bestand prüfen, statt ihm zu vertrauen.

189 Gehölzarten, 378 Bilder, eine fremde Datenquelle. Ein Python-Programm holt zu jeder Art zwei lizenzierte Fotos von iNaturalist und schreibt zu jedem Bild einen Metadatensatz. Aus diesen Metadaten entsteht hier eine kleine Datenbank, dazu acht Abfragen, die prüfen, ob der Bestand hält, was er verspricht. Eine davon findet etwas.

Der Anlass war unspektakulär: eine Lernkartensammlung zur Gehölzkunde, 189 botanische Namen in einem Anki-Deck, ohne Bilder. Bilder von Hand zu suchen hätte für jede Art zwei Entscheidungen gebraucht – welche Beobachtung, welches Foto – und bei 189 Arten wären das 378 Entscheidungen nach einem Bauchgefühl gewesen, das sich hinterher niemand mehr erklären kann.

Also wurden die Kriterien zuerst aufgeschrieben und dann in Code gefasst: Die Art muss exakt getroffen sein, die Beobachtung soll Research Grade haben, das Bild eine Mindestkantenlänge von 500 px, die Lizenz muss verwertbar sein – und die beiden Bilder einer Art dürfen nicht aus derselben Beobachtung stammen, sonst zeigen sie dieselbe Pflanze am selben Tag.

Das ist eine Datenpipeline. Es ist noch keine Datenbank. Die Metadaten lagen als CSV und JSON nebeneinander, ohne Schlüssel, ohne Beziehungen und ohne eine einzige Abfrage, die eine Aussage über ihre Qualität erzwingt. Diese Schicht ist 2026 nachträglich für dieses Portfolio entstanden – vier Tabellen in SQLite, acht Prüfabfragen, ein Bericht.

Der interessante Teil ist nicht, dass die Abfragen laufen. Der interessante Teil ist, dass eine davon einen Befund liefert – und dass dieser Befund nicht weggeräumt wurde.

Was davon meine Arbeit ist

  • Das Python-Programm – Konfiguration, API-Anbindung, Namensauflösung, Bewertung der Kandidaten, Download, Berichte. 12 Module, rund 2.300 Zeilen.
  • Die Datenbank und die Abfragen – Datenmodell, Import, acht Prüfungen, Prüfbericht. Nachträglich, 2026.
  • Nicht von mir – sämtliche Bilder und alle Inhalte der Metadatensätze. Sie stammen von iNaturalist-Nutzer:innen und stehen unter fünf verschiedenen Creative-Commons-Lizenzen.

Anlass war eine private Lernkartensammlung, kein Auftrag. Der User-Agent des Programms sagt das auch der API.

Was der Bestand hergibt

  • 189 Arten · 378 Metadatensätze · 378 Beobachtungen
  • 396 API-Anfragen, keine einzige Abweisung wegen Überlastung
  • 376 von 378 Fotos mit Research Grade
  • 378 von 378 mit Lizenzangabe: cc0 136, cc-by 214, cc-by-nc 26, cc-by-sa 2
  • 8 Prüfabfragen: 6 bestanden, 1 Befund, 1 zählt
  • 45 Regeltests, alle bestanden

Der Datenweg

1 Deck lesen 189 botanische Namen aus einer .apkg-Datei – mit zipfile und sqlite3 der Standardbibliothek. Das Deck wird nur gelesen, nie verändert.
2 Taxon auflösen Je Name mehrere Suchvarianten gegen /v1/taxa, von spezifisch nach allgemein. Ein reiner Gattungstreffer gilt nicht als Erfolg.
3 Kandidaten bewerten Bis zu 30 Beobachtungen je Art aus /v1/observations, jedes Foto nach sieben Kriterien bepunktet. Ohne Lizenz kein Download.
4 Ablegen und protokollieren Bild plus Metadatensatz mit Autor, Lizenz, Quell-URL, Prüfsumme. Dazu fünf Berichte, darunter einer nur für Problemfälle.
5 Datenbank und Prüfung Vier Tabellen in SQLite, acht Abfragen, ein Prüfbericht. Nachträglich ergänzt – der Teil, den das Originalprogramm nicht hat.

Schritte 1 bis 4 sind das Originalprogramm, Stand des Laufs: 30. August 2026. Schritt 5 ist die Ergänzung für dieses Portfolio. Beide Teile sind getrennt gehalten – der Originalcode wurde nicht angefasst.

Wie ein Bild ausgewählt wird

Die Auswahl ist ausdrücklich nicht „die ersten zwei Treffer". Jedes Foto bekommt Punkte, und jeder Punkt trägt seine Begründung mit in den Bericht. Die Reihenfolge der Kriterien ist die eigentliche Entscheidung – sie legt fest, was was überstimmt.

Aus src/selection.py und src/config.py des Programms, nicht nacherzählt.
KriteriumPunkteWarum
Taxon identisch+40Ein anderes Taxon zeigt womöglich eine andere Art.
Research Grade+35Mehrere Personen haben die Bestimmung bestätigt.
Lizenz+15 bis +30Freiere Lizenz ist besser: cc0 vor cc-by vor cc-by-sa vor cc-by-nc.
Kurze Kante ab 1.500 px+20Auflösung, gestaffelt bis hinunter zur Mindestkante.
Abweichendes Taxon−15Abwertung, kein Ausschluss – der Bericht führt es als Problemfall.
Kurze Kante unter 500 px−25Für eine Lernkarte unbrauchbar.
Seitenverhältnis über 3:1−10Deutet auf Panorama oder engen Ausschnitt hin.
Keine Lizenzangabe−1000Ausschluss. „Alle Rechte vorbehalten" wird nie stillschweigend übernommen.

Danach kommt die Regel, die im Bericht am häufigsten sichtbar wird: Erst wird je Beobachtung das beste Foto genommen, und nur wenn keine zweite Beobachtung übrig bleibt, ein zweites Foto derselben. Deshalb stammen bei allen 189 Arten die beiden Bilder aus verschiedenen Beobachtungen – Prüfabfrage 7 rechnet das nach.

Gegenüber der API verhält sich das Programm zurückhaltend: eine Sekunde Pause zwischen zwei Anfragen, höchstens 50 pro Minute bei erlaubten 60, vier Versuche mit wachsender Wartezeit. Im dokumentierten Lauf kam über 396 Anfragen keine einzige Abweisung wegen Überlastung zurück.

Das Datenmodell

Vier Tabellen. Was in den Quelldaten nicht vorkommt, steht auch nicht im Modell: Ein Anki-Deck mit botanischen Namen kennt keinen deutschen Trivialnamen, und welche Suchvariante am Ende gegriffen hat, hält kein Metadatensatz fest. Zwei leere Spalten mitzuführen wäre die unehrlichere Lösung gewesen.

TabelleZeilenFelder
plants
Artenstamm
189 plant_id, scientific_name (Name im Deck), name_kern, taxon_id, taxon_name (Name bei iNaturalist), taxon_kern, name_abweichung
observations
Beobachtungen
378 observation_id, plant_id, source, observed_on, quality_grade, place_guess, source_url
images
Bildmetadaten
378 image_id, observation_id, plant_id, selected_rank, filename, url, license_code, author, attribution, width, height, sha256, file_present
checks
Prüfergebnisse
8 check_id, check_type, frage, sql, expected, actual, status, note

Der Import ist wiederholbar und nicht additiv: Ein zweiter Lauf legt die Datei neu an, statt Zeilen zu verdoppeln. Fehlende Werte bleiben NULL – nichts wird stillschweigend ersetzt, denn genau diese Lücken sollen die Abfragen ja finden.

Dass die Tabelle observations genauso viele Zeilen hat wie images, ist kein Modellierungsfehler, sondern das Ergebnis der Auswahlregel: Weil je Bild eine eigene Beobachtung gewählt wurde, steht hinter jedem Bild genau eine. Ein Modell, das das nicht abbilden könnte, könnte Prüfabfrage 7 nicht stellen.

Die acht Prüfabfragen

Jede Abfrage hat einen Sollwert. Bestanden heißt: Die Abfrage findet nichts. Befund heißt: Sie findet etwas – und das ist dann das Ergebnis, kein Fehler des Programms.

Nr.PrüfungFrageErgebnis
1AbdeckungWelche Pflanzen haben weniger als zwei ausgewählte Bilder?0 – bestanden
2DublettenWelche Bild-URLs kommen mehrfach vor?0 – bestanden
3NachvollziehbarkeitWelche Bilder haben keine Quell-ID oder keine Quell-URL?0 – bestanden
4LizenzWelche Bilder tragen keine verwertbare Lizenzangabe?0 – bestanden
5NutzbarkeitWelche Bilder unterschreiten 500 px Mindestkantenlänge?0 – bestanden
6AblageZu welchen Metadatensätzen fehlt die Bilddatei im Ordner?6 – Befund
7PlausibilitätStammen die beiden Bilder einer Art aus verschiedenen Beobachtungen?0 – bestanden
8TaxonomieBei welchen Arten steht hinter dem abweichenden Namen ein anderer Artbegriff?21 – gezählt

Die acht Abfragen ausführen Prüfbericht (CSV)

Der Befund: sechs fehlende Dateien

Der Download-Bericht des Programms meldet 378 Bilder vorhanden, Ziel 378. Im Bildordner liegen aber 372 Dateien. Die Abfrage, die Metadaten gegen Dateibestand hält, benennt die Differenz:

SELECT i.filename, p.scientific_name, i.license_code
FROM images i
JOIN plants p ON p.plant_id = i.plant_id
WHERE i.file_present = 0
ORDER BY p.scientific_name, i.selected_rank
filenamescientific_namelicense_code
Lonicera_pileata_1.jpgLonicera pileata*cc-by
Lonicera_pileata_2.jpgLonicera pileata*cc-by
Spiraea_x_arguta_1.jpgSpiraea × argutacc0
Spiraea_x_arguta_2.jpgSpiraea × argutacc-by
Spiraea_x_vanhouttei_1.jpgSpiraea × vanhoutteicc0
Spiraea_x_vanhouttei_2.jpgSpiraea × vanhoutteicc0

Es sind nicht sechs beliebige Dateien. Es sind genau die Bilder der drei Arten, die das Programm im Problembericht selbst als REVIEW markiert hat. Spiraea × arguta und Spiraea × vanhouttei fallen bei iNaturalist auf dasselbe Taxon zusammen – ohne Gegenmaßnahme hätten beide Arten identische Fotos bekommen. Das Programm hat das nach dem Durchlauf erkannt, für die zweite Art auf Ersatzfotos ausgewichen und beide Fälle zur Prüfung vorgelegt. Lonicera pileata* wurde auf das breitere Taxon Lonicera ligustrina aufgelöst.

Warum der Befund stehen bleibt

Es wäre in zwei Minuten erledigt gewesen: Datensätze löschen, Abfrage grün, acht von acht. Nur wäre dann eine Prüfung verschwunden, die genau das gefunden hat, wofür sie da ist. Der Zustand ist nachvollziehbar – jemand hat die drei fraglichen Arten aussortiert, ohne die Metadaten mitzunehmen. Eine Datenqualitätsprüfung, deren Befunde man wegräumt, prüft nichts mehr.

Die achte Abfrage zählt, statt zu urteilen

Bei 36 der 189 Arten weicht der Name bei iNaturalist vom Namen im Deck ab. Als Zahl ist das wertlos: Bei 15 davon ist es nur die Schreibweise – das Deck führt Prunus avium* mit einer Merkhilfe, iNaturalist schreibt Prunus avium. Solche Zusätze werden vor dem Vergleich gestrichen, in SQL wie in der Browserfassung nach derselben Regel.

Übrig bleiben 21 Fälle, in denen der Name selbst ein anderer ist. Auch diese sind nicht gleichartig, und genau deshalb bewertet die Abfrage sie nicht:

BeispielWas dahintersteckt
Euonymus europaea → Euonymus europaeusGrammatische Endung. Dieselbe Art.
Sorbus aria → Aria edulisGültige taxonomische Revision, andere Gattung.
Mahonia aquifolium → Berberis aquifoliumEbenso – der gebräuchliche Name ist heute ein Synonym.
Hydrangea arborescens ssp. arborescens → Hydrangea arborescensUnterart auf Art zusammengezogen. Bilder zeigen möglicherweise eine andere Unterart.
Lonicera pileata* → Lonicera ligustrinaAuf ein breiteres Taxon aufgelöst. Fachlich zu prüfen.

Die ersten drei Zeilen sind unbedenklich, die letzten beiden nicht – und diesen Unterschied kann keine SQL-Abfrage entscheiden. Sie kann nur die Liste erzeugen, die jemand ansehen muss. Deshalb hat Abfrage 8 als einzige keinen Sollwert und den Status gezählt statt bestanden. Eine Prüfung, die hier ein Urteil fällte, wäre genau die Sorte Automatisierung, die hinterher niemand mehr auffängt.

Dieselbe Sorgfalt, andere Quelle

Eine zweite Recherche gegen eine fremde Schnittstelle – diesmal gegen das österreichische Rechtsinformationssystem: Rechtsbestand aus dem RIS →
Und was aus diesen 371 Bildern geworden ist: ein Bestimmungswerkzeug für 189 Arten →

Grenzen dieses Belegs

  • Keine Berufserfahrung mit Datenbanken. Die SQLite-Schicht ist 2026 nachträglich für dieses Portfolio entstanden. Es gibt keine berufliche Station, in der ich mit SQL gearbeitet habe, und das Originalprogramm hat keine Datenbank. Belegt ist, dass ich ein Datenmodell aufsetzen, Daten reproduzierbar importieren und Qualitätsprüfungen formulieren kann.
  • 378 Datensätze sind eine kleine Datenmenge. Nichts an diesem Beleg sagt etwas über Datenmengen, Indizes, Abfrageoptimierung oder Datenbankbetrieb aus.
  • Kein juristischer Beleg. Der RIS-Fall zeigt Recherche in einer Fachdatenbank mit Quellenhierarchie und Fassungsständen. Er ist keine Rechtsauskunft, keine Rechtsberatung und kein Nachweis juristischer Ausbildung oder Behördenpraxis.
  • Kein Anlass war beruflich. Die Bildersammlung entstand für eigene Lernkarten, der Skill als Werkzeug für eine andere Person, der Recherchefall aus einem Studienprojekt.
  • Keine Bilder zum Herunterladen. Die 618 MB Bildmaterial gehören iNaturalist-Nutzer:innen und stehen unter fünf verschiedenen Lizenzen. Weitergegeben werden nur die Metadaten – mit Autor, Lizenz und Quell-URL, denn ohne sie dürfte auch das nicht.

Zum Nachrechnen

Prüfabfragen im Browser Datenbank (SQLite, 252 KB) Prüfbericht (CSV) Metadaten (CSV, 132 KB) RIS-Protokoll (Text)

Die Datenbank lässt sich mit jedem SQLite-Werkzeug öffnen; die Tabelle checks enthält alle acht Abfragen im Wortlaut samt Sollwert und Ergebnis. Erzeugt werden beide Dateien von skripte/artdaten-datenbank.py, das Rechercheprotokoll von skripte/ris-recherche.py. Beide Skripte liegen außerhalb des Website-Ordners und werden nicht mit ausgeliefert.

Weiterlesen

Zurück zum Einstieg für Daten und Prozesse · derselbe Umgang mit Pflanzendaten, aber mit einem Sprachmodell im Ablauf: Make gegen Zapier, an einer echten Strecke · das Gebiet aus dem Rechtsfall, fachlich: Wienerberg – Feldbezug und Grenzen · Datenqualität an einem anderen Bestand: PIM-Werkzeug.

Wo ein fremder Datenbestand geprüft werden muss

Wenn Sie eine Rolle im Datenmanagement, in der Datenqualität oder im Reporting besetzen: Diese Seite zeigt den ganzen Weg von der Schnittstelle bis zur Prüfabfrage, mit jedem Befund dazwischen.

E-Mail schreiben Lebenslauf ansehen Alle Kontaktwege