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
.apkg-Datei – mit zipfile und sqlite3 der Standardbibliothek. Das Deck wird nur gelesen, nie verändert.
/v1/taxa, von spezifisch nach allgemein. Ein reiner Gattungstreffer gilt nicht als Erfolg.
/v1/observations, jedes Foto nach sieben Kriterien bepunktet. Ohne Lizenz kein Download.
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.
| Kriterium | Punkte | Warum |
|---|---|---|
| Taxon identisch | +40 | Ein anderes Taxon zeigt womöglich eine andere Art. |
| Research Grade | +35 | Mehrere Personen haben die Bestimmung bestätigt. |
| Lizenz | +15 bis +30 | Freiere Lizenz ist besser: cc0 vor cc-by vor cc-by-sa vor cc-by-nc. |
| Kurze Kante ab 1.500 px | +20 | Auflösung, gestaffelt bis hinunter zur Mindestkante. |
| Abweichendes Taxon | −15 | Abwertung, kein Ausschluss – der Bericht führt es als Problemfall. |
| Kurze Kante unter 500 px | −25 | Für eine Lernkarte unbrauchbar. |
| Seitenverhältnis über 3:1 | −10 | Deutet auf Panorama oder engen Ausschnitt hin. |
| Keine Lizenzangabe | −1000 | Ausschluss. „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.
| Tabelle | Zeilen | Felder |
|---|---|---|
| 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üfung | Frage | Ergebnis |
|---|---|---|---|
| 1 | Abdeckung | Welche Pflanzen haben weniger als zwei ausgewählte Bilder? | 0 – bestanden |
| 2 | Dubletten | Welche Bild-URLs kommen mehrfach vor? | 0 – bestanden |
| 3 | Nachvollziehbarkeit | Welche Bilder haben keine Quell-ID oder keine Quell-URL? | 0 – bestanden |
| 4 | Lizenz | Welche Bilder tragen keine verwertbare Lizenzangabe? | 0 – bestanden |
| 5 | Nutzbarkeit | Welche Bilder unterschreiten 500 px Mindestkantenlänge? | 0 – bestanden |
| 6 | Ablage | Zu welchen Metadatensätzen fehlt die Bilddatei im Ordner? | 6 – Befund |
| 7 | Plausibilität | Stammen die beiden Bilder einer Art aus verschiedenen Beobachtungen? | 0 – bestanden |
| 8 | Taxonomie | Bei welchen Arten steht hinter dem abweichenden Namen ein anderer Artbegriff? | 21 – gezählt |
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
| filename | scientific_name | license_code |
|---|---|---|
Lonicera_pileata_1.jpg | Lonicera pileata* | cc-by |
Lonicera_pileata_2.jpg | Lonicera pileata* | cc-by |
Spiraea_x_arguta_1.jpg | Spiraea × arguta | cc0 |
Spiraea_x_arguta_2.jpg | Spiraea × arguta | cc-by |
Spiraea_x_vanhouttei_1.jpg | Spiraea × vanhouttei | cc0 |
Spiraea_x_vanhouttei_2.jpg | Spiraea × vanhouttei | cc0 |
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:
| Beispiel | Was dahintersteckt |
|---|---|
Euonymus europaea → Euonymus europaeus | Grammatische Endung. Dieselbe Art. |
Sorbus aria → Aria edulis | Gültige taxonomische Revision, andere Gattung. |
Mahonia aquifolium → Berberis aquifolium | Ebenso – der gebräuchliche Name ist heute ein Synonym. |
Hydrangea arborescens ssp. arborescens → Hydrangea arborescens | Unterart auf Art zusammengezogen. Bilder zeigen möglicherweise eine andere Unterart. |
Lonicera pileata* → Lonicera ligustrina | Auf 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.