You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyMuPDF提取PDF简历文本不全及区块分类错误的技术求助

解决PyMuPDF提取简历PDF文本的两大问题:提取不全与区块识别错误

问题分析

  1. 文本提取不全:常见原因包括PDF是扫描生成的图片格式(无原生文本)、文本被图层遮挡、或使用默认提取参数未捕获所有文本块。
  2. 区块识别/章节归属错误:简历布局灵活,PyMuPDF默认按PDF内部流顺序返回文本块,而非视觉阅读顺序;且简单的关键词匹配逻辑容易误判,导致内容跨章节归属。

解决方案及代码示例

以下是优化后的脚本,同时解决上述两个问题:

import fitz
import pytesseract
from PIL import Image

def extract_and_classify_resume(pdf_path):
    doc = fitz.open(pdf_path)
    text_blocks = []

    for page in doc:
        # 提取带坐标的原生文本块
        page_text = page.get_text("dict")
        if page_text["blocks"]:
            # 遍历所有文本块,提取有效文本及位置、格式信息
            for block in page_text["blocks"]:
                if "lines" in block:
                    for line in block["lines"]:
                        for span in line["spans"]:
                            clean_text = span["text"].strip()
                            if clean_text:
                                text_blocks.append({
                                    "text": clean_text,
                                    "top": block["bbox"][1],
                                    "font_size": span["size"],
                                    "is_bold": bool(span["flags"] & 1)
                                })
        else:
            # 无原生文本,判定为扫描件,执行OCR
            pix = page.get_pixmap(dpi=300)  # 提高DPI提升OCR准确率
            img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
            ocr_lines = pytesseract.image_to_string(img, lang="chi_sim").split("\n")
            for line in ocr_lines:
                clean_line = line.strip()
                if clean_line:
                    # 模拟扫描件文本块的位置顺序
                    text_blocks.append({
                        "text": clean_line,
                        "top": len(text_blocks),
                        "font_size": 12,
                        "is_bold": False
                    })

    # 按文本块顶部y坐标排序,还原视觉阅读顺序
    text_blocks.sort(key=lambda x: x["top"])

    # 定义目标章节及匹配规则
    target_sections = {
        "个人信息": [],
        "教育背景": [],
        "工作经历": [],
        "项目经验": [],
        "技能特长": []
    }
    current_section = None
    # 章节标题关键词+格式特征(加粗/大字号)双重判定
    section_rules = {
        "个人信息": {"keywords": ["个人信息", "基本信息"], "min_font_size": 14},
        "教育背景": {"keywords": ["教育背景", "教育经历"], "min_font_size": 14},
        "工作经历": {"keywords": ["工作经历", "职业经历"], "min_font_size": 14},
        "项目经验": {"keywords": ["项目经验", "项目经历"], "min_font_size": 14},
        "技能特长": {"keywords": ["技能", "专业技能"], "min_font_size": 14}
    }

    for block in text_blocks:
        text = block["text"]
        # 检查是否匹配章节标题
        matched_section = None
        for section, rules in section_rules.items():
            if any(k in text for k in rules["keywords"]) and \
               (block["font_size"] >= rules["min_font_size"] or block["is_bold"]):
                matched_section = section
                break
        
        if matched_section:
            current_section = matched_section
            continue  # 跳过标题本身,只收集内容
        
        # 将内容归入当前匹配的章节
        if current_section is not None:
            target_sections[current_section].append(text)

    # 合并章节内容为可读字符串
    final_result = {sec: "\n".join(content) for sec, content in target_sections.items()}
    return final_result

# 测试调用
if __name__ == "__main__":
    resume_data = extract_and_classify_resume("test_resume.pdf")
    for section, content in resume_data.items():
        print(f"=== {section} ===")
        print(content if content else "无匹配内容")
        print("\n")

关键优化点

  1. 解决提取不全:

    • 优先提取带坐标的原生文本,确保捕获所有可访问的文本块;
    • 自动检测扫描件PDF,调用OCR工具补充提取图片中的文本;
    • 提高OCR的DPI参数,提升识别准确率。
  2. 解决区块/章节归属错误:

    • 按文本块的顶部y坐标排序,严格遵循视觉阅读顺序;
    • 采用**关键词+格式特征(字号/加粗)**的双重判定规则,减少标题误判;
    • 动态切换当前归属章节,确保后续文本块归入正确分类。

额外优化建议

  • 针对多列布局的简历:可通过文本块的x坐标划分左右列,先处理完左列所有内容再处理右列;
  • 调整章节规则:根据目标简历的格式,修改section_rules中的关键词、字号阈值;
  • 加入段落合并:若相邻文本块的y坐标差小于设定阈值,可合并为同一段落,提升内容可读性。

内容的提问来源于stack exchange,提问作者emma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 02:37:05