求基于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
相关产品推荐
相关产品推荐

