Skip to content

matzejo/open-data-katalog

Repository files navigation

Open Data Metadata Catalog

Ein lokaler Metadaten-Katalog für Open-Data-Quellen.
Harvestet Metadaten von öffentlichen Datenportalen, speichert sie in einer DuckDB und macht sie über ein Streamlit-Dashboard durchsuchbar.


Features

  • 🔍 Metadaten-Suche über 400.000+ Datensätze aus 6+ Portalen
  • 📊 Streamlit-Dashboard mit 4D-Explorer, Parallel-Ansicht, Karte und CSV-Export
  • 🔄 Idempotenter Harvest — UPSERT auf Primärschlüssel, keine Duplikate
  • 📦 Provenienz — Rohdaten unverändert als gzip-JSONL archiviert
  • 🔌 Erweiterbar — neue Portal-Typen durch eine Python-Klasse
  • 💻 Lokal & offline — DuckDB auf lokaler Platte, keine Cloud-Abhängigkeit

Unterstützte Quellen

Portal Typ Datasets Lizenz
GovData CKAN ~151.000 variiert
Hamburg Transparenzportal CKAN ~237.000 variiert
Open.NRW CKAN ~10.000 variiert
Open Data München CKAN ~336 variiert
Our World in Data OWID Search-API ~12.000 Charts CC-BY-4.0
Destatis GENESIS-Online REST (POST) ~110.000+ dl-de/by-2-0

Quickstart

# 1. Repository klonen
git clone https://github.com/YOUR_USER/open-data-katalog.git
cd open-data-katalog

# 2. Virtuelle Umgebung erstellen
python -m venv .venv
source .venv/bin/activate  # Linux/Mac
.venv\Scripts\activate      # Windows

# 3. Abhängigkeiten installieren
pip install -r requirements.txt

# 4. Portale konfigurieren
cp seeds.example.yaml seeds.yaml
# → seeds.yaml bearbeiten, ggf. Destatis-Token eintragen

# 5. Harvest starten
python harvester.py

# 6. Dashboard starten
streamlit run dashboard.py --server.port 8501

Projektstruktur

open-data-katalog/
├── harvester.py              # Haupt-Harvester (CKAN + OWID)
├── harvester_destatis.py     # Separater Destatis-Harvester
├── dashboard.py              # Streamlit-Dashboard
├── seeds.yaml                # Portal-Konfiguration
├── seeds.example.yaml        # Beispiel-Konfiguration (ohne Tokens)
├── requirements.txt          # Python-Abhängigkeiten
├── catalog.db                # DuckDB (wird vom Harvester erzeugt)
├── log.md                    # Append-only Ingest-Log
├── sources/                  # Rohdaten (gzip-JSONL, Provenienz)
│   ├── ckan/<portal>/<date>/
│   ├── owid/<portal>/<date>/
│   └── destatis/<portal>/<date>/
└── .github/workflows/ci.yml  # CI (Syntax-Check)

Architektur

┌─────────────┐   ┌─────────────┐   ┌─────────────┐
│  CKAN-API   │   │ OWID-API   │   │ Destatis-API│
│  (REST)     │   │ (Search)   │   │ (POST)      │
└──────┬──────┘   └──────┬──────┘   └──────┬──────┘
       │                 │                 │
       ▼                 ▼                 ▼
┌─────────────────────────────────────────────────┐
│              harvester.py / _destatis.py         │
│  → Paginierter Abruf                            │
│  → Rohdaten als gzip-JSONL (Provenienz)         │
│  → Normalisierung + UPSERT in DuckDB            │
└─────────────────────┬───────────────────────────┘
                      │
                      ▼
┌─────────────────────────────────────────────────┐
│              catalog.db (DuckDB)                 │
│  datasets: portal, dataset_id, titel, thema,    │
│            publisher, formate, lizenz, url, …   │
│  tags:     portal, dataset_id, tag              │
└─────────────────────┬───────────────────────────┘
                      │
                      ▼
┌─────────────────────────────────────────────────┐
│              dashboard.py (Streamlit)            │
│  → Sidebar-Filter (Portal, Thema, Lizenz, …)    │
│  → KPI-Zeile (Datasets, Portale, Formate, …)    │
│  → 4D-Explorer (Bubble-Matrix)                  │
│  → Parallel-Ansicht (Plotly parallel_categories) │
│  → Karte (Portal-Standorte)                     │
│  → Datentabelle + CSV-Export                     │
└─────────────────────────────────────────────────┘

Harvest-Workflow

  1. seeds.yaml definiert Portale mit Typ und Basis-URL
  2. harvester.py iteriert über alle Portale
  3. Pro Portal: paginierter API-Abruf → Rohdaten speichern → normalisieren → UPSERT
  4. log.md dokumentiert jeden Lauf (append-only)
  5. Dashboard liest read-only aus der DuckDB

Destatis-Besonderheiten

  • Die GENESIS-API unterstützt nur POST (GET wurde am 15.07.2025 abgeschaltet)
  • Authentifizierung per username/password als HTTP-Header
  • Kostenlose Registrierung unter genesis.destatis.de
  • API ist langsam (~25s/Page) — Batch-Commit alle 50 Seiten

Erweiterung: Neuen Portal-Typ hinzufügen

  1. In harvester.py eine neue harvest_*-Funktion schreiben
  2. In harvest_portal() den neuen Typ registrieren
  3. In seeds.yaml einen Eintrag mit type: dein_typ hinzufügen
def harvest_mein_portal(con, session, name, base_url):
    # 1. API abrufen
    # 2. Rohdaten speichern (save_raw / save_raw_*)
    # 3. Normalisieren → rows + tags
    # 4. upsert_datasets() + upsert_tags()
    # 5. append_log()

Lizenz

MIT — siehe LICENSE.

Haftungsausschluss

Dieses Projekt erntet ausschließlich Metadaten (Titel, Beschreibung, Lizenz, URL),
niemals die eigentlichen Dateninhalte. Die Nutzung der Daten unterliegt den
Lizenzen der jeweiligen Quellportale.

About

No description, website, or topics provided.

Resources

License

Stars

2 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages