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ší situaciDoporučené postupydůvod
Více polí v rámci stejné čáry má stejné souřadnice yBezpečné spojování span.textVětšinou přepínání fontů nebo barev
Mezi rozpětími je zřejmá vodorovná mezeraZkontrolujte mezery bbox a v případě potřeby vložte mezery nebo tabulátoryMůž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ísmaZachovat 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řazenyOznačit jako nízkou kvalitu, převést na ruční nebo OCRNedostatek spolehlivého základu pro třídění a seskupování
Sémanticky souvislý text napříč blokyJe 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: line je 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_tolerance je 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 line sprá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á situaceMetody manipulaceZda 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í mezeraPo zkontrolování mezer vložte mezeru nebo tabulátorBuďte opatrní, potřebujete pravidla
Inline vzorce a indexy způsobují významné rozdíly v souřadnicích yZachovává původní konstrukci rozpětíNe
Single word span a bbox unorderOznačte nízkou kvalitu, přepněte na manuální nebo OCRNe
Sémantický souvislý text napříč blokySoudit podle kontextuNe, je potřeba pomoc s NLP

Kritéria přijetí a hranice manuálního hodnocení

Pozorujte tento jevMožné důvodyRozhodnutí řešit tuto záležitostZda 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 barvyBezpečné spojování span.textAno
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átoryBuď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 unorderNaskenované nebo poškozené PDFOznačeno jako nízká kvalita, přechod na manuální nebo OCRNe
Textová sémantika mezi blokyStránkování a segmentaceKřížové sloučení bloků vyžaduje kontextuální úsudekNe, 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ě spojte span.text.

Pokud narazíte na in-line vzorce nebo indexy

  • Zachovat původní strukturu span a 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í

Aktualizováno 2026-11-15