import json import logging import re import os from collections import defaultdict import pickle import time import shutil from gematria import calculate_gematria # --- Konfiguration --- logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') BOOK_RANGE = range(1, 40) MAX_PHRASE_WORDS = 20 TEXTS_DIR = "texts/torah" CACHE_FILE = "tanakh_phrasedict.cache" OLD_INDICES_DIR = "indices_by_book" def clean_text(text): """Bereinigt den hebräischen Text.""" text = re.sub(r'\[.*?\]', '', text) text = re.sub(r"[^\u05D0-\u05EA\s]+", "", text) text = re.sub(r"\s+", " ", text).strip() return text def cleanup_old_files(): """Löscht alte, inkompatible Dateien und Verzeichnisse.""" if os.path.isdir(OLD_INDICES_DIR): logging.warning(f"Lösche altes Index-Verzeichnis: '{OLD_INDICES_DIR}'...") shutil.rmtree(OLD_INDICES_DIR) # Die alte Cache-Datei muss ebenfalls gelöscht werden, da sie das neue Format nicht hat if os.path.exists(CACHE_FILE): logging.warning(f"Lösche alte Cache-Datei für Re-Indizierung: '{CACHE_FILE}'...") os.remove(CACHE_FILE) def main(): """Erstellt ein globales Phrasen-Wörterbuch mit Wortanzahl und Frequenz.""" logging.info("Starte den globalen Index-Builder...") start_time = time.time() temp_phrases = [] phrase_frequencies = defaultdict(int) # --- Phase 1: Alle Phrasen sammeln und Frequenzen zählen --- logging.info("Phase 1: Sammle Phrasen und zähle Frequenzen...") for book_num in BOOK_RANGE: filepath = os.path.join(TEXTS_DIR, f"{book_num:02}.json") if not os.path.exists(filepath): continue logging.info(f" -> Verarbeite Buch {book_num:02}...") with open(filepath, 'r', encoding='utf-8') as f: data = json.load(f) for chap_idx, chapter in enumerate(data.get("text", []), start=1): for verse_idx, verse_text in enumerate(chapter, start=1): words = clean_text(verse_text).split() if not words: continue for length in range(1, min(len(words), MAX_PHRASE_WORDS) + 1): for start in range(len(words) - length + 1): phrase_words = words[start:start+length] phrase_text = " ".join(phrase_words) gematria_val = calculate_gematria("".join(phrase_words)) if gematria_val > 0: source_ref = f"B{book_num:02d},K{chap_idx:02d},V{verse_idx:02d}" # Speichere alle relevanten Daten temporär temp_phrases.append({ "gematria": gematria_val, "text": phrase_text, "source": source_ref, "words": length }) # Zähle die Häufigkeit jeder einzigartigen Phrase phrase_frequencies[phrase_text] += 1 logging.info(f"Phase 1 abgeschlossen. {len(temp_phrases):,} Phrasen-Instanzen gefunden.") # --- Phase 2: Finales Wörterbuch mit Frequenzdaten erstellen --- logging.info("Phase 2: Erstelle finales Phrasen-Wörterbuch...") final_phrase_dict = defaultdict(list) # Set, um Duplikate (gleiche Phrase, gleiche Gematria) zu vermeiden seen_phrases = set() for phrase in temp_phrases: # Einzigartiger Schlüssel, um zu verhindern, dass die gleiche Phrase mehrfach pro Gematria-Wert gespeichert wird phrase_key = (phrase['gematria'], phrase['text']) if phrase_key in seen_phrases: continue seen_phrases.add(phrase_key) final_phrase_dict[phrase['gematria']].append({ "text": phrase['text'], # Wichtig: Wir speichern jetzt auch Wortanzahl und Frequenz! "words": phrase['words'], "freq": phrase_frequencies[phrase['text']], "source": phrase['source'] # Quelle der ersten Begegnung }) logging.info("Phase 2 abgeschlossen.") # --- Phase 3: Speichern --- logging.info(f"Phase 3: Speichere das Phrasen-Wörterbuch in Cache-Datei: {CACHE_FILE}") with open(CACHE_FILE, 'wb') as f: pickle.dump(dict(final_phrase_dict), f) end_time = time.time() logging.info(f"\nIndizierung erfolgreich abgeschlossen. Gesamtdauer: {(end_time - start_time):.2f} Sekunden.") if __name__ == "__main__": cleanup_old_files() main()