No description
  • Python 99.5%
  • Shell 0.4%
  • Dockerfile 0.1%
Find a file
rene 3a6ecbc7b8 auswerten: Rueckschau auf den Eingangsordner
mealie-import auswerten [/Volumes/rezeptimport] [--seit JJJJ-MM-TT] [-o datei]
stellt je Rezept den Stand beim Import (Datei im Auftragsordner, ueber
mealie_objekt wie beim Hochladen abgebildet) neben den heutigen in Mealie:
noch im Posteingang, durchgesehen mit oder ohne Aenderungen, geloescht;
dazu die auffaelligen Berichtszeilen. Ersetzte Laeufe desselben Fotos
werden nur genannt. Die Aenderungen beim Durchsehen sind die Rueckmeldung,
an der sich der lokale Leser verbessern laesst. Am echten Bestand vom
2026-10-13 geprueft: zeigt die Handkorrekturen an fuenf Rezepten richtig.

Claude-Session: https://claude.ai/code/session_01TjsuBxX38MCCCm38iBHNP7
2026-10-13 19:56:24 +02:00
beispiele/erotik-food-kochkurs mealie-import 0.1: Rezept-Markdown, pruefen, hochladen mit Nachmessen, url, bild, zip 2026-10-11 21:16:05 +02:00
deploy eingang: sauber herunterfahren - laufender Auftrag wird bei SIGTERM fertig 2026-10-12 20:04:05 +02:00
src/mealie_import auswerten: Rueckschau auf den Eingangsordner 2026-10-13 19:56:24 +02:00
tests auswerten: Rueckschau auf den Eingangsordner 2026-10-13 19:56:24 +02:00
.dockerignore eingang: Eingangsordner mit Claude (Opus 5.5) lesen, Foto zuschneiden, hochladen 2026-10-11 21:47:36 +02:00
.gitignore mealie-import 0.1: Rezept-Markdown, pruefen, hochladen mit Nachmessen, url, bild, zip 2026-10-11 21:16:05 +02:00
Dockerfile eingang: Eingangsordner mit Claude (Opus 5.5) lesen, Foto zuschneiden, hochladen 2026-10-11 21:47:36 +02:00
pyproject.toml eingang: lokaler Leser (Qwen in LM Studio) als Standard, Claude waehlbar 2026-10-12 16:44:44 +02:00
README.md auswerten: Rueckschau auf den Eingangsordner 2026-10-13 19:56:24 +02:00
uv.lock eingang: lokaler Leser (Qwen in LM Studio) als Standard, Claude waehlbar 2026-10-12 16:44:44 +02:00

mealie-import

Rezepte aus Webseiten, Fotos, Scans und ganzen Rezeptmappen redigiert nach Mealie bringen. Mit Abschnitten, Tags, Kategorien, Notizen und Bild. Nach dem Hochladen wird zurückgelesen, ob alles angekommen ist.

Entstanden am 2026-10-11 aus der Rezeptmappe eines Kochkurses (PDF, 4 Gänge, 9 Teilrezepte). Nachgemessen gegen Mealie 3.28.0.

Warum, wenn Mealie selbst importieren kann

Mealie hat einen URL-Import und einen KI-Import. Der KI-Import kann aber nur ein Rezept je Vorgang. Sein Prompt sagt wörtlich: „Assume everything you receive describes exactly one recipe.“ Er liest keine PDFs, schneidet das Foto nicht zu und kennt keine Menüs. Auf mealie.motocamp.de ist er außerdem nicht eingerichtet (Stand 2026-10-11: kein KI-Anbieter).

Dieses Werkzeug deckt den Rest ab:

  • Dokumente mit mehreren Rezepten, Menüs (ein Rezept je Gang, Teilrezepte als Abschnitte)
  • eine Durchsicht vor dem Hochladen: Das Rezept liegt als lesbares Markdown vor, Abweichungen von der Vorlage stehen als Notiz im Rezept
  • vorhandene Tags und Kategorien vorab abgleichen, Tippfehler fangen
  • aktualisieren statt Dubletten anlegen
  • Nachmessen nach jedem Upload

Das Lesen und Redigieren übernimmt Claude Code (Skill rezept-extraktor-fuer-mealie). Das Werkzeug erledigt den mechanischen Teil und ruft selbst kein Sprachmodell auf.

Einrichten

uv sync
mkdir -p ~/.config/mealie-import && chmod 700 ~/.config/mealie-import
cat > ~/.config/mealie-import/config.toml <<'EOF'
url = "https://mealie.motocamp.de"
token = "…"   # Mealie → Profil → API-Tokens
EOF
chmod 600 ~/.config/mealie-import/config.toml

MEALIE_URL und MEALIE_TOKEN in der Umgebung haben Vorrang vor der Datei.

Befehle

Befehl Was er tut
organizer vorhandene Kategorien, Tags, Werkzeuge anzeigen
pruefen DATEIEN|ORDNER Form, Typografie, Bilder, Dubletten; mit Mealie: was neu angelegt würde, was schon existiert. --offline ohne Mealie
hochladen DATEIEN|ORDNER zeigt den Plan (Probelauf); mit --ja anlegen bzw. aktualisieren, danach nachmessen
url URL [-o ORDNER] Entwurf aus einer Webseite, mit Bild
bild FOTO --raster 100 Vorschau mit Koordinatengitter zum Ausmessen
bild FOTO --box x,y,b,h zuschneiden, aufrichten, auf 1600 px verkleinern, JPEG
zip DATEIEN -o X.zip Export für die Nextcloud-Migration in der Oberfläche, ohne Token

Aufruf mit uv run mealie-import ….

Eingangsordner (Dauerdienst auf der DS)

mealie-import eingang ORDNER beobachtet einen Ordner wie den Consume-Ordner von Paperless. Auf der DS ist das /volume1/rezeptimport, eingebunden als Container mealie-import (siehe deploy/). Ein Auftrag ist eine Datei oder ein Unterordner: Foto, Scan, HEIC vom iPhone, PDF, Link-Datei (.webloc, .url, .txt).

Ablauf je Auftrag:

  1. Warten, bis die Datei fertig hochgeladen ist (60 s ohne Änderung).
  2. Das Original vor dem Modellaufruf nach .in-arbeit/ holen. So gibt es nach einem Absturz keinen zweiten Lauf.
  3. Das Modell lesen lassen, Rezept-Markdown und Foto-Box kommen als strukturierte Ausgabe zurück.
  4. Prüfen, hochladen, nachmessen. Jedes Rezept bekommt den Tag „Posteingang“: in Mealie durchsehen, dann den Tag entfernen.
  5. Den Auftrag nach erledigt/ oder fehler/ legen, jeweils mit bericht.txt. Die Kosten stehen in kosten.csv.

Leser: lokal (Standard) oder Claude

lokal: qwen3.6-35b-a3b-mlx in LM Studio (M1 Max) claude: Opus 5.5
Foto-Zuschnitt, IoU gegen Sollposition 0,86–0,99 (Koordinaten 0–1000) 1,00 (Pixel)
PDF, 2 Seiten der Kochkurs-Mappe nach den Sicherungen 28/28 Zutatenzeilen; teilt in 2 Rezepte 1 Rezept mit Abschnitten
Dauer Foto ca. 1,5 min, PDF 3,5–5 min 20–40 s
Kosten 0 0,07–0,12 $ je Auftrag
verfügbar nur, wenn der Mac läuft (sonst warten die Aufträge) immer

Gemessen am 2026-10-11/12 mit tests/integration/eingang_echt.py.

Einstellungen:

  • MEALIE_IMPORT_LESER=lokal|claude wählt den Leser.
  • MEALIE_IMPORT_PDF_LESER=claude schickt nur PDFs an Claude.
  • LOKAL_URL und LOKAL_MODELL legen Server und Modell fest.
  • LM_API_KEY ist der Schlüssel für LM Studio; am Mac wird er aus ~/.hermes/.env gelesen.

Was der lokale Leser falsch machte und wie es abgefangen wird. Jeder Punkt ist in mindestens einem Lauf vorgekommen:

beobachtet Gegenmaßnahme
erfundene Zeiten, Portionen, Ausbeuten und Menüs, sogar die Beispielwerte der Formatvorlage wörtlich Er sieht nur kategorien:. Alle anderen Kopfzeilen werden verworfen und im Bericht genannt. Angaben aus der Vorlage schreibt er wörtlich in die Beschreibung.
neue Kategorien („Pasta“ neben „Nudelgerichte“) Nur vorhandene Kategorien kommen durch.
Personen-Tag „René“ ohne Beleg Er setzt keine Tags.
## Teig statt ### Teig Überschriften werden repariert.
Flammkuchen-Teil eines PDFs ganz weggelassen, ohne Meldung Vollständigkeitsprüfung gegen die Textebene: Fehlen mehr als 10 % der Zutatenzeilen, wird nicht hochgeladen.
Selbstauskunft behauptet Dinge, die nicht im Ergebnis stehen Der Hinweis heißt im Bericht „ungeprüft“.
Umlaute in Umschrift („Pilzfueellung“), weil der Systemtext so geschrieben war Der Systemtext steht in richtigem Deutsch.
strukturierte Ausgabe landet in reasoning_content statt content Beide Felder werden gelesen.
Schritte umgestellt („in den Ofen“ vor dem Kneten) und Absätze am Ende weggelassen, ohne Meldung (Roggen-Dinkel-Mischbrot) Erst wörtliche Abschrift der Seite, dann das Rezept (Feld abschrift vorn im Schema). abgleich.py vergleicht über Wortpaare: Schritte zurück in die Reihenfolge der Vorlage, fehlender Text als Schritt angehängt oder als Notiz. Bei PDFs dient die Textebene als Abschrift.
Foto nicht gemeldet (Mischbrot) oder mit falscher Box; auf einer Seite mit vier Rezepten und vier Fotos eines gemeldet, links bei 0 statt 147 ‰ Fotos kommen beim lokalen Leser nur aus einer kleinen zweiten Anfrage, je Rezept. Die große ist Rückfall, falls die kleine scheitert.
in dieser Nachfrage vier richtige Boxen, aber foto_bild: -1 („keines“); mit Bildern ab 1 hielt er die Zahl für die Buchseite Eigenes Feld hat_foto; bei nur einem Bild gilt immer dieses. Fünf Seiten in sieben Läufen richtig, auch die beiden ohne Gericht-Foto.
Zutatenzeilen des Nachbarrezepts als Schritt angehängt (Nudelseite) Der Abgleich hängt nur Fließtext an. Buchsatz wird vorher zerlegt: Trennstriche, umbrochene Zeilen, „·“ zwischen Zutaten.
Variationen übersprungen, ihr Text als elf Schritte ans Hauptrezept gehängt (Rouladen) Mehr als zwei fehlende Absätze je Rezept gehen als Notiz ein, mit dem Hinweis auf übersprungene Rezepte. Im Systemtext: Variationen mit eigenen Zutaten sind eigene Rezepte.
Zitat-Tipp beim falschen Rezept (Wurzelpüree-Tipp unter Selleriepüree) Ein Tipp geht an das Rezept, dessen Name darin steht.
Beschreibung wiederholt die Schritte Sätze, die fast wörtlich in den Schritten stehen, fliegen aus der Beschreibung.
„Für 4 Personen“ bei allen vier Nudelrezepten weggelassen, Zubereitungszeit und Kalorien behalten; „4 Personen“ als Kopfzeile Portionen: geschrieben, die verworfen wird Eine Portionsangabe der Abschrift („Für 4 Personen“, „Zutaten für 4 Personen“, „4 Personen“), die vor den Schritten eines Rezepts steht und ihm fehlt, kommt an den Anfang seiner Beschreibung.
Zutatenliste des Buchs in einer Zeile mit Kommas galt als „nicht zugeordnet“ Die Zutaten eines Abschnitts zählen für den Abgleich auch am Stück.
Zutaten in erfundene Abschnitte gegliedert („Nudeln und Gemüse“, „Garnitur“) Steht keiner der Titel als Zeile in der Abschrift, werden die Abschnitte zusammengelegt.
ein Rezept der Seite ausgelassen (Pichelsteiner Eintopf neben dem Wurstsalat; die vier Füllungen neben den Rouladen), der Abgleich hängte dessen Text als Schritte an Nennt die Abschrift mehr Rezeptköpfe („Für 4 Personen“, „Zutaten für 4 Personen“, „4 Personen“) als Rezepte geliefert sind, fragt das Werkzeug mit denselben Bildern nach den fehlenden (Rezept-Nachfrage, ca. 1 min). Text hinter einem weiteren Rezeptkopf wird nie als Schritt angehängt, sondern als Notiz mit Warnung. Die Zählregel schlägt an neun echten Seiten genau bei den zwei mit ausgelassenem Rezept an.
Zutaten mit „|“ statt „·“ gereiht; ### Abschnitt und ### Schritt 1 als Titel (aus der Formatvorlage bzw. erfunden) „|“ trennt wie „·“. Ein einzelner Abschnitt verliert einen Titel, der nicht in der Vorlage steht; mehrere werden zusammengelegt.
Tipp-Kasten mal als Notiz, mal als Schritt („PROFI-TIPP: …“) Ein Schritt, der mit „Tipp:“ oder „PROFI-TIPP:“ beginnt, wird Notiz „Tipp“.
gerade Anführungszeichen (Kochbuch "Suppen und Schmankerl") Paare in einer Zeile werden „…“.
erfundene Beschreibungen („Ein klassischer bayerischer Wurstsalat mit …“) Ein Satz fällt weg, wenn weniger als 20 % seiner Wortpaare in der Abschrift stehen – nur, wenn die Abschrift mindestens 70 % der Schritte des Rezepts enthält (in einer Abschrift fehlte ein Rezept ganz). Gemessen: erfundene 0,00/0,12, echte 0,94–1,00.
„Zutaten für 4 Personen“ als Abschnittstitel Ein Zutaten-Titel, der nur eine Portionsangabe ist, wird Beschreibung.
Kategorien: groß geschrieben, still verloren Kopfzeilen werden ohne Rücksicht auf Groß- und Kleinschreibung gelesen.
Lesefehler in Mengen („1 Msp.“ statt „1 TL“ in kursiver Kleinschrift) Nicht abgefangen: Der Fehler steht schon in der Abschrift. Beim Durchsehen die Mengen gegen das Buch lesen. Messungen dazu unten.

Lesefehler in kleiner Schrift: was gemessen ist (IMG_1914, Fleischpflanzerl-Zutaten, 2026-10-12). Je eine Probe, wenn nicht anders angegeben:

gesendet Aufgabe Ergebnis Dauer
ganze Doppelseite, 2212×1659 (heute) Hauptanfrage falsch (2 von 2 Läufen) ca. 3 min
ganze Doppelseite, 2212×1659 / 3200×2400 / 4032×3024 nur diesen Abschnitt abschreiben falsch, je eine Zeile fehlt 128 / 77 / 109 s
Halbseite, 1568×2334 nur diesen Abschnitt abschreiben richtig (2 von 2) 60–77 s
zwei überlappende Hälften (je 60 %) Hauptanfrage falsch, keine doppelten Rezepte 558 s
Halbseite, 1568×2334 ganze Halbseite abschreiben richtig 329 s

Größere Bilder ändern nichts. Das Bild wird vor dem Modell offenbar auf eine feste Größe gebracht, die genaue Grenze ist nicht gemessen. Hälften helfen nur, wenn das Modell sonst nichts zu tun hat. Ein zweistufiger Ablauf (je Hälfte nur abschreiben, dann aus der Abschrift gliedern) läge hochgerechnet bei 12–15 min je Doppelseite und ist nicht gebaut. | Kategorie „Brot“, vorhanden ist nur „Brot & Backwaren“ | Eindeutig passende vorhandene Kategorie wird übernommen (Teilwort oder sehr ähnlich), sonst verworfen. |

Ein zweiter Lauf desselben Fotos (Datei aus fehler/ oder erledigt/ zurück in den Eingang) ersetzt ein gleichnamiges Rezept, wenn es noch den Tag „Posteingang“ trägt und aus demselben Foto stammt (Prüfsumme in den extras), auch unter „Titel (2)“. In jedem anderen Fall wird nichts überschrieben, das neue Rezept heißt dann „Titel (2)“: ein durchgesehenes Rezept (Tag entfernt) bleibt so geschützt, und ein gleichnamiges Rezept aus einem anderen Buch geht nicht verloren. Ändert sich beim zweiten Lauf der Titel, entsteht ein neues Rezept, und das alte muss von Hand gelöscht werden.

Rückschau: mealie-import auswerten [/Volumes/rezeptimport] [--seit JJJJ-MM-TT] [-o datei.md] liest alle Aufträge in erledigt/ und fehler/ und stellt je Rezept den Stand beim Import (die Datei im Auftragsordner) neben den heutigen in Mealie: noch im Posteingang, durchgesehen mit oder ohne Änderungen, gelöscht. Die Änderungen beim Durchsehen sind die Rückmeldung, an der sich der Leser verbessern lässt. Dazu die auffälligen Berichtszeilen (Abgleich, Nachfragen, Reparaturen). Ersetzte Läufe desselben Fotos werden nur genannt.

Bei beiden Lesern gilt: Systemschlüssel (mealie:, bild:, quelle:) aus der Modellantwort werden immer entfernt. Ein erfundenes mealie: würde sonst ein bestehendes Rezept überschreiben.

Rezeptformat

Eine Markdown-Datei je Rezept. Ein Menü ist ein Ordner: Rezepte mit demselben menue: im selben Ordner bilden es, gang: legt die Reihenfolge fest. Beispiel: beispiele/erotik-food-kochkurs/.

# Titel

kategorien: Vorspeisen, Suppen
tags: Martina, René
portionen: 4
ergibt: 12 Taler
vorbereitung: 20 Minuten
kochzeit: 1 Std. 5 Min.
gesamtzeit: 1 Stunde 25 Minuten
quelle: https://…
bild: titel.jpg
menue: Erotik Food Kochkurs
gang: 1
mealie: titel-slug

Beschreibung als freier Text, auch mehrere Absätze.

## Zutaten

### Abschnitt
- 2 Zwiebeln

## Zubereitung

### Abschnitt
1. Zwiebeln würfeln.
   Fortsetzungszeilen gehören zum Schritt davor.

## Notizen

### Quelle
Freier Text.

Alle Kopfzeilen sind optional. Was das Werkzeug daraus macht:

  • menue: wird automatisch zum Tag. Jedes Rezept des Menüs bekommt eine Notiz „Menüfolge“, gebaut aus allen Dateien des Ordners.
  • mealie: schreibt das Werkzeug nach dem ersten Hochladen selbst in die Datei. Ist der Schlüssel gesetzt, aktualisiert der nächste Upload dieses Rezept. Die Datei ist dann die Quelle der Wahrheit: Was in Mealie von Hand an Titel, Zutaten, Schritten, Notizen, Tags oder Kategorien geändert wurde, wird überschrieben. Bewertung, Kommentare und Werkzeuge bleiben.
  • portionen: ist die Zahl, nach der Mealie skaliert. ergibt: ist eine Ausbeute wie „12 Taler“. Ein Bereich wie „10-12 Taler“ bleibt Text.
  • Zeiten sind Freitext und gehen so nach Mealie.
  • Unicode-Brüche in Zutaten (½) werden zu 1/2, damit Mealies Zutaten-Parser sie versteht.

pruefen warnt bei geraden Anführungszeichen (") und bei unpaarigen „ “.

Typische Abläufe

Foto oder Scan (mit Claude Code):

  1. Claude liest das Foto und schreibt das Rezept-Markdown.
  2. Das Gerichtfoto zuschneiden: bild foto.jpg --raster 100, die Box ablesen, dann bild foto.jpg --box x,y,b,h -o rezept.jpg. Das Ergebnis ansehen.
  3. pruefen, durchsehen, dann hochladen (Probelauf) und hochladen --ja.

PDF/Rezeptmappe: den Text mit pdftotext -layout, die Seiten mit pdftoppm -r 60 -png plus magick montage als Kontaktbogen zum Abgleich. Je Gang ein Markdown, alle in einen Ordner mit menue: und gang:.

Webseite: url URL -o arbeit/, den Entwurf durchsehen. Beschreibungen von Rezeptportalen sind oft Werbetext („Über 116 Bewertungen …“), Titel tragen den Autor („… von uevers“). Kategorien und Tags setzen, dann hochladen.

Wie Mealie die Daten ablegt (nachgemessen)

API (hochladen) ZIP (zip, Nextcloud-Migration)
Abschnitte bei Zutaten und Schritten ja ja
Zeiten wie geschrieben („20 Minuten“) englisch („20 minutes“); Freitext, der keine Dauer ist, geht verloren
Tag-Schreibweise wie geschrieben durch str.title(): „BBQ“ → „Bbq“
erneut hochladen aktualisiert Dublette
Bild ja ja (full.jpg im Rezeptordner)
Token nötig ja nein, Upload in der Oberfläche

Weitere Fallen des ZIP-Wegs, die der Export schon berücksichtigt:

  • keywords als String; eine Liste ergäbe keine Tags.
  • Zutaten alle als Dict, nie gemischt.
  • JSON mit ensure_ascii, weil Mealie die Datei ohne encoding= öffnet.

Beim URL-Entwurf liest Mealies Scraper das Rezept (/api/recipes/test-scrape-url, speichert nichts). Das Werkzeug liest die Seite zusätzlich selbst, denn manche Seiten (Chefkoch) verweisen für Bild und Autor nur per @id auf andere Teile des JSON-LD. Als Rückfallebene dient og:image.

Tests

uv run --extra eingang pytest                      # Format, Prüfungen, ZIP, Entwurf, Eingang
uv run python tests/integration/lokales_mealie.py  # gegen ein echtes Mealie, lokal
uv run --extra eingang python tests/integration/eingang_echt.py   # Eingang mit lokalem Leser
uv run --extra eingang python tests/integration/eingang_echt.py --leser claude --ja-kostet

Der Integrationstest installiert die Mealie-Version aus GEPRUEFT_GEGEN (nur Backend, Python 3.14) nach ~/.cache/mealie-import/ und startet sie mit leerer Datenbank. Dann spielt er durch: anlegen (Bild, Zeiten, Ausbeute), aktualisieren ohne Dublette, Probelauf ohne Änderung und den ZIP-Weg. Mit --url URL kommt der Webseiten-Entwurf dazu. Stand 2026-10-11: 21/21 bestanden.

Nach einem Mealie-Update auf dem Server: --version X.Y.Z laufen lassen und bei Erfolg GEPRUEFT_GEGEN in src/mealie_import/mealie.py nachziehen. hochladen warnt, solange die Versionen nicht übereinstimmen. Die lokale Installation meldet sich als develop, das ist harmlos.

Beispiel

beispiele/erotik-food-kochkurs/ enthält die Rezepte aus der Rezeptmappe der Kochschule KreativKochen (Regina Martensen, Otterfing). Sie liegen hier nur als privates Testmaterial. Vor einer Veröffentlichung des Repos gehören sie durch eigene Rezepte ersetzt.