55 lines
1.8 KiB
Python
55 lines
1.8 KiB
Python
"""DOCX 解析器(python-docx fallback)。"""
|
|
|
|
from app.core.logging import get_logger
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
def parse_docx_with_python_docx(file_content: bytes) -> str | None:
|
|
"""用 python-docx 解析 DOCX,返回 Markdown 或 None(失败时)。"""
|
|
try:
|
|
import io
|
|
|
|
from docx import Document
|
|
|
|
doc = Document(io.BytesIO(file_content))
|
|
md_parts = []
|
|
|
|
for para in doc.paragraphs:
|
|
text = para.text.strip()
|
|
if not text:
|
|
continue
|
|
|
|
style = para.style.name.lower()
|
|
if style.startswith("heading 1"):
|
|
md_parts.append(f"# {text}")
|
|
elif style.startswith("heading 2"):
|
|
md_parts.append(f"## {text}")
|
|
elif style.startswith("heading 3"):
|
|
md_parts.append(f"### {text}")
|
|
elif style.startswith("heading"):
|
|
md_parts.append(f"#### {text}")
|
|
elif style.startswith("list"):
|
|
md_parts.append(f"- {text}")
|
|
else:
|
|
md_parts.append(text)
|
|
|
|
# 处理表格
|
|
for table in doc.tables:
|
|
rows = []
|
|
for row in table.rows:
|
|
cells = [cell.text.strip() for cell in row.cells]
|
|
rows.append("| " + " | ".join(cells) + " |")
|
|
if rows:
|
|
# 添加表头分隔行
|
|
if len(rows) > 1:
|
|
sep = "| " + " | ".join(["---"] * len(table.columns)) + " |"
|
|
rows.insert(1, sep)
|
|
md_parts.append("\n".join(rows))
|
|
|
|
markdown = "\n\n".join(md_parts)
|
|
return markdown if markdown.strip() else None
|
|
except Exception as e:
|
|
logger.warning("python-docx 解析失败: %s", e)
|
|
return None
|