import pdfplumber import easyocr import fitz import re import numpy as np reader = easyocr.Reader(['en']) def clean_text(text): """ Clean extracted text while preserving useful structure. """ text = re.sub(r'[ \t]+', ' ', text) text = re.sub(r'\n+', '\n', text) return text.strip() def extract_pdf_text(pdf_path): """ Extract selectable text using pdfplumber. """ text = "" with pdfplumber.open(pdf_path) as pdf: for page in pdf.pages: page_text = page.extract_text() if page_text: text += page_text + "\n" return clean_text(text) def extract_scanned_pdf_text(pdf_path): """ OCR fallback for scanned PDFs using PyMuPDF + EasyOCR. """ print("Opening PDF...") doc = fitz.open(pdf_path) text = "" print(f"Pages found: {len(doc)}") for page_num in range(1, len(doc)): print(f"Processing page {page_num + 1}") page = doc.load_page(page_num) pix = page.get_pixmap(matrix=fitz.Matrix(1, 1)) img = np.frombuffer( pix.samples, dtype=np.uint8 ) img = img.reshape( pix.height, pix.width, pix.n ) results = reader.readtext( img, detail=0 ) text += " ".join(results) text += "\n" doc.close() return clean_text(text) def extract_text_from_pdf(pdf_path): text = extract_pdf_text(pdf_path) if len(text.strip()) > 50: return text print("Scanned PDF detected. Running OCR...") return extract_scanned_pdf_text(pdf_path) def extract_text_from_image(image_path): results = reader.readtext( image_path, detail=0 ) text = " ".join(results) return clean_text(text) def extract_text(file_path): if file_path.lower().endswith(".pdf"): return extract_text_from_pdf(file_path) return extract_text_from_image(file_path)