lecturers-stone / document_parser.py
alfndly's picture
Upload folder using huggingface_hub
c732cdb verified
Raw History Blame Contribute Delete
3.45 kB
"""
Document Parser supporting TXT, Markdown, PDF, DOCX, and raw strings.
"""
from pathlib import Path
from typing import Union
import pymupdf # PyMuPDF
import docx
import pptx
import openpyxl
def extract_text_from_file(file_path: Union[str, Path]) -> str:
"""Extract plain text from various file formats (.txt, .md, .pdf, .docx)."""
path = Path(file_path)
if not path.is_file():
raise FileNotFoundError(f"File not found: {path}")
ext = path.suffix.lower()
if ext in [".txt", ".md", ".markdown", ".rtf", ".rst", ".py", ".json", ".csv"]:
return path.read_text(encoding="utf-8", errors="replace")
elif ext == ".pdf":
text_parts = []
with pymupdf.open(str(path)) as doc:
for page in doc:
t = page.get_text()
if t:
text_parts.append(t)
return "\n\n".join(text_parts).strip()
elif ext in [".docx", ".doc"]:
if ext == ".doc":
# Best effort try python-docx or raw read
try:
doc = docx.Document(str(path))
return "\n".join([p.text for p in doc.paragraphs if p.text]).strip()
except Exception:
return path.read_text(encoding="utf-8", errors="replace")
doc = docx.Document(str(path))
paragraphs = [p.text for p in doc.paragraphs if p.text]
# Also parse tables if present
for table in doc.tables:
for row in table.rows:
row_text = " | ".join([cell.text.strip() for cell in row.cells if cell.text.strip()])
if row_text:
paragraphs.append(row_text)
return "\n".join(paragraphs).strip()
elif ext in [".pptx", ".ppt"]:
prs = pptx.Presentation(str(path))
text_runs = []
for slide_idx, slide in enumerate(prs.slides, 1):
slide_texts = []
for shape in slide.shapes:
if shape.has_text_frame:
for paragraph in shape.text_frame.paragraphs:
p_text = "".join(run.text for run in paragraph.runs).strip()
if p_text:
slide_texts.append(p_text)
elif shape.has_table:
for row in shape.table.rows:
row_text = " | ".join(cell.text.strip() for cell in row.cells if cell.text.strip())
if row_text:
slide_texts.append(row_text)
if slide_texts:
text_runs.append(f"--- Slide {slide_idx} ---\n" + "\n".join(slide_texts))
return "\n\n".join(text_runs).strip()
elif ext in [".xlsx", ".xlsm", ".xltx"]:
wb = openpyxl.load_workbook(str(path), data_only=True)
sheet_texts = []
for sheet_name in wb.sheetnames:
ws = wb[sheet_name]
rows_text = []
for row in ws.iter_rows(values_only=True):
non_empty = [str(cell).strip() for cell in row if cell is not None and str(cell).strip()]
if non_empty:
rows_text.append(" | ".join(non_empty))
if rows_text:
sheet_texts.append(f"--- Sheet: {sheet_name} ---\n" + "\n".join(rows_text))
return "\n\n".join(sheet_texts).strip()
else:
# Default fallback to plain text read
return path.read_text(encoding="utf-8", errors="replace")