Automatisierte Aggregation von EU-, AT-, DE- und CH-Gesetzgebung mit Fokus auf den EU AI Act.
Legal Scraper aggregiert Gesetze und Verordnungen aus vier offiziellen europaeischen Rechtsquellen in einer durchsuchbaren SQLite-Datenbank mit Meilisearch-Volltextsuche. Der Fokus liegt auf dem EU AI Act (Verordnung 2024/1689), der auf Artikelebene (Art. 1-113) geparst wird.
graph LR
A["EUR-Lex<br/>SPARQL + CELLAR"] -->|HTML| P["Parser<br/>lxml + regex"]
B["RIS Austria<br/>REST API"] -->|JSON + HTML| P
C["Gesetze-im-Internet<br/>XML Bulk"] -->|ZIP + XML| P
D["Fedlex Switzerland<br/>SPARQL + PDF"] -->|PDF| P
P -->|upsert + SHA-256| S["SQLite<br/>FTS5"]
S -->|batch sync| M["Meilisearch<br/>Volltextindex"]
S --> UI["Streamlit<br/>Dashboard"]
M --> UI
S -.->|"1019+ Dokumente"| S
| Feature | Beschreibung |
|---|---|
| Multi-Source Scraping | Vier offizielle Rechtsquellen (AT, EU, DE, CH) ueber REST, SPARQL und XML |
| EU AI Act Parser | Artikel-Level Parsing (Art. 1-113) der Verordnung 2024/1689 fuer praezise RAG-Queries |
| Change Detection | SHA-256 Hash-Vergleich erkennt Gesetzesaenderungen automatisch |
| Dual Search | Meilisearch (primaer) mit SQLite FTS5 Fallback |
| Scheduled Scraping | APScheduler fuehrt taeglich um 02:00 Uhr automatisch alle Scraper aus |
| REST API | FastAPI mit Swagger-Docs fuer Suche, Statistiken und manuelle Scraper-Trigger |
| Streamlit UI | Dashboard mit Suche, Statistiken und Scraper-Steuerung |
| PDF-Extraktion | PyMuPDF extrahiert Volltext aus Fedlex-PDFs |
| Alerting | Optionale Benachrichtigungen bei neuen/geaenderten Gesetzen (Mattermost, ERPNext) |
| Docker | 3-Container Setup (App, Meilisearch, UI) mit docker compose |
| Quelle | Land | Methode | Inhalte |
|---|---|---|---|
| RIS Austria | AT | REST API | Bundesgesetze, Verordnungen (konsolidiert) |
| EUR-Lex / CELLAR | EU | SPARQL | EU-Verordnungen, Richtlinien seit 2000 |
| Gesetze-im-Internet | DE | XML Bulk | ~6.000 deutsche Bundesgesetze |
| Fedlex | CH | SPARQL + PDF | Schweizer Bundesgesetze |
# Repository klonen
git clone https://github.com/AI-Engineerings-at/legal-scraper.git
cd legal-scraper
# Konfiguration anlegen
cp .env.example .env
# MEILISEARCH_KEY in .env setzen (min. 16 Zeichen)
# Starten
docker compose up -d
# Ersten Scrape manuell ausloesen
curl -X POST http://localhost:8000/scrape/all| Service | URL |
|---|---|
| Streamlit UI | http://localhost:8501 |
| API | http://localhost:8000 |
| API Docs (Swagger) | http://localhost:8000/docs |
| Meilisearch | http://localhost:7700 |
# Volltextsuche
curl "http://localhost:8000/search?q=Datenschutz&source=ris_austria&limit=10"
# Statistiken
curl http://localhost:8000/stats
# Einzelnen Scraper starten
curl -X POST http://localhost:8000/scrape/eurlex
# Alle Scraper starten
curl -X POST http://localhost:8000/scrape/all
# Scraper-Status
curl http://localhost:8000/scraper-statuslegal-scraper/
├── docker-compose.yml
├── .env.example
├── app/
│ ├── Dockerfile
│ ├── requirements.txt
│ ├── main.py # FastAPI + APScheduler
│ ├── database.py # SQLite + FTS5 + Change Detection
│ ├── search_index.py # Meilisearch Sync
│ ├── change_alerts.py # Mattermost + ERPNext Alerts
│ ├── sync_to_notebook.py # open-notebook Integration
│ └── scrapers/
│ ├── __init__.py
│ ├── ris_austria.py # RIS Austria REST API
│ ├── eurlex.py # EUR-Lex SPARQL + CELLAR
│ ├── euaiact.py # EU AI Act Artikel-Parser
│ ├── gesetze_im_internet.py # XML Bulk Download
│ └── fedlex.py # Fedlex SPARQL + PDF
├── ui/
│ ├── Dockerfile
│ └── app.py # Streamlit Dashboard
└── data/ # Persistente Daten (auto-erstellt, gitignored)
├── sqlite/
└── meilisearch/
Alle Konfiguration erfolgt ueber Umgebungsvariablen in .env:
| Variable | Pflicht | Beschreibung |
|---|---|---|
MEILISEARCH_KEY |
Ja | Master Key fuer Meilisearch (min. 16 Zeichen) |
LOG_LEVEL |
Nein | DEBUG, INFO, WARNING, ERROR (Standard: INFO) |
MM_URL |
Nein | Mattermost Server URL fuer Alerts |
MM_ALERT_TOKEN |
Nein | Mattermost Bot Token |
MM_CHANNEL |
Nein | Mattermost Channel ID |
ERPNEXT_URL |
Nein | ERPNext URL fuer Task-Erstellung |
ERPNEXT_API_KEY |
Nein | ERPNext API Key |
ERPNEXT_API_SECRET |
Nein | ERPNext API Secret |
NOTEBOOK_URL |
Nein | open-notebook URL fuer Sync |
NOTEBOOK_ID |
Nein | open-notebook Notebook ID |
- Neue Datei anlegen:
app/scrapers/neue_quelle.py async def run()implementieren, diedatabase.upsert_document()aufruft- In
app/scrapers/__init__.pyregistrieren:
from . import neue_quelle
ALL_SCRAPERS = { ..., "neue_quelle": neue_quelle.run }MIT License. Siehe LICENSE.
Built by AI Engineering
