ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

山东大学软件学院项目实训【个人8】

山东大学软件学院项目实训【个人8】

法律文书智能摘要系统文件上传实现分析

一、整体架构设计

该系统采用格式识别 + 策略路由的架构模式,在documents.py中实现统一的上传入口,根据文件扩展名和内容特征自动路由到不同解析器:

┌─────────────────────────────────────────────────────────────┐ │ /api/documents/upload │ └─────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────┐ │ 格式检测 │ │ ext = filename.split │ └─────────────────────────┘ │ │ │ ┌──────────┘ │ └──────────┐ ▼ ▼ ▼ ┌───────────┐ ┌─────────────┐ ┌─────────────┐ │ .txt │ │ .docx │ │ .pdf │ │ 直接解码 │ │ parse_word │ │ parse_pdf │ └───────────┘ └─────────────┘ └─────────────┘ │ ┌───────────┴───────────┐ ▼ ▼ ┌───────────┐ ┌───────────┐ │ is_scanned│ │is_scanned │ │ = False │ │ = True │ │ 返回文本块│ │ ocr_pdf │ └───────────┘ └───────────┘

二、各格式实现详解

1. TXT 格式 - 多编码兼容解码

核心实现documents.py:189-209):

with open(file_path, "rb") as f: raw = f.read() # 尝试不同编码,处理双重UTF-8编码情况 try: text = raw.decode("utf-8") # 检测是否为双重编码(mojibake) if any(c in text for c in ['å', 'é', 'ä', 'ç', 'è']) and not any('\u4e00' <= c <= '\u9fff' for c in text[:200]): text = text.encode('latin-1').decode('utf-8') except (UnicodeDecodeError, UnicodeEncodeError): try: text = raw.decode("gbk") except UnicodeDecodeError: text = raw.decode("utf-8", errors="replace")

技术要点

处理步骤技术手段解决的问题
首选UTF-8解码raw.decode("utf-8")处理标准UTF-8编码文件
双重编码检测mojibake特征字符检测处理Windows下常见的双重编码问题
GBK降级raw.decode("gbk")兼容传统中文Windows编码
容错兜底errors="replace"确保任何情况下都能解析

2. DOCX 格式 - python-docx 解析

核心实现pdf_parser.py:281-307):

def parse_word(file_path: str) -> tuple[DocumentMeta, list[TextBlock]]: from docx import Document as DocxDocument docx_doc = DocxDocument(file_path) blocks: list[TextBlock] = [] for i, para in enumerate(docx_doc.paragraphs): text = para.text.strip() if not text: continue block_type = "title" if para.style and "Heading" in (para.style.name or "") else "text" blocks.append(TextBlock( content=text, page=1, # Word无精确页码,标记为1 bbox=[0, i * 20, 500, (i + 1) * 20], # 近似坐标 block_type=block_type, ))

技术要点

特性实现方式说明
标题识别通过样式名判断"Heading" in para.style.name
段落分割按docx段落对象遍历天然保持段落结构
页码处理统一标记为1Word文档内部无固定页码概念
坐标模拟线性计算近似坐标[0, i*20, 500, (i+1)*20]

3. PDF 非扫描件 - PyMuPDF 高精度解析

核心实现pdf_parser.py:163-278):

def parse_pdf(file_path: str, filter_mode: FilterMode = "keep_all") -> tuple[DocumentMeta, list[TextBlock]]: doc = fitz.open(file_path) is_scanned = detect_scanned(doc) # 扫描件检测 if is_scanned: doc.close() return meta, [] # 返回空块,后续走OCR for page_num in range(len(doc)): page = doc[page_num] page_dict = page.get_text("dict") for block in page_dict.get("blocks", []): if block.get("type") == 0: # text block for line in block.get("lines", []): line_text = "" for span in line.get("spans", []): line_text += span.get("text", "").strip() # 判断行类型(页眉/页脚/正文/标题) block_type = "title" if max_font_size > 14 else "text" if line_bbox[1] < 50: block_type = "header" elif line_bbox[3] > page.rect.height - 50: block_type = "footer"

扫描件检测算法pdf_parser.py:12-19):

def detect_scanned(doc: fitz.Document, sample_pages: int = 3) -> bool: """检测PDF是否为扫描件:前几页文本极少则判定为扫描件""" pages_to_check = min(sample_pages, len(doc)) total_text = "" for i in range(pages_to_check): total_text += doc[i].get_text() return len(total_text.strip()) < 50 * pages_to_check

段落合并算法pdf_parser.py:50-107):

判断条件阈值说明
行尾空缺比例gap_ratio > 0.20行尾空白超过页面宽度20%
垂直间距> 2.5 * font_size段落间距大于2.5倍行高
字体大小变化> 1.5字号变化超过1.5磅

4. PDF 扫描件 - OCR + LLM勘误

核心实现ocr_service.py:65-150):

def ocr_pdf(file_path: str) -> list[TextBlock]: doc = fitz.open(file_path) blocks: list[TextBlock] = [] for page_num in range(len(doc)): page = doc[page_num] # 1. 页面渲染为图像(300 DPI) pix = page.get_pixmap(dpi=300) img = Image.open(io.BytesIO(pix.tobytes("png"))) # 2. 图像预处理 preprocessed_img = preprocess_image(img) # 3. Tesseract OCR ocr_data = pytesseract.image_to_data( preprocessed_img, lang="chi_sim", output_type=pytesseract.Output.DICT )

图像预处理流程ocr_service.py:21-62):

原始图像 → 灰度化 → 二值化(Otsu阈值)→ 中值滤波去噪 → 倾斜校正 → OCR识别

后端调用链路documents.py:174-185):

if meta.is_scanned: # 首先进行OCR识别 ocr_blocks = ocr_pdf(file_path) # 然后使用LLM进行勘误和标准化 blocks, ocr_correction = enhance_ocr_results(ocr_blocks)

三、四种格式实现对比

维度TXTDOCXPDF(非扫描)PDF(扫描件)
解析引擎Python内置解码python-docxPyMuPDFTesseract OCR
文本精度无损无损无损依赖图像质量
结构保留仅段落标题/段落完整结构+坐标OCR重建结构
页眉页脚处理N/AN/A可配置过滤OCR后处理
页码信息精确精确
坐标信息模拟精确像素转换
置信度N/AN/AN/A字符级置信度
处理耗时极快较快中等较慢
内存占用

四、技术亮点总结

1. 智能扫描件检测

  • 基于文本密度判断,阈值50 * pages_to_check
  • 兼顾准确性和性能,仅采样前3页

2. 多编码容错机制

  • UTF-8优先,GBK降级,容错兜底
  • 双重编码自动检测(mojibake特征)

3. 段落边界智能识别

  • 融合行尾空缺、垂直间距、字体变化三重判断
  • 自适应阈值,避免过度分割或合并

4. OCR质量优化

  • 完整的图像预处理流水线
  • 字符级置信度输出,支持后续LLM勘误

5. 渐进式处理策略

  • 同步完成:文件保存、基础解析、信息抽取、文本切片
  • 后台异步:LLM分类、向量化、A-MEM吸收
  • 提升用户体验,避免长时间等待
返回列表