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

求基于Python的德语PDF组织结构图非结构化文本分类方案

德语组织结构图PDF文本块分类解决方案

针对你提到的矩形文本块分类问题,以下是几个实用的Python方向,避开你之前踩过的坑:

1. 规则+统计特征混合方案

利用德语组织结构图的文本规律,结合统计特征做分类,通用性更强:

  • Type提取:先整理德语常见的组织类型词汇表(["Referat", "Abteilung", "Bereich", "Gruppe", "Sektion"]等),用精确匹配或模糊匹配(考虑大小写、拼写变体)定位Type;
  • Title提取:通常是Type+编号/标识(如Referat XI A 9),在找到Type后,匹配后续的字母数字组合,或者直接提取包含Type的完整短文本块;
  • 负责人(Person in charge):抓德语里的称呼前缀(Herr, Frau, MR, FR),结合名字首字母大写的特征,用正则匹配(比如r"(Herr|Frau|MR|FR)\s+[A-Z][a-z]*(\s+[A-Z][a-z]*)?");同时统计文本块的词长,负责人通常是短文本;
  • Description:剩下的长文本块,词数多、无特定前缀,直接归类。

示例代码片段:

import re

type_vocab = {"Referat", "Abteilung", "Bereich", "Gruppe"}
person_pattern = re.compile(r"(Herr|Frau|MR|FR)\s+[A-Z][a-z]+(\s+[A-Z][a-z]+)?", re.IGNORECASE)

def classify_text_block(text):
    text = text.strip()
    # 匹配Type
    type_match = next((t for t in type_vocab if t.lower() in text.lower()), None)
    # 匹配负责人
    person_match = person_pattern.search(text)
    # 判断Title:包含Type且长度较短
    if type_match and len(text.split()) <= 5:
        return {"Type": type_match, "Title": text, "Description": None, "Person in charge": person_match.group() if person_match else None}
    # 判断负责人单独块
    elif person_match and len(text.split()) <= 3:
        return {"Type": None, "Title": None, "Description": None, "Person in charge": text}
    # 剩下的是Description
    else:
        return {"Type": type_match, "Title": None, "Description": text, "Person in charge": None}

2. 微调小语种预训练语言模型

针对德语短文本分类,用Hugging Face的小语种LLM做少量样本微调,比通用NLP工具更适配非完整句子的场景:

  • 选择轻量模型:比如bert-base-german-cased、distilbert-base-german-cased,训练成本低;
  • 标注少量样本:准备50-100个已分类的矩形文本块,格式化为(文本块, 分类标签),这里可以把四个类别作为多标签任务(一个文本块可能对应多个类别,比如同时包含Type和Title);
  • 用Transformers库快速实现微调:

示例代码框架:

from transformers import BertTokenizer, BertForSequenceClassification, Trainer, TrainingArguments
import torch
from datasets import Dataset

# 假设已标注样本:list of dict,每个dict含"text", "type", "title", "description", "person"
labeled_data = [
    {"text": "Referat XI A 9", "type": 1, "title": 1, "description": 0, "person": 0},
    # 更多样本...
]

# 转为Dataset
dataset = Dataset.from_list(labeled_data)
tokenizer = BertTokenizer.from_pretrained("bert-base-german-cased")

def tokenize_function(examples):
    return tokenizer(examples["text"], padding="max_length", truncation=True)

tokenized_datasets = dataset.map(tokenize_function, batched=True)

# 定义多标签分类模型
model = BertForSequenceClassification.from_pretrained(
    "bert-base-german-cased",
    num_labels=4,
    problem_type="multi_label_classification"
)

# 训练参数
training_args = TrainingArguments(
    output_dir="./results",
    per_device_train_batch_size=8,
    num_train_epochs=3,
    logging_dir="./logs",
)

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_datasets,
)

trainer.train()

# 推理
def classify_with_model(text):
    inputs = tokenizer(text, return_tensors="pt", padding=True, truncation=True)
    outputs = model(**inputs)
    predictions = torch.sigmoid(outputs.logits).tolist()[0]
    labels = ["Type", "Title", "Description", "Person in charge"]
    result = {labels[i]: text if predictions[i] > 0.5 else None for i in range(4)}
    return result

3. 结合视觉特征辅助分类

PDF里的组织结构图文本通常有字体样式差异,提取文本时同步获取字体属性(字号、粗细、颜色),辅助分类:

  • 用PyMuPDF(fitz)提取文本的同时获取字体信息:
import fitz

doc = fitz.open("org_chart.pdf")
page = doc[0]

# 获取带字体信息的文本块
text_blocks = page.get_text("dict")["blocks"]
for block in text_blocks:
    if block["type"] == 0:  # 文本块
        for line in block["lines"]:
            for span in line["spans"]:
                text = span["text"]
                font_size = span["size"]
                is_bold = "bold" in span["font"].lower()
                # 根据字体特征判断类别:大字号粗体大概率是Title/Type,小字号是负责人,常规字号长文本是Description

把字体特征和规则/模型结合,进一步提升准确率,比如大字号(>12)粗体的文本优先匹配Type和Title,小字号(<10)的优先匹配负责人。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 04:40:18