Source code for backend.services.parser_service

# Parser-Service: Liest Text aus verschiedenen Dateiformaten
# Unterstützt PDF, Word, PowerPoint, Excel, Bilder (OCR), Markdown und Text

import fitz  # PyMuPDF — Library zum PDF-Lesen
from docx import Document as DocxDocument  # python-docx — Library zum Word-Lesen
from pptx import Presentation  # python-pptx — Library zum PowerPoint-Lesen
from openpyxl import load_workbook  # openpyxl — Library zum Excel-Lesen
import pytesseract  # OCR — Text aus Bildern extrahieren
from PIL import Image  # Pillow — Bildverarbeitung
from pathlib import Path


# Unterstützte Dateiformate
SUPPORTED_FORMATS = {
    ".pdf", ".docx", ".txt", ".pptx", ".xlsx", ".md",
    ".png", ".jpg", ".jpeg"
}


[docs] def parse_file(file_path: str) -> str: """ Liest eine Datei und gibt den extrahierten Text zurück. Erkennt automatisch das Format anhand der Dateiendung. """ path = Path(file_path) suffix = path.suffix.lower() if suffix not in SUPPORTED_FORMATS: raise ValueError(f"Dateityp '{suffix}' wird nicht unterstützt. " f"Unterstützt: {', '.join(sorted(SUPPORTED_FORMATS))}") if suffix == ".pdf": return _parse_pdf(path) elif suffix == ".docx": return _parse_docx(path) elif suffix == ".pptx": return _parse_pptx(path) elif suffix == ".xlsx": return _parse_xlsx(path) elif suffix in (".png", ".jpg", ".jpeg"): return _parse_image(path) elif suffix == ".md": return _parse_markdown(path) elif suffix == ".txt": return _parse_txt(path)
def _parse_pdf(path: Path) -> str: """ Extrahiert Text aus einer PDF-Datei. Geht Seite für Seite durch und sammelt den Text. """ text = "" doc = fitz.open(str(path)) for page in doc: text += page.get_text() text += "\n\n" # Seitenumbruch als Trennung doc.close() return text.strip() def _parse_docx(path: Path) -> str: """ Extrahiert Text aus einer Word-Datei (.docx). Liest jeden Absatz einzeln aus. """ doc = DocxDocument(str(path)) paragraphs = [] for paragraph in doc.paragraphs: if paragraph.text.strip(): # Leere Absätze überspringen paragraphs.append(paragraph.text) return "\n\n".join(paragraphs) def _parse_pptx(path: Path) -> str: """ Extrahiert Text aus einer PowerPoint-Datei (.pptx). Geht jede Folie und jede Textbox durch. """ prs = Presentation(str(path)) slides_text = [] for slide_num, slide in enumerate(prs.slides, 1): slide_content = [f"--- Folie {slide_num} ---"] for shape in slide.shapes: # Nur Shapes mit Text verarbeiten if shape.has_text_frame: for paragraph in shape.text_frame.paragraphs: if paragraph.text.strip(): slide_content.append(paragraph.text) slides_text.append("\n".join(slide_content)) return "\n\n".join(slides_text) def _parse_xlsx(path: Path) -> str: """ Extrahiert Text aus einer Excel-Datei (.xlsx). Liest jedes Tabellenblatt Zeile für Zeile. """ wb = load_workbook(str(path), read_only=True) sheets_text = [] for sheet_name in wb.sheetnames: ws = wb[sheet_name] sheet_content = [f"--- Blatt: {sheet_name} ---"] for row in ws.iter_rows(values_only=True): # Zellen zu Text umwandeln, leere Zellen überspringen cells = [str(cell) for cell in row if cell is not None] if cells: sheet_content.append(" | ".join(cells)) sheets_text.append("\n".join(sheet_content)) wb.close() return "\n\n".join(sheets_text) def _parse_image(path: Path) -> str: """ Extrahiert Text aus einem Bild via OCR (Optical Character Recognition). Benötigt Tesseract als externes Programm. """ try: image = Image.open(str(path)) text = pytesseract.image_to_string(image, lang="deu+eng") return text.strip() except Exception as e: raise ValueError(f"OCR fehlgeschlagen: {e}. " "Ist Tesseract installiert? (brew install tesseract)") def _parse_markdown(path: Path) -> str: """ Liest eine Markdown-Datei und entfernt die Formatierung. Gibt den reinen Text zurück. """ raw = path.read_text(encoding="utf-8") # Markdown-Tags entfernen für reinen Text # Wir behalten den Rohtext, da die Struktur für AI nützlich ist return raw def _parse_txt(path: Path) -> str: """ Liest eine einfache Textdatei. Versucht verschiedene Encodings falls UTF-8 nicht klappt. """ try: return path.read_text(encoding="utf-8") except UnicodeDecodeError: return path.read_text(encoding="latin-1")