"""PDF extractor with optional OCR fallback.""" from pathlib import Path from typing import List from src.ingest.models import DocumentChunk, NormalizedDocument def _extract_with_pymupdf(path: Path) -> tuple[str, List[DocumentChunk]]: import fitz # pymupdf doc = fitz.open(str(path)) chunks: List[DocumentChunk] = [] parts: List[str] = [] for page_num, page in enumerate(doc, start=1): text = page.get_text("text").strip() if text: parts.append(f"--- Страница {page_num} ---\n{text}") chunks.append(DocumentChunk(text=text, source=path.name, page=page_num)) doc.close() return "\n\n".join(parts).strip(), chunks def _extract_with_ocr(path: Path) -> tuple[str, List[DocumentChunk]]: try: import fitz import pytesseract from PIL import Image import io except ImportError: return "", [] doc = fitz.open(str(path)) chunks: List[DocumentChunk] = [] parts: List[str] = [] for page_num, page in enumerate(doc, start=1): pix = page.get_pixmap(dpi=200) img = Image.open(io.BytesIO(pix.tobytes("png"))) text = pytesseract.image_to_string(img, lang="rus+eng").strip() if text: parts.append(f"--- Страница {page_num} (OCR) ---\n{text}") chunks.append(DocumentChunk(text=text, source=path.name, page=page_num)) doc.close() return "\n\n".join(parts).strip(), chunks def extract_pdf(path: Path, document_id: str, project: str, doc_type: str, use_ocr: bool = True) -> NormalizedDocument: full_text, chunks = _extract_with_pymupdf(path) ocr_used = False if not full_text and use_ocr: full_text, chunks = _extract_with_ocr(path) ocr_used = bool(full_text) return NormalizedDocument( document_id=document_id, filename=path.name, doc_type=doc_type, project=project, full_text=full_text, chunks=chunks or ([DocumentChunk(text=full_text, source=path.name)] if full_text else []), metadata={"format": "pdf", "ocr_used": ocr_used, "pages": len(chunks)}, mime_hint="application/pdf", )