Poller, Schema, Quadlet-Units und Quellenregister aus dem Monorepo gdelt-bot in ein eigenes Repo ausgelagert. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VzNVf1KaHPZ1fzJT2jd18j
4.6 KiB
Ingest
Stufe 0 und 1 der Pipeline: Quellenregister und Roh-Erfassung. Keine Kodierung — was hier landet, soll sich beliebig oft neu kodieren lassen.
Dateien
| Datei | Zweck |
|---|---|
sources.toml |
Quellenregister, einzige Wahrheit ueber die Quellen |
schema.sql |
Postgres-Schema (quellen, raw_items, codings, poll_laeufe) |
poller.py |
Poller, zwei Senken: Postgres und gzip-JSONL |
Containerfile |
Image fuer Bebop |
lagebild-ingest.container, lagebild.network |
Quadlet-Units, rootless |
ingest.env.example |
Vorlage fuer die Zugangsdaten |
Bebop
# 1. Schema einspielen
psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -f schema.sql
# 2. Image bauen
podman build -t localhost/lagebild-ingest:latest .
# 3. Konfiguration ablegen
mkdir -p ~/.config/lagebild
cp ingest.env.example ~/.config/lagebild/ingest.env
cp sources.toml ~/.config/lagebild/sources.toml
chmod 600 ~/.config/lagebild/ingest.env
$EDITOR ~/.config/lagebild/ingest.env
# 4. Quadlet installieren
mkdir -p ~/.config/containers/systemd
cp lagebild-ingest.container lagebild.network ~/.config/containers/systemd/
systemctl --user daemon-reload
systemctl --user start lagebild-ingest
journalctl --user -u lagebild-ingest -f
# Damit der Dienst ohne offene Sitzung weiterlaeuft:
loginctl enable-linger "$USER"
sources.toml ist eingehaengt, nicht ins Image gebacken: eine neue Quelle ist
ein systemctl --user restart lagebild-ingest, kein Neubau.
Pi 5 — Schatten-Ingest
Ohne Postgres, ohne Container:
python3 poller.py --sink jsonl:/var/lib/lagebild/schatten
Legt <dir>/YYYYMMDD/YYYYMMDDHHMMSS.jsonl.gz an, dedupliziert ueber eine
SQLite daneben. Als systemd --user-Unit mit Restart=always einrichten.
Der Sinn ist nicht Redundanz um ihrer selbst willen: RSS-Feeds haben kein Archiv. Steht Bebops Poller einen Tag still, ist dieser Tag unwiederbringlich weg. Kodierungen lassen sich wiederholen, Rohdaten nie.
Betrieb
# Lizenzstatus im Register gegen die aktuelle robots.txt pruefen
python3 poller.py --check-robots # Exit != 0 bei Abweichung
# ein einzelner Durchlauf
python3 poller.py --sink "$DATABASE_URL" --once
--check-robots gehoert in einen woechentlichen Cron. Ein Verlag, der seine
robots.txt aendert, aendert damit seinen Nutzungsvorbehalt — und das ist der
Punkt, an dem eine Quelle stillgelegt werden muss.
Aendert sich etwas, wird sources.toml angepasst, nie der Code. Eine
gesperrte Quelle bleibt im Register stehen (aktiv = false), damit
nachvollziehbar bleibt, warum sie fehlt. Der Poller verweigert den Start,
wenn eine als gesperrt gefuehrte Quelle aktiv geschaltet ist.
Waechter
-- aktive Quellen, die seit ueber sechs Stunden nichts Neues liefern
select * from quellen_stillstand;
-- Fehler der letzten Stunde
select quelle, http_status, fehler, begonnen_am from poll_laeufe
where fehler is not null and begonnen_am > now() - interval '1 hour';
Arbeitsvorrat fuer Yantra
select * from unkodiert('qwen3-14b-q4/prompt-1') limit 500;
Liefert alle Items, die diese Kodierer-Version noch nicht gesehen hat. Eine neue Prompt-Version ist damit automatisch ein vollstaendiger Recode-Auftrag ueber die gesamte Historie, ohne dass ein Feed erneut abgerufen wird.
Verhalten
- 15-Minuten-Takt, an den Slotgrenzen ausgerichtet (+30 s Versatz), identisch zu GDELTs Paketgrenzen — damit bleiben die Slots vergleichbar.
- Bedingter GET ueber ETag/Last-Modified, im Register gespeichert. Im Test antworteten 4 von 12 Quellen im zweiten Durchlauf mit 304.
- Dedup ueber
unique (quelle, item_key);item_keyist guid, ersatzweise Link, ersatzweise ein Titel-Hash. - Fehlertoleranz: eine kaputte Quelle beendet den Durchlauf nicht, der
Fehler landet in
poll_laeufe. - Kein Volltext-Abruf. Nur der Feed selbst wird geholt. Titel und Teaser reichen als Kodierungsinput, und damit stellt sich die TDM-Frage nach § 44b UrhG gar nicht erst.
Gemessen (2026-09-04)
Erster Lauf ueber 12 aktive Quellen: 820 Items gesehen, 810 neu, gesamter Durchlauf unter 3 s. Zweiter Lauf unmittelbar danach: 1 neues Item.
Das Trigramm-Clustering findet quellenuebergreifende Dubletten sofort:
zeit | handelsblatt | 1.00 | Bekennerschreiben: Erneut Sabotage am Stromnetz
spiegel | derstandard | 0.92 | Niederlage fuer Donald Trump - Gericht in Missouri
Offen
- Telegram-Fetcher (Telethon/MTProto). Register ist vorbereitet, Eintraege
stehen auf
aktiv = false. Die Bot-API kann fremde Kanaele nicht lesen. - Ersatz-URL fuer den BR24-Feed (aktuell 404).
- Quellenpool von 12 auf ~40 erweitern; Regionalzeitungen ueber SearXNG auf Debby suchen.