Dezelfde regel tekst door PyMuPDF in meer dan tien delen wordt opgesplitst? Dit bepaalt of er moet worden samengevoegd
PyMuPDF splitst dezelfde regel woorden in meer dan een dozijn reeksen. Meestal is het lettertype, de lettergrootte of de stijl veranderd, niet noodzakelijkerwijs de segmentatie. Dit artikel legt uit hoe je stijlwijzigingen en alineagrenzen kunt onderscheiden, en geeft voorbeelden van het samenvoegen van logica en een acceptatieformulier om te voorkomen dat een zin tijdens de vertaling in stukken wordt gehakt.
Wanneer u extractDICT() van PyMuPDF gebruikt om PDF-tekst te extraheren, kan het zijn dat een samenhangende zin in zeven, acht of meer span wordt opgedeeld in het geretourneerde resultaat. Dit is meestal geen parseerfout, maar een waarheidsgetrouwe weerspiegeling van de onderliggende structuur van de PDF: het wisselen van lettertype, kleurveranderingen of lokale stijlaanpassingen kunnen de tekststroom tijdens het renderen onderbreken.
Als deze "style slicing" wordt aangezien voor "paragraafsegmentatie", zal het daaropvolgende opschonen, vertalen of ophalen gemakkelijk zinssegmentatiefouten veroorzaken. Dit artikel legt uit hoe je stijlwijzigingen kunt onderscheiden van alineagrenzen, geeft een samengevoegd voorbeeld van het samenvoegen van logica en biedt een acceptatieformulier waarmee je kunt voorkomen dat je een zin in stukken hakt.
Een tekstregel in de PDF is opgesplitst in vele reeksen. Moeten ze worden samengevoegd? Conclusie in één zin
Als er meerdere span in dezelfde line zijn en de y-coördinaten hetzelfde zijn, is het meestal het wisselen van lettertype, lettergrootte of kleur, die veilig kunnen worden gesplitst; de alineagrens moet gebaseerd zijn op de structuur van block en line, niet op het aantal span.
| jouw situatie | Aanbevolen praktijken | reden |
|---|---|---|
| Meerdere overspanningen binnen dezelfde lijn hebben dezelfde y-coördinaten | Veilige splitsing span.text | Meestal lettertype- of kleurwisseling |
| Er is een duidelijke horizontale opening tussen de overspanningen | Controleer de afstand tussen de bboxen en voeg indien nodig spaties of tabs in | Kan een tabteken of kolomeinderesidu zijn, er zijn regels nodig |
| Het verschil in y-coördinaten van overspanningen binnen dezelfde regel is groter dan 10% van de lettergrootte | Behoud de oorspronkelijke overspanningsstructuur zonder samen te voegen | Dit kunnen inline formules of subscripts zijn |
| Enkele woordspanne en bbox zijn ongeordend | Markeer als lage kwaliteit, converteer naar handmatig of OCR | Gebrek aan betrouwbare basis voor sorteren en groeperen |
| Semantisch doorlopende tekst over blokken heen | Contextueel oordeel is vereist en automatische samenvoeging wordt niet uitgevoerd. | Het kan een pagingfragment zijn |
Verduidelijk eerst de hiërarchische relatie tussen Blok, Lijn en Span
Woordenboekstructuur van PyMuPDF
De woordenboekuitvoer van PyMuPDF volgt strikt de structuur van de inhoudsstroom van PDF, en de hiërarchie van buiten naar binnen is als volgt:
block: een onafhankelijk typografiegebied op de pagina, zoals een alinea met tekst, een tabelcel of een legenda.line: Visuele enkele tekstregel binnenblock.span:lineis een interne reeks opeenvolgende tekens met hetzelfde lettertype, dezelfde grootte, kleur en stijl.
Voor meer beschrijvingen van velden op elke laag raadpleegt u Officiële documentatie voor PyMuPDF TextPage.
Waarom genereert stijlwisseling een nieuwe reeks?
Zolang er vetgedrukt, cursief, kleurverandering of lettertype-terugval in het midden van een tekstregel aanwezig is (Chinese karakters worden bijvoorbeeld gemengd met Engels en cijfers), wordt er een nieuwe span gegenereerd. Deze span's behoren tot dezelfde line en delen dezelfde basislijn en verticale positie.
Waar je op moet letten bij alineagrenzen
Het echte einde van een alinea wordt gemarkeerd door het einde van de line-lijst en het begin van een nieuwe block, niet door het nummer van span. Het verwarren van deze twee kan praktische problemen veroorzaken: "Belangrijke tip" wordt bijvoorbeeld ten onrechte herkend als twee afzonderlijke zinnen, waardoor het vertaalgeheugen niet in staat is de volledige term te matchen.
Synthesevoorbeeld: correcte uitvoer en randgevallen
Correcte uitvoer
Om het probleem te illustreren construeren we een synthetisch scenario. Stel dat er een regel tekst in de invoer-PDF staat: "Let op: het systeem zal over 5 minuten opnieuw opstarten." Onder hen gebruikt "Let op:" een vet lettertype, "het systeem wordt over 5 minuten opnieuw opgestart" keert terug naar het Song-lettertype.
Correcte extractDICT()-uitvoer zou vier span onder één line-object moeten bevatten. De bbox van elke span overlappen elkaar in verticale richting sterk, en de y-coördinaten van origin zijn in principe consistent. Deze vier fragmenten worden aan elkaar gesplitst om een volledige semantische eenheid te vormen.
Invoer van lage kwaliteit
Een typische foutsituatie is dat de gescande PDF niet is OCRed, of dat de PDF-generator elk Chinees teken als een afzonderlijk tekstobject schrijft. In dit geval kan extractDICT() tientallen span's van één woord retourneren, en kunnen er kleine gaten of onregelmatige overlappingen tussen hun bbox's voorkomen.
Deze situatie kan niet eenvoudigweg worden opgelost door string-aaneenschakeling, omdat er geen betrouwbare basis is voor sorteren en groeperen. Het is veiliger om de pagina te markeren als 'gestructureerde gegevens van lage kwaliteit' en deze handmatig te laten proeflezen of naar een speciaal OCR-proces te sturen, in plaats van een samenvoeging te forceren.
Span-merge logica gebaseerd op geometrische kenmerken
Voorbeeldcode
Het volgende Python-voorbeeld laat zien hoe je de uitvoerstructuur van extractDICT() in het geheugen kunt simuleren en een veilige peer span merge-functie kunt implementeren. Opmerking: Dit voorbeeld construeert synthetische data puur in het geheugen en leest geen echte PDF-bestanden; het wordt alleen gebruikt om de logica van het samenvoegingsalgoritme te verifiëren.
Zorg er bij het gebruik van deze in de praktijk voor dat de PyMuPDF-versie de extractDICT-methode ondersteunt (aanbevolen 1.23.x of hoger) en voer deze uit in je eigen gesloten afhankelijkheidsomgeving.
# 合成示例:演示同行span合并逻辑,非真实PDF解析结果
# 依赖: PyMuPDF (pymupdf) >= 1.23.0,仅用于类型参考,本例纯内存构造
def merge_spans_in_line(line_dict, y_tolerance=2.0):
"""合并同一line内y坐标相近的span,保留原始顺序"""
if not line_dict.get("spans"):
return ""
spans = sorted(line_dict["spans"], key=lambda s: s["bbox"][0]) # 按x排序
merged_text = []
current_y = spans[0]["origin"][1]
buffer = [spans[0]["text"]]
for span in spans[1:]:
y = span["origin"][1]
if abs(y - current_y) <= y_tolerance:
buffer.append(span["text"])
else:
merged_text.append("".join(buffer))
buffer = [span["text"]]
current_y = y
merged_text.append("".join(buffer))
return "\n".join(merged_text)
# 构造合成line数据,模拟四种字体混排(正常情况)
synthetic_line = {
"spans": [
{"text": "请注意:", "bbox": (100, 200, 160, 220), "origin": (100, 215)},
{"text": "系统将在", "bbox": (160, 200, 220, 220), "origin": (160, 215)},
{"text": "5", "bbox": (220, 200, 230, 220), "origin": (220, 215)},
{"text": "分钟后重启。", "bbox": (230, 200, 310, 220), "origin": (230, 215)}
]
}
result = merge_spans_in_line(synthetic_line)
assert result == "请注意:系统将在5分钟后重启。", f"合并失败: {result}"
# 边界测试:y坐标差异超过容差,应视为不同行片段(即使在同一line dict中也应分隔)
bad_line = {
"spans": [
{"text": "上行", "bbox": (100, 200, 140, 220), "origin": (100, 215)},
{"text": "下行", "bbox": (100, 230, 140, 250), "origin": (100, 245)}
]
}
bad_result = merge_spans_in_line(bad_line, y_tolerance=2.0)
# y差值30 > 2.0,应被分隔为两行
assert bad_result == "上行\n下行", f"异常行未正确分隔: {repr(bad_result)}"
Voorzorgsmaatregelen voor gebruik
- De waarde 2.0 voor
y_toleranceis alleen ingesteld voor synthesevoorbeelden en is geen industriestandaard. - In daadwerkelijke projecten kan deze waarde dynamisch worden berekend op basis van de gemiddelde documentgrootte; Als
linezelf correct is gedeeld, is er meestal geen extra y-coördinatenverificatie nodig. - De voorbeelden in dit artikel zijn alleen demonstraties op codeniveau en garanderen niet de daadwerkelijke prestaties van bestanden of producten.
📊 Kernvergelijking
De onderstaande tabel vergelijkt verschillende afhandelingsmethoden en of automatische samenvoeging geschikt is, gebaseerd op de hierboven genoemde acceptatieregels.
| Waargenomen situatie | Afhandelingsmethoden | Of automatische fusies geschikt zijn |
|---|---|---|
| Binnen dezelfde lijn zijn de y-coördinaten van de span consistent | Veilige splicing | Ja |
| Er is een duidelijke horizontale opening tussen de overspanningen | Na het controleren van de afstand voeg je een spatie of tabstop in | Wees voorzichtig, en je hebt regels nodig |
| Inline-formules en subscripts veroorzaken aanzienlijke verschillen in y-coördinaten | Behoudt de oorspronkelijke overspanningsstructuur | Nee |
| Enkele woordenreeks en bbox ongeordend | Markeer lage kwaliteit, schakel over op handmatig of OCR | Nee |
| Semantische continue tekst over blokken heen | Oordeel op basis van context | Nee, NLP-hulp is vereist |
Acceptatiecriteria en Grenzen voor handmatige beoordeling
| Observeer het fenomeen | Mogelijke redenen | Beslissing om de zaak af te handelen | Of automatische fusie van toepassing is |
|---|---|---|---|
| Meerdere overspanningen en y-coördinaten binnen dezelfde lijn zijn consistent | Lettertype/kleurwisseling | Veilige splitsing span.text | Ja |
| Er is een merkbare horizontale opening tussen de overspanningen (> ruimtebreedtes) | Overige tabel- en kolommarkeringen | Controleer bbox-spatiëring en voeg spaties of tab-stops in | Wees voorzichtig, en je hebt regels nodig |
| Verschil in span y-coördinaten binnen dezelfde regel: > Lettergrootte: 10% | Formules binnen de regel en subscripts | Bebehoud de oorspronkelijke overspanningsstructuur zonder te laten samenvoegen | Nee |
| Enkele woordenreeks en bbox ongeordend | Gescande of beschadigde PDF | Gemarkeerd als lage kwaliteit, overschakelen naar handmatig of OCR | Nee |
| Tekstsemantiek tussen blokken | Paginering en segmentatie | Cross-block merging vereist contextuele beoordeling | Nee, NLP-hulp is vereist |
Deze tabel behandelt alleen structurele validatie op het niveau van codedemonstratie; end-to-end effecten vereisen integratie met taalmodellen of handmatige steekproefcontroles. Automatische samenvoeging mag niet worden toegepast op formaatgevoelige documenten zoals juridische contracten of medische dossiers, tenzij gevalideerd door domeinexperts.
Bereid voor gebruik zelf de desensitisatietest-PDF voor, voer page.get_text("dict", sort=True) uit om JSON te exporteren, en verifieer vervolgens elk item één voor één.
Gebruikt voor pre-vertalingscontroles in documenten
Controleer eerst de paginavolgorde, bronlocatie en tekstintegriteit grondig, en geef vervolgens hetzelfde geanonimiseerde voorbeeld aan het vertaalproces. Na de vertaling is het nog steeds nodig om te controleren of de titel, hoofdtekst en onderschriften correct overeenkomen; het is niet voldoende om alleen te beoordelen of de tekst vloeiend is.
OmniDoc (Productinvoer) biedt multi-formaat documentvertaalportalen en de officiële website introduceert OCR, woordenlijsten en tweetalige referentiefuncties. Voor teams die direct vanaf de bestanden willen beginnen, is dit een pad dat de moeite waard is om te evalueren met echte monsters. Gebruik alstublieft het geanonimiseerde bestand dat u hebt geautoriseerd om te uploaden en de resultaten te verifiëren met de checklist in dit artikel. Dit beweert niet dat OmniDoc gebruikmaakt van de open-source bibliotheek of interne algoritmen uit dit artikel, noch vervangt het productprestatietesten door voorbeelden.
🎯 Welke methode past bij jou?
Als je alleen tekst op dezelfde regel wilt organiseren
- Groeperen volgens
line; wanneer y-coördinaten overeenkomen, sluitspan.textveilig aan.
Als je in-line formules of subscripts tegenkomt
- Behoud de oorspronkelijke
span-structuur en fuseer niet.
Als je werkt met scans of PDF's met veel enkele spans,
- Aanvankelijk als lage kwaliteit gemarkeerd, daarna overgestapt op handmatige kalibratie of speciale OCR-processen.
Als je wilt vertalen over blokken of pagina's
- Op basis van contextuele beoordeling is het niet raadzaam om direct automatisch te mergen.
❓ Veelgestelde Vragen (FAQ)
1. Als een regel tekst in meerdere reeksen is opgesplitst, moet die dan gesegmenteerd zijn?
Niet per se; meestal wordt het veroorzaakt door veranderingen in lettertype, lettergrootte of kleur. Binnen dezelfde line deelt span dezelfde basislijn en verticale positie.
2. Waar moet je op letten aan het einde van een alinea?
Kijk of de line-lijst eindigt en of de nieuwe block begint, in plaats van het aantal span.
3. Kun je het probleem met de enkelvoudige tekenafstand oplossen met stringconcatenatie?
Niet aan te raden. Dergelijke situaties missen betrouwbare sequencing- en groeperingscriteria; een veiligere aanpak is om ze als laag van kwaliteit te markeren en over te plaatsen naar handmatige of OCR-processen.
4. Hoeveel moet y_tolerance worden ingesteld tijdens de samenvoeging?
De 2.0 in het voorbeeld is uitsluitend bedoeld voor synthesedoeleinden en is geen industriestandaard. In echte projecten kun je dynamisch berekenen op basis van de gemiddelde lettergrootte of direct vertrouwen op line-groepering.
5. Kunnen automatische fusies worden gebruikt in juridische contracten?
Niet geschikt tenzij geverifieerd door domeinexperts.
📝 Samenvatting
Om te bepalen of span kan samensmelten, is de sleutel om eerst naar de structuur van line en block te kijken, en vervolgens naar hun geometrische posities. Bij het tegenkomen van formules, scans of cross-block semantiek is het beter om de oorspronkelijke vorm te behouden of over te schakelen op handmatige semantiek dan ze met geweld te verbinden.
Ervaar nu: upload je document om te beginnen met vertalen, waarbij je de originele opmaak behoudt


