"""文档解析:各类文件 → 纯文本(供 RAG 切块/embedding)。 按扩展名路由:txt/md/csv 直读;docx(python-docx);xlsx(openpyxl);pdf(pypdf)。 扫描件/版面 OCR(MinerU/PaddleOCR) 为后续。 """ from __future__ import annotations import csv import io def parse(filename: str, data: bytes) -> str: ext = filename.lower().rsplit(".", 1)[-1] if "." in filename else "" if ext in ("txt", "md", "markdown", "text", ""): return data.decode("utf-8", errors="replace") if ext == "csv": return _csv(data) if ext == "docx": return _docx(data) if ext == "xlsx": return _xlsx(data) if ext == "pdf": return _pdf(data) raise ValueError(f"暂不支持的文件类型: .{ext}") def _csv(data: bytes) -> str: text = data.decode("utf-8", errors="replace") rows = list(csv.reader(io.StringIO(text))) return "\n".join(" | ".join(r) for r in rows if any(c.strip() for c in r)) def _docx(data: bytes) -> str: from docx import Document # python-docx doc = Document(io.BytesIO(data)) lines: list[str] = [p.text for p in doc.paragraphs if p.text.strip()] for table in doc.tables: for row in table.rows: cells = [c.text.strip() for c in row.cells] if any(cells): lines.append(" | ".join(cells)) return "\n".join(lines) def _xlsx(data: bytes) -> str: from openpyxl import load_workbook wb = load_workbook(io.BytesIO(data), read_only=True, data_only=True) lines: list[str] = [] for ws in wb.worksheets: lines.append(f"# 工作表: {ws.title}") for row in ws.iter_rows(values_only=True): cells = [str(c) for c in row if c is not None] if cells: lines.append(" | ".join(cells)) return "\n".join(lines) def _pdf(data: bytes) -> str: from pypdf import PdfReader reader = PdfReader(io.BytesIO(data)) pages = [(page.extract_text() or "").strip() for page in reader.pages] return "\n\n".join(p for p in pages if p)