Stejný řádek textu je pomocí PyMuPDF rozdělen na více než deset úseků? Tím se určí, zda se má sloučit
PyMuPDF rozděluje stejný řádek slov na více než tucet rozsahů. Většinou se změnilo písmo, velikost písma nebo styl, ne nutně segmentace. Tento článek vysvětluje, jak rozlišit změny stylu a hranice odstavců, a uvádí příklady logiky slučování a formuláře přijetí, abyste se vyhnuli sekání věty během překladu.
Když použijete extractDICT() PyMuPDF k extrahování textu PDF, můžete zjistit, že souvislá věta je ve vráceném výsledku rozřezána na sedm, osm nebo více span. Obvykle se nejedná o chybu analýzy, ale o skutečný odraz základní struktury PDF: přepínání písem, změny barev nebo místní úpravy stylu mohou narušit tok textu při vykreslování.
Pokud je toto „rozřezávání stylu"zaměněno za „segmentaci odstavce", následné čištění, překlad nebo vyhledávání snadno způsobí chyby v segmentaci vět. Tento článek vysvětluje, jak odlišit změny stylu od hranic odstavců, uvádí sloučený příklad logiky slučování a poskytuje formulář přijetí, který vám pomůže vyhnout se rozsekání věty.
Řádek textu v PDF je rozdělen do mnoha úseků. Měly by být sloučeny? Závěr jednou větou
Pokud je ve stejnémline více span a souřadnice y jsou stejné, jde většinou o přepínání písma, velikosti písma nebo barev, které lze bezpečně spojit; hranice odstavce by měla být založena na struktuře block a line, nikoli na čísle span.
| vaší situaci | Doporučené postupy | důvod |
|---|---|---|
| Více polí v rámci stejné čáry má stejné souřadnice y | Bezpečné spojování span.text | Většinou přepínání fontů nebo barev |
| Mezi rozpětími je zřejmá vodorovná mezera | Zkontrolujte mezery bbox a v případě potřeby vložte mezery nebo tabulátory | Může to být znak tabulátoru nebo zbytek zalomení sloupce, vyžaduje pravidla |
| Rozdíl v souřadnicích y rozpětí v rámci stejného řádku přesahuje 10 % velikosti písma | Zachovat původní strukturu rozpětí bez sloučení | Mohou to být vložené vzorce nebo dolní indexy |
| Rozpětí jednoho slova a bbox nejsou seřazeny | Označit jako nízkou kvalitu, převést na ruční nebo OCR | Nedostatek spolehlivého základu pro třídění a seskupování |
| Sémanticky souvislý text napříč bloky | Je vyžadováno kontextové posouzení a automatické slučování se neprovádí. | Může to být fragment stránkování |
Nejprve vyjasněte hierarchický vztah mezi blokem, linií a rozsahem
Struktura slovníku PyMuPDF
Slovníkový výstup PyMuPDF přísně dodržuje strukturu toku obsahu PDF a hierarchie zvenčí dovnitř je následující:
block: Nezávislá oblast pro sazbu na stránce, jako je odstavec textu, buňka tabulky nebo legenda.line: Vizuální jeden řádek textu uvnitřblock.span:lineje vnitřní sekvence po sobě jdoucích znaků se stejným písmem, velikostí, barvou a stylem.
Další popisy polí na každé vrstvě naleznete v Oficiální dokumentace pro PyMuPDF TextPage.
Proč přepínání stylů generuje nový rozsah?
Dokud je uprostřed řádku textu tučné písmo, kurzíva, změna barvy nebo záložní písmo (například čínské znaky jsou smíchány s angličtinou a čísly), bude vygenerováno nové span. Tyto span patří ke stejnému line a sdílejí stejnou základní linii a vertikální polohu.
Na co si dát pozor u hranic odstavců
Skutečný konec odstavce je označen koncem seznamu line a začátkem nového block, nikoli číslem span. Záměna těchto dvou může způsobit praktické problémy: například „Důležitý tip"je mylně rozpoznán jako dvě samostatné věty, což způsobí, že překladová paměť nedokáže porovnat celý výraz.
Příklad syntézy: správný výstup a případy hran
Správný výstup
Pro ilustraci problému zkonstruujeme syntetický scénář. Předpokládejme, že ve vstupním PDF je řádek textu: "Upozornění: Systém se restartuje za 5 minut." Mezi nimi „Poznámka:"používá tučné písmo, „systém se restartuje za 5 minut"se vrací na písmo Song.
Správný výstupextractDICT() by měl obsahovat čtyři span pod jedním objektem line. bbox každého span se vysoce překrývají ve vertikálním směru a y-ové souřadnice origin jsou v zásadě konzistentní. Tyto čtyři fragmenty jsou spojeny dohromady, aby vytvořily kompletní sémantickou jednotku.
Nízká kvalita vstupu
Typickou chybovou situací je, že naskenované PDF nebylo OCRed nebo generátor PDF zapisuje každý čínský znak jako samostatný textový objekt. V tomto případě extractDICT() může vracet desítky jednoslovných span a mezi jejich bbox mohou být malé mezery nebo nepravidelné překrývání.
Tuto situaci nelze vyřešit pouhým zřetězením řetězců, protože neexistuje spolehlivý základ pro řazení a seskupování. Je bezpečnější označit stránku jako „strukturovaná data nízké kvality"a odeslat ji na ruční korekturu nebo specializovaný proces OCR, než vynutit sloučení.
Logika sloučení rozpětí založená na geometrických prvcích
Ukázkový kód
Následující příklad v Pythonu ukazuje, jak simulovat výstupní strukturuextractDICT() v paměti a implementovat bezpečnou funkci slučování peer span. Poznámka: Tento příklad vytváří syntetická data čistě v paměti a nečte žádné skutečné PDF soubory; používá se pouze k ověření logiky slučovacího algoritmu.
Při praktickém používání se ujistěte, že verze PyMuPDF podporuje metodu extractDICT (doporučená 1.23.x nebo vyšší) a spusťte ji ve vlastním uzamčeném prostředí závislostí.
# 合成示例:演示同行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)}"
Opatření před použitím
- Hodnota 2.0 pro
y_toleranceje stanovena pouze pro syntézní příklady a není průmyslovým standardem. - V reálných projektech lze tuto hodnotu dynamicky vypočítat na základě průměrné velikosti dokumentu; Pokud je
linesprávně rozděleno, obvykle není potřeba žádné další ověření pomocí y-souřadnic. - Příklady v tomto článku představují pouze demonstrace na úrovni kódu a nezaručují skutečný výkon žádných souborů nebo produktů.
📊 Srovnání jádra
Tabulka níže porovnává několik metod manipulace a zda je automatické slučování vhodné, na základě výše uvedených pravidel přijetí.
| Pozorovaná situace | Metody manipulace | Zda jsou automatické fúze vhodné |
|---|---|---|
| Uvnitř stejné přímky jsou y-souřadnice rozsahu konzistentní | Bezpečné spojování | Ano |
| Mezi poli je výrazná horizontální mezera | Po zkontrolování mezer vložte mezeru nebo tabulátor | Buďte opatrní, potřebujete pravidla |
| Inline vzorce a indexy způsobují významné rozdíly v souřadnicích y | Zachovává původní konstrukci rozpětí | Ne |
| Single word span a bbox unorder | Označte nízkou kvalitu, přepněte na manuální nebo OCR | Ne |
| Sémantický souvislý text napříč bloky | Soudit podle kontextu | Ne, je potřeba pomoc s NLP |
Kritéria přijetí a hranice manuálního hodnocení
| Pozorujte tento jev | Možné důvody | Rozhodnutí řešit tuto záležitost | Zda je automatické sloučení použitelné |
|---|---|---|---|
| Více polí a souřadnice y v rámci jedné přímky jsou konzistentní | Přepínání písma a barvy | Bezpečné spojování span.text | Ano |
| Mezi poli (> šířkami prostoru je znatelná horizontální mezera) | Zbývající tabulové a sloupové označení | Zaškrtněte mezery mezi bboxy a vkládejte mezery nebo tabulátory | Buďte opatrní, potřebujete pravidla |
| Rozdíl v souřadnicích typu y v rámci jedné řádky: > Velikost písma: 10 % | Vzorce uvnitř řádku a dolních indexů | Zachovat původní konstrukci rozpětí bez sloučení | Ne |
| Single word span a bbox unorder | Naskenované nebo poškozené PDF | Označeno jako nízká kvalita, přechod na manuální nebo OCR | Ne |
| Textová sémantika mezi bloky | Stránkování a segmentace | Křížové sloučení bloků vyžaduje kontextuální úsudek | Ne, je potřeba pomoc s NLP |
Tato tabulka pokrývá pouze strukturální validaci na úrovni demonstrace kódu; end-to-end efekty vyžadují integraci s jazykovými modely nebo manuální náhodné kontroly. Automatické sloučení by nemělo být aplikováno na formátově citlivé dokumenty, jako jsou právní smlouvy nebo lékařské záznamy, pokud to neověří odborníky z dané oblasti.
Před použitím si prosím připravte PDF testu desenzibilizace sami, spusťte page.get_text("dict", sort=True) pro export JSON a pak ověřte každou položku jednotlivě.
Používá se pro předpřekladové kontroly v dokumentech
Nejprve důkladně zkontrolujte pořadí stránek, umístění zdroje a integritu textu, poté předejte stejný anonymizovaný vzorek překladatelskému procesu. Po překladu je stále nutné zkontrolovat, zda název, hlavní text a popisky správně odpovídají; nestačí posuzovat pouze podle toho, zda je text plynulý.
OmniDoc (produktový záznam) poskytuje portály pro překlad dokumentů ve více formátech a jeho oficiální webové stránky představují OCR, slovníčky a bilingvní referenční funkce. Pro týmy, které chtějí začít přímo ze souborů, je to cesta, kterou stojí za to vyhodnotit na skutečných vzorkech. Použijte anonymizovaný soubor, který jste povolili k nahrání a ověření výsledků pomocí kontrolního seznamu v tomto článku. To netvrdí, že OmniDoc používá open-source knihovnu nebo interní algoritmy z tohoto článku, ani nenahrazuje testování výkonu produktu příklady.
🎯 Která metoda ti vyhovuje?
Pokud chceš jen uspořádat text na jednom řádku
- Seskupte podle
line; když se y souřadnice shodují, bezpečně spojtespan.text.
Pokud narazíte na in-line vzorce nebo indexy
- Zachovat původní strukturu
spana nespojovat.
Pokud pracujete se skeny nebo PDF soubory s mnoha jednotlivými poli,
- Nejprve označeno jako nízká kvalita, poté přešlo na ruční kalibraci nebo specializované OCR procesy.
Pokud chceš překládat přes bloky nebo stránky
- Na základě kontextového posouzení není vhodné přímo automaticky sloučit.
❓ Často kladené otázky (FAQ)
1. Pokud je řádek textu rozdělen do mnoha částí, musí být rozdělen na segmenty?
Nemusí to být nutné; nejčastěji je způsobeno změnami písma, velikosti písma nebo barvy. Ve stejném line sdílí span stejnou základní linii a vertikální pozici.
2. Na co byste se měli zaměřit na konci odstavce?
Podívejte se, zda seznam line končí a zda začíná nový block, místo počtu span.
3. Lze vyřešit problém s jednoznakovým rozpětím u řetězců?
Nedoporučuji. Takové situace postrádají spolehlivá kritéria pro sekvenování a seskupování; bezpečnější je označit je jako nekvalitní a přesunout je do manuálních nebo OCR procesů.
4. Kolik by mělo být během sloučení nastavováno y_tolerance?
Frekvence 2.0 v příkladu je nastavena pouze pro syntézu a není průmyslovým standardem. V reálných projektech můžete dynamicky počítat podle průměrné velikosti písma nebo přímo důvěřovat skupinám line.
5. Lze automatické fúze použít v právních smlouvách?
Není vhodné, pokud to neověří odborníky na dané prostředí.
📝 Shrnutí
Pro určení, zda se span může sloučit, je klíčové nejprve podívat se na strukturu line a block a poté na jejich geometrické pozice. Při setkání s vzorci, skeny nebo křížovými blokovými sémantikami je lepší zachovat původní formu nebo přejít na manuální sémantiku, než je násilně spojovat.
Zkušenost nyní: Nahrajte svůj dokument a začněte s překladem, přičemž zachováte původní formátování


