Betrieb: flugscanner-mu disabled, Scraping nur Asia (instabile DE-Anbindung)

This commit is contained in:
Orbitalo 2026-03-25 11:07:36 +00:00
parent b1aaaa9d57
commit 427d5ee03d

327
STATE.md
View file

@ -1,5 +1,5 @@
# STATE: Flugpreisscanner
**Stand: 26.02.2026**
**Stand: 21.03.2026**
---
@ -12,9 +12,8 @@
| flugscanner-hub | ✅ Läuft (Docker: web + scheduler) |
| flugscanner-asia | ✅ Läuft (Docker: agent + noVNC) |
| flugscanner-mu | ✅ Läuft (Docker: agent + noVNC) |
| Forgejo-Repo | ✅ http://100.89.246.60:3000/orbitalo/flugpreisscanner |
| Dashboard | ✅ http://100.92.161.97:8080 |
| Telegram Bot | ✅ @CX_HKG_Alert_bot — Alerts + /preis + /best + /status |
| Telegram Bot | ✅ @CX_HKG_Alert_bot |
---
@ -24,205 +23,152 @@ Täglich günstigste Flüge **FRA → KTI (Frankfurt → Phnom Penh)** automatis
Kabine: **Economy** · Gepäck: 1 Koffer + Handgepäck · Aufenthalt: ~2 Monate
Fokus: **Cathay Pacific (CX) via Hong Kong** — beste Preis-Leistung in Economy.
KI wertet aus: jetzt buchen oder warten?
Scraping läuft bewusst von Heimnetz-IPs — nicht von Hetzner (Datacenter-IPs werden geblockt).
**Route: 🇭🇰 HKG Stopover** — Multi-City FRA→HKG (12 Nächte) → KTI → FRA.
Realistischer Preis: **9001.050 EUR** Roundtrip Economy.
---
## Container
## Container & Zugänge
| CT | Name | Server | LAN-IP | Tailscale-IP | Aufgabe |
|----|------|--------|--------|--------------|---------|
| 115 | `flugscanner-hub` | pve-hetzner | 10.10.10.115 | 100.92.161.97 | Gehirn: Dashboard + Scheduler + KI-Auswertung (OpenRouter) + DB + Job-Koordination |
| 115 | `flugscanner-asia` | pve1 Kambodscha | 192.168.0.131 | 100.112.190.22 | Scraping-Node A: SeleniumBase CDP + noVNC, Heimnetz-IP Asien |
| 145 | `flugscanner-mu` | helmut-pve Muldenstein | 192.168.178.130 | 100.75.182.15 | Scraping-Node B: SeleniumBase CDP + noVNC, Heimnetz-IP Deutschland |
**Zugänge:**
- Hub (pve-hetzner): `ssh root@100.88.230.59` PW: Astral-Proxmox!2026 → `pct exec 115`
- Asia (pve1): `ssh root@192.168.0.197` PW: astral66 → `pct exec 115`
- Muldenstein: `ssh root@100.75.182.15` PW: astral66 (direkt, kein pct nötig)
- helmut-pve: `ssh root@100.87.235.11` PW: astral66
| CT | Name | Server | Tailscale-IP | Zugang |
|----|------|--------|--------------|--------|
| 115 | `flugscanner-hub` | pve-hetzner | 100.92.161.97 | `ssh root@100.88.230.59` PW: Astral-Proxmox!2026 → `pct exec 115` |
| 115 | `flugscanner-asia` | pve-ka-1 (Kambodscha) | 100.112.190.22 | `sshpass -p astral66 ssh root@100.122.56.60``pct exec 115` |
| 145 | `flugscanner-mu` | helmut-pve (Muldenstein) | 100.75.182.15 | `sshpass -p astral66 ssh root@100.75.182.15` (direkt) |
**Wichtig:**
- Scraping läuft NIE von CT 115 / Hetzner aus
- CT 115 koordiniert nur — die Nodes führen aus
- Muldenstein = deutsche IP (beste Ergebnisse für Kayak, Momondo)
- Kambodscha = asiatische IP (Momondo/Traveloka werden übersprungen — Geo-Block)
- **Tailscale auf allen Containern** — sichere Kommunikation über Tailnet
- Kambodscha-Node überspringt Momondo/Traveloka (Geo-Block)
- Muldenstein = deutsche IP (beste KAYAK/Momondo-Ergebnisse)
---
## CT 115 — Flugpreisscanner Hub
**Nur Koordination, Auswertung, Dashboard — KEIN Scraping, KEIN noVNC hier.**
### Dienste (Docker)
| Service | Container | Port | Aufgabe |
|---------|-----------|------|---------|
| web | `flugscanner-web` | 8080 | Flask Dashboard |
| scheduler | `flugscanner-scheduler` | — | Jobs verteilen, KI auslösen, Telegram Bot |
### Pfade
## Pfade Hub (CT 115, pve-hetzner)
```
/opt/flugscanner/
├── hub/
│ ├── docker-compose.yml
│ ├── .env
│ ├── Dockerfile
│ ├── data/
│ │ └── flugscanner.db ← SQLite Datenbank
│ └── src/
│ ├── web.py ← Flask Dashboard + API
│ ├── scheduler.py ← Job-Koordination + Telegram Bot
│ ├── ki.py ← OpenRouter Auswertung + Plausibilität
│ ├── db.py ← DB-Zugriff + Init
│ └── requirements.txt
└── node/ ← (auf Nodes ausgecheckt)
```
---
## Scraping-Nodes (asia + mu)
### Dienste (Docker)
| Service | Container | Port | Aufgabe |
|---------|-----------|------|---------|
| agent | `flugscanner-agent` | 5010 | Jobs empfangen, Selenium starten |
| novnc | `flugscanner-novnc` | 6080 | Chrome live im Browser sehen |
### Pfade
```
/opt/flugscanner/node/
/opt/flugscanner/hub/
├── docker-compose.yml
├── .env ← NODE_NAME=flugscanner-asia/mu
├── Dockerfile
├── .env ← OPENROUTER_API_KEY, TELEGRAM_BOT_TOKEN
├── data/
│ └── flugscanner.db ← SQLite Datenbank
└── src/
├── agent.py ← Flask API (POST /job, GET /status)
├── worker.py ← SeleniumBase CDP Scraper
└── requirements.txt
├── web.py ← Flask Dashboard + API
├── scheduler.py ← Job-Koordination + Vision-KI + Telegram Bot
├── ki.py ← OpenRouter KI-Plausibilität
└── db.py ← DB-Zugriff + Init
```
### Kommunikation
## Pfade Nodes (asia + mu)
```
Hub Scheduler → POST http://[Node-Tailscale-IP]:5010/job
{ "scanner": "kayak_multicity", "von": "FRA", "nach": "KTI", "kabine": "economy", ... }
Node antwortet:
{ "results": [...], "node": "flugscanner-mu", "count": 10, "screenshot_b64": "..." }
/opt/flugscanner/node/src/
├── worker.py ← SeleniumBase CDP Scraper (alle Scanner)
└── agent.py ← Flask API (POST /job, GET /status)
```
---
## Scanner
| Scanner | Status | Anmerkung |
|---------|--------|-----------|
| Kayak (Roundtrip) | ✅ Aktiv | Beste Datenquelle, GDPR-Consent automatisiert |
| **Kayak Multi-City CX via HKG** | ✅ Aktiv | Primärer Scanner — FRA→HKG→KTI→FRA |
| Trip.com | ✅ Aktiv | Gute Ergänzung, auch CX-Filter |
| Momondo | ✅ Aktiv | Nur auf Muldenstein (Geo-Block aus Asien) |
| Google Flights | ⚠ Eingeschränkt | Wenige Ergebnisse, Consent-Probleme |
| Traveloka | ⚠ Nur Muldenstein | Geo-Block aus Asien |
| Wego | ❌ Deaktiviert | |
| Skyscanner | ❌ Deaktiviert | Bot-Detection |
### Node-spezifische Einschränkungen
Momondo und Traveloka werden auf `flugscanner-asia` automatisch übersprungen (Geo-Block).
Konfiguration: `NODE_SCANNER_SKIP` in scheduler.py.
| Scanner | Status | Nodes | Anmerkung |
|---------|--------|-------|-----------|
| Kayak Roundtrip | ✅ Aktiv | beide | Beste Datenquelle |
| Kayak Multi-City CX via HKG | ✅ Aktiv | beide | FRA→HKG→KTI→FRA |
| Trip.com | ✅ Aktiv | beide | flightType=RT fix 21.03.2026 |
| Momondo | ✅ Aktiv | nur mu | Geo-Block aus Asien |
| Traveloka | ⚠ Nur mu | nur mu | Geo-Block aus Asien |
| Google Flights | ⚠ Eingeschränkt | beide | Consent-Probleme |
| Wego | ❌ Deaktiviert | — | |
| Skyscanner | ❌ Deaktiviert | — | Bot-Detection |
---
## Anti-Bot-Strategie
## KI-Pipeline
- Scan-Intervall: zufällig **2545 Minuten** (nicht regelmäßig)
- SeleniumBase **UC/CDP Mode** (undetected Chromium)
- GDPR-Consent automatisch wegklicken (Kayak, Momondo)
- **Zwei verschiedene Geo-Locations** (Kambodscha + Deutschland)
- Scrape-URL (.de) getrennt von Booking-URL (.com) — Nutzer sieht internationale Preise
### 1. KI-Augen (OpenRouter gpt-4o-mini)
Screenshot-Analyse nach jedem Scan: PRICES_FOUND / COOKIE_BANNER / CAPTCHA / ERROR_PAGE
### 2. Kabinenklassen-Erkennung (OpenRouter gpt-4o-mini)
Vision klassifiziert Economy / Economy Light / Premium Economy / Business
### 3. Vision-Preis-Lokal (Ollama qwen3-vl:32b — kostenlos)
Nach jedem Scan: liest günstigsten **Roundtrip**-Preis aus Screenshot.
- Abweichung ≤15% → `ki_verified=1`, `ki_preis_visual` gesetzt
- Abweichung >15% → Original `plausibel=0`, neuer Eintrag `scanner=*_ki` mit KI-Preis
### 4. KI-Plausibilität (OpenRouter gpt-4o-mini)
Batch-Prüfung aller neuen Preise gegen Erfahrungswerte.
### OpenRouter
| Variable | Wert |
|----------|------|
| OPENROUTER_API_KEY | sk-or-v1-3c3... (aktualisiert 21.03.2026) |
| AI_MODEL | openai/gpt-4o-mini |
---
## Datenbank — prices Tabelle (wichtige Felder)
| Feld | Bedeutung |
|------|-----------|
| preis | Scraper-Rohpreis |
| plausibel | 1=ok, 0=Artefakt/One-Way/unplausibel, NULL=ungeprüft |
| plausi_grund | Begründung |
| ki_preis_visual | Von Vision-KI (qwen3-vl) gelesener Preis |
| ki_verified | 1 = durch Vision-KI geprüft |
| ki_verified_at | Zeitstempel der Verifikation |
| preis_korrigiert | Preis + Gepäckzuschlag falls Economy Light |
---
## Preisreferenz (Stand 21.03.2026)
**FRA → KTI Roundtrip Economy, ~2 Monate Aufenthalt**
| Metrik | Wert |
|--------|------|
| Günstigster bestätigter Roundtrip | **870 EUR** (KAYAK, 01.03.2026) |
| Realistischer Schnitt | 9001.050 EUR |
| Obergrenze plausibel | 1.400 EUR |
| Unter 870 EUR | verdächtig (Artefakt oder One-Way) |
**Datenbasis (Stand 21.03.2026):**
- 2.107 plausible Preise gesamt
- 407 Sidebar-Artefakte bereinigt
- 252 Trip.com One-Way-Preise bereinigt
---
## Bekannte Bugs & Fixes
| Datum | Bug | Fix |
|-------|-----|-----|
| 21.03.2026 | Trip.com lieferte One-Way statt Roundtrip | `flightType=RT` in URL ergänzt |
| 21.03.2026 | KAYAK extrahierte Sidebar-Filterpreise | `_filter_sidebar_preise()` + Anker-Preis-Filter |
| 21.03.2026 | Momondo Opodo-Popup blockierte Screenshots | `_dismiss_comparison_popup()` |
| 21.03.2026 | Portainer logs als false positive in Loki | Loki-Filter erweitert |
| 21.03.2026 | OpenRouter API Key abgelaufen | Neuer Key in .env |
---
## Scan-Zeiten (Hub)
| Zeit | Was |
|------|-----|
| 06:30 / 12:30 / 18:30 | Standard-Scan (alle Jobs, alle Nodes) |
| 08:00 | Vorlauf-Scan (45/60/84 Tage vorab) |
| 07:30 | Morgenbericht Telegram |
| 20:00 | Tagesbilanz Telegram |
---
## Telegram Bot
**Bot:** @CX_HKG_Alert_bot
**Token:** `8693839370:AAEPG0t2gA5jkLFH3J8UmstZMkHPdp0aTG4`
**Chat-ID:** 674951792
**Bot:** @CX_HKG_Alert_bot · **Chat-ID:** 674951792
### Befehle
| Befehl | Funktion |
|--------|----------|
| /preis | Aktueller CX-Preis via HKG |
| /best | Top 3 günstigste heute |
| /status | Systemstatus (Nodes, letzte Scan-Zeit) |
### Automatische Nachrichten
| Wann | Was |
|------|-----|
| Täglich 07:00 | Morgenbericht mit Preisübersicht |
| Bei CX < 900 | Preis-Alert |
| Bei Anstieg > 50€ | Preisanstieg-Warnung |
| Nach 3x Null-Ergebnissen | Scanner-Problem-Alert (pro Node) |
---
## Datenbank (SQLite auf CT 115)
Pfad: `/opt/flugscanner/hub/data/flugscanner.db`
| Tabelle | Inhalt |
|---------|--------|
| jobs | Geplante Scraping-Jobs (Route, Anbieter, Intervall, Airline-Filter) |
| prices | Rohe Preisdaten (Preis, Datum, Anbieter, Node, Booking-URL, plausibel) |
| screenshots | Vision-AI Screenshots mit Kabinenklassen-Erkennung |
| analyses | KI-Auswertungen mit Timestamp |
| prompts | Editierbare KI-Prompts |
| nodes | Registrierte Scraping-Nodes + Status |
| logs | System-Logs |
---
## KI-Auswertung
- Läuft automatisch nach jedem Scraping-Durchlauf
- **Vision AI**: Screenshots werden per gpt-4o-mini klassifiziert (Economy/PE/Business)
- **Plausibilitätsprüfung**: Preise 70012.000€ für Economy Roundtrip
- **Marktanalyse**: Prompt editierbar im Dashboard
- OpenRouter Guthaben wird im Dashboard angezeigt
### OpenRouter
| Variable | Wert |
|----------|------|
| OPENROUTER_API_KEY | `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` |
| AI_MODEL | `openai/gpt-4o-mini` |
---
## Preiserwartung (Stand 26.02.2026)
**FRA → HKG → Phnom Penh → FRA — Cathay Pacific Economy Roundtrip**
| Metrik | Wert |
|--------|------|
| Günstigster | ~726 EUR |
| Realistischer Schnitt | **9001.050 EUR** |
| Gute Airlines (CX/SQ/TG) Durchschnitt | ~1.030 EUR |
| Zum Vergleich: Reisebüro VA PE | ~2.000 EUR |
---
## Repo
`git.orbitalo.net/orbitalo/flugpreisscanner`
API-Token (cursor-deploy-3): `a6dd1ee58e091c894169c5ae15f6b74bb9461c56`
| Alert | Auslöser |
|-------|----------|
| Preis-Alert | CX < 900 EUR |
| Preisanstieg | > 50 EUR Anstieg |
| Scanner-Problem | 3x Null-Ergebnisse in Folge |
---
@ -231,13 +177,38 @@ API-Token (cursor-deploy-3): `a6dd1ee58e091c894169c5ae15f6b74bb9461c56`
| Datum | Was |
|-------|-----|
| 25.02.2026 | System live geschaltet |
| 25.02.2026 | Cookie-Banner-Fix + Screenshot-Verbesserungen |
| 26.02.2026 | Umstellung PE → Economy, CX via HKG als Hauptroute |
| 26.02.2026 | Telegram Bot @CX_HKG_Alert_bot eingerichtet |
| 26.02.2026 | SeleniumBase 4.34 → 4.47 (CDP-Verbesserungen) |
| 26.02.2026 | _scrape_url / _booking_url Trennung (Scrape .de, Booking .com) |
| 26.02.2026 | GDPR-Consent-Handling für Kayak/Momondo |
| 26.02.2026 | NODE_SCANNER_SKIP: Momondo/Traveloka auf Asia deaktiviert |
| 26.02.2026 | Alert-Zähler jetzt pro Node (kein Spam durch Geo-Blocks) |
| 26.02.2026 | SSH-Fix Muldenstein (PermitRootLogin yes) |
| 26.02.2026 | Doku in CT999 ergänzt (ct-145-flugscanner-mu.md + index.md) |
| 26.02.2026 | Umstellung PE → Economy, CX via HKG Hauptroute |
| 26.02.2026 | Telegram Bot eingerichtet, Doku CT999 |
| 21.03.2026 | OpenRouter API Key erneuert |
| 21.03.2026 | Trip.com One-Way Bug gefixt (flightType=RT) |
| 21.03.2026 | KAYAK Sidebar-Preis-Filter implementiert |
| 21.03.2026 | Momondo Popup-Dismisser implementiert |
| 21.03.2026 | Vision-KI Pipeline (qwen3-vl:32b lokal) eingebaut |
| 21.03.2026 | DB: ki_preis_visual + ki_verified Spalten |
| 21.03.2026 | Web-UI: KI-Verified Badge (grün/blau) |
| 21.03.2026 | 407 Sidebar + 252 One-Way Preise bereinigt |
| 21.03.2026 | Doku flugscanner-asia Zugang (via pve-ka-1) |
---
## Betrieb nur Kambodscha-Node (25.03.2026)
**Hintergrund:** Instabile Internetanbindung zum Scraping-Node in Deutschland (Muldenstein).
**Aenderung:** In `hub/data/flugscanner.db` → Tabelle `nodes`: **`flugscanner-mu`** auf `status='disabled'` gesetzt.
Alle aktiven Scans laufen nur noch ueber **`flugscanner-asia`** (CT 115 auf **pve-ka-1**, Tailscale **100.112.190.22**) — Kambodscha / Phnom-Penh-Region.
**Auswirkung:**
- **Momondo** und **Traveloka** werden nicht mehr ausgefuehrt (Geo-Block aus Asien; vorher nur sinnvoll ueber DE-IP).
- **KAYAK**, **Trip.com**, eingeschraenkt **Google Flights** bleiben auf dem Asia-Node aktiv.
**MU-Node wieder einschalten** (wenn Verbindung stabil):
```bash
cd /opt/flugscanner/hub && docker compose stop
sqlite3 data/flugscanner.db "UPDATE nodes SET status='online' WHERE name='flugscanner-mu';"
docker compose start
```
| Datum | Was |
|-------|-----|
| 25.03.2026 | flugscanner-mu disabled — Scraping nur noch Asia (Kambodscha) |