Při předávání anotovaných dokumentů nepředávejte pouze PDF, které vypadá čistě.

Tento článek poskytuje řešení vrstvené extrakce a ověřování zabezpečení založené na PyMuPDF, které řeší problémy se záměnou textu a komentářů, únikem citlivých dat a záměnou souřadnicových systémů při extrakci anotací PDF. Obsah pokrývá princip nezávislé datové vrstvy, příklady defenzivního programování, zpracování okrajových podmínek a kritéria ručního přijetí a vysvětluje, jak správně zapojit OmniDoc do pracovního postupu překladu dokumentů pro dvojjazyčné porovnání a přijetí.

Před předáním anotací PDF mnoho lidí přímo použije page.get_text() k exportu čistého textu pro překlad, archivaci nebo předání dalšímu recenzentovi. Tento text ale obvykle neobsahuje anotace. Některé extrakční metody také vloží komentáře doprostřed textu, čímž přeruší sémantiku; modifikační komentáře a citlivé poznámky v postranním panelu mohou chybět.

Tento článek je napsán pro vývojáře a vlastníky dokumentů, kteří potřebují pracovat s anotovanými PDF. Po přečtení pochopíte, proč jsou anotace nezávislé datové vrstvy, jak extrahovat text a anotace ve vrstvách, které okrajové případy je třeba řešit defenzivně a které akceptační body je nutné potvrdit ručně.

Všechny příklady v tomto článku používají syntetické vzorky. Kód byl ukázkově zkontrolován v izolovaném prostředí, ale to není zárukou všech skutečných souborů nebo výkonu produktu. Před zpracováním důležitých dokumentů si prosím uschovejte originály a zkontrolujte je podle hranic a přejímacích položek v textu.

Jak extrahovat anotované PDF před předáním? Závěr jednou větou

Zacházejte s textem a anotacemi jako se dvěma nezávislými datovými toky a extrahujte je samostatně a proveďte explicitní kontrolu zabezpečení obsahu anotací.

vaší situaciDoporučené postupydůvod
K exportu textu používejte pouze get_text()Neberte to jako kompletníVýchozí výstup obvykle neobsahuje anotace
Revizní komentáře recenzentů je třeba uchovatIterujte poznámky jednotlivě pomocí page.annots()Anotace jsou nezávislé objekty připojené ke stránce
Komentáře mohou obsahovat identifikační čísla a interní kódy.Porovnejte podle citlivých pravidel, označte redacted=True a nahraďte zástupným symbolemPoznámky k recenzi mohou obsahovat citlivá data
Stránka se otočíNejprve použijte page.rotation_matrix nebo page.derotation_matrix k transformaci souřadnicObdélník poznámky založený na neotočené stránce
Připraveno pro proces překladuNejprve vyčistěte značky formátovaného textu a po překladu je zkontrolujte ručněVyhněte se překladům obsahujícím kód

Proč jsou anotace nezávislé na datové vrstvě textu

Ve specifikaci PDF jsou proud obsahu stránky (Content Stream) a anotační slovník (Annots Array) strukturálně odděleny. Tělo se skládá z textových zobrazovaných pokynů; anotace jsou nezávislé objekty připojené ke stránce s vlastními souřadnicemi, typem a atributy obsahu. Metoda Page.annots() PyMuPDF vrací generátor, který prochází tímto nezávislým seznamem anotací místo proudu textu stránky.

To znamená, že nemůžete předpokládat, že veškerý text, který vidíte, lze extrahovat stejným způsobem.

Rozdíl mezi anotacemi třídy známky a třídy obsahu

  • Anotace značek (jako je zvýraznění a podtržení) neobsahují samotný text, ale zaznamenávají pouze oblast (čtverce/obdélníky) odpovídající původnímu textu. Skutečný text lze získat pouze vyhledáním textu pomocí souřadnic.
  • Anotace obsahu (jako poznámky, volný text) mají své vlastní obsahové řetězce a lze je číst přímo.
  • Pokud čtete annot.info["content"] přímo bez rozlišení typu, ztratíte původní kontext, na který odkazuje anotace třídy tagů, nebo vyvoláte výjimku, pokud je obsah prázdný.

Příklad syntézy: vrstvená extrakce a zachycení citlivých informací

Abychom demonstrovali správnou logiku zpracování, vytvořili jsme syntetický scénář obsahující tři typické anotace v kódu. Následující vstupy jsou ukázky vytvořené v kódu, nikoli ze skutečných souborů zákazníků, a slouží pouze pro účely vzdělávací ukázky.

Očekávaný výstup obsahuje tři strukturovaná pole:

  1. Fragment textu: Obsahuje pouze původní text stránky bez obsahu anotace.
  2. Seznam anotací: Každý záznam obsahuje typ, umístění, autora, čas a obsah (pokud existuje).
  3. Bezpečnostní značka: Pokud obsah anotace odpovídá přednastaveným citlivým pravidlům (jako je ID číslo, interní kód), záznam je označen jako redacted=True a obsah je nahrazen zástupným symbolem.

Tři typy hranic, které je třeba bránit

  • Prázdná anotace obsahu: Inkoustové (inkoustové) nebo grafické anotace vytvořené některými čtenáři nemají textové atributy. Přímý přístup k .info["content"] může mít za následek prázdný řetězec nebo Žádný, kód musí provádět obranné kontroly a nemůže předpokládat, že všechny anotace mají čitelný text.
  • Souřadnice otočené stránky: Po otočení stránky o 90 stupňů je obdélník poznámky stále založen na neotočené stránce. Pokud přímo použijete tyto souřadnice k oříznutí nebo umístění textu, poloha bude zcela zmatená a nejprve je třeba provést transformaci souřadnic.
  • Orphan Object: Pokud je dokument zavřen nebo stránka je znovu načtena během procesu procházení, aktuální objekt poznámky se okamžitě stane neplatným. Všechny operace čtení musí být dokončeny během životnosti jedné stránky.

Implementace Pythonu: bezpečné procházení a ověřování anotací

Příklad používá PyMuPDF k vytvoření testovacího PDF v paměti, demonstruje hierarchickou extrakci a základní maskovací logiku. Závislá knihovna je PyMuPDF (tj. balíček pymupdf). Spusťte jej v uzamčeném závislém prostředí. Pro úplný přístup k atributu annot musí být verze >=1.23.0. Tento kód neprovádí síťové operace ani zápis souborů, slouží pouze k demonstraci logiky.

import fitz  # PyMuPDF
import re

# 合成示例:仅在内存中构造,无需外部文件
def create_sample_pdf():
    doc = fitz.open()
    page = doc.new_page()
    # 插入正文
    page.insert_text((72, 72), "Confidential Project Alpha Report", fontsize=12)
    # 添加便签批注(含敏感信息模拟)
    page.add_text_annot((200, 72), "Reviewer: SSN 123-45-6789 approved.")
    # 添加高亮批注(无自身文本,关联正文)
    highlight = page.add_highlight_annot(fitz.Rect(72, 60, 250, 80))
    # 必须调用update()使info变更生效
    highlight.set_info(title="Editor", content="Check this term")
    highlight.update()
    return doc

def extract_with_safety(page, sensitive_pattern=r"\d{3}-\d{2}-\d{4}"):
    body_text = page.get_text("text")
    annotations = []

    # 显式遍历批注生成器
    for annot in page.annots():
        info = annot.info
        # 防御性获取内容,处理None或空字符串
        content = info.get("content", "") or ""

        # 边界处理:敏感词检测与脱敏
        is_sensitive = bool(re.search(sensitive_pattern, content))
        safe_content = "[REDACTED]" if is_sensitive else content

        annotations.append({
            "type": annot.type[1],
            "author": info.get("title", "Unknown"),
            "content": safe_content,
            "is_redacted": is_sensitive,
            # 注意:此为未旋转坐标系,若页面有旋转需配合rotation_matrix使用
            "rect": list(annot.rect)
        })
    return body_text, annotations

# 执行校验
doc = create_sample_pdf()
page = doc[0]
text, annots = extract_with_safety(page)

assert "SSN 123-45-6789" not in str(annots), "敏感信息未被拦截"
assert any(a["type"] == "Highlight" for a in annots), "标记类批注丢失"
assert len(text.strip()) > 0, "正文提取失败"
print(f"Extracted {len(annots)} annotations safely.")

Ve svém jádru je kód defenzivní programování: není důvěryhodná čistota obsahu anotací ani se nepředpokládá integrita typu anotace. Příkaz assert se používá k ověření očekávané logiky, ale toto je pouze ukázka a nepředstavuje úplnou záruku výkonu pro všechny varianty PDF.

Porovnání kategorií anotací

Typ anotaceZda přinést vlastní textJak získat obsahBody, které je třeba vzít v úvahu při předání
Zvýraznit, podtrhnoutNe, zaznamenávat pouze oblasti (čtyřkolky/obdélníky)Zkontrolujte text pomocí souřadnicJe třeba zachovat odpovídající kontext původního textu
Poznámky, volný textAno, přichází s vlastním řetězcem obsahučíst přímoZkontrolujte citlivý obsah
Inkoust, grafika, těsněníČasto bez atributu textuUdělejte obranný krátký hovorRučně potvrďte, zda se jedná o podpis nebo schvalovací pečeť

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

Automatická extrakce nemůže pokrýt všechny okrajové případy. Následující tabulka uvádí akceptační body, kterým je třeba věnovat pozornost během předávání, přičemž rozlišuje mezi rozsahem, který kód dokáže zpracovat, a scénáři, které vyžadují ruční zásah.

Pozorovat jevyZpracování na úrovni kóduLidská kontrola nebo rozhodování
Obsah komentáře je prázdný, ale ikona existujeTyp záznamu je Inkoust nebo Razítko, obsah je ponechán prázdnýPotvrďte, zda se jedná o podpis nebo schvalovací razítko, a rozhodněte se, zda chcete snímek snímku zachovat
Pozice komentáře přesahuje CropBoxSouřadnice jsou stále platné, ale vykreslení není vidětUrčete, zda se nejedná o opuštěnou anotaci zbylou z historie, kterou lze obvykle ignorovat.
Komentáře ve formátu RTF obsahují značky HTMLExtrahujte původní řetězec, ponechte štítkyPřed překladem vyčistěte značky nebo je převeďte na prostý text, abyste se vyhnuli překladům obsahujícím kód.
Jméno autora anotace je zkomolenéExtrahujte tak, jak je, žádné dohady o kódováníZkontrolujte metadata zdrojového souboru a ověřte, zda se jedná o název konkrétního kódování
Vnořené vlákno odpovědíPyMuPDF vrátí plochý seznamZnovu vytvořte strom dialogového okna na základě ParentID, jinak dojde ke ztrátě kontextu

Nelze použít: Toto řešení se nevztahuje na zašifrované soubory PDF bez zadání hesla, strukturálně poškozené soubory PDF a soubory, které k definování typů anotací používají nestandardní privátní rozšíření. V těchto situacích může skript tiše přeskočit nebo vyvolat výjimku C++ nízké úrovně, kterou je nutné potvrdit ručním otevřením zdrojového souboru pomocí profesionálních nástrojů.

Použijte kontrolní seznamy pro překlad dokumentů

Nejprve potvrďte pořadí stránek, umístění zdroje a integritu textu a poté odešlete stejný znecitlivěný vzorek do procesu překladu. Po překladu je ještě potřeba zkontrolovat, zda název, text a ilustrace správně odpovídají. Nemůžete jen zkontrolovat, zda je text hladký.

OmniDoc poskytuje portál pro překlad dokumentů ve více formátech a oficiální webové stránky zavádějí funkce OCR, glosář a dvojjazyčné porovnání. Pokud chce tým zahájit zpracování přímo ze souboru, lze tuto cestu vyhodnotit reálnými vzorky. Použijte prosím znecitlivěné soubory, k jejichž nahrávání máte oprávnění, a zkontrolujte výsledky podle zaškrtávacích položek v tomto článku. Není zde žádné tvrzení, že OmniDoc používá open source knihovny nebo interní algoritmy z tohoto článku, ani tento příklad nenahrazuje testování výkonu produktu.

Reference a další kroky

  1. Vyberte soubor historického projektu, který obsahuje smíšené typy anotací.
  2. Spusťte výše uvedený ověřovací skript a spočítejte podíl položek, které vyžadují ruční kontrolu.
  3. Pokud poměr překročí očekávání, přidejte do procesu předání krok předběžného zpracování namísto spoléhání se na následné nástroje, které poskytnou odpověď.

🎯 Která metoda je pro vás vhodná?

Pokud potřebujete pouze přeložit text

Text můžete přímo extrahovat, ale musíte potvrdit, zda v exportovaném obsahu nechybí nějaké anotace.

Pokud chcete dokument předat někomu jinému k archivaci

Zároveň si ponechte hlavní text a seznam poznámek a citlivý obsah označte jako necitlivý.

Pokud má váš soubor PDF otočené stránky

Nejprve proveďte transformaci souřadnic a poté použijte polohu poznámky k nalezení textu.

Pokud je soubor zašifrovaný nebo strukturálně poškozený

Toto řešení není použitelné. Otevřete zdrojový soubor pro potvrzení ručně pomocí profesionálních nástrojů.

❓ Často kladené otázky (FAQ)

1. Proč get_text() neobsahuje anotace?

Výchozí výstup obvykle obsahuje pouze tělo stránky. Anotace jsou objekty nezávislé na toku textu stránky a je třeba je procházet samostatně pomocí page.annots().

2. Lze číst text všech komentářů přímo?

nemůže. Anotace typu značky, jako je zvýraznění a podtržení, neobsahují samotný text a zaznamenávají pouze oblasti; inkoustové a grafické poznámky také nemusí mít žádné textové atributy a vyžadují obranný úsudek.

3. Proč je pozice stránky po otočení zmatená?

Anotační obdélník je založen na neotočené stránce. Pokud se použije přímo k umístění textu, způsobí chyby. Nejprve musíte použít page.rotation_matrix nebo page.derotation_matrix pro transformaci souřadnic.

4. Ztratí se vnořené odpovědi?

PyMuPDF vrací plochý seznam a pokud není strom dialogu rekonstruován na základě ParentID, kontext bude ztracen.

5. Lze tímto skriptem zpracovat zašifrované PDF?

Soubory PDF, které jsou zašifrovány a neposkytují heslo, nespadají do rozsahu tohoto řešení a vyžadují ruční potvrzení.

📝 Shrnutí

Anotace jsou nezávislou datovou vrstvou v PDF. Před předáním by měl být text a anotace extrahovány samostatně a poznámky by měly být zkontrolovány, zda neobsahují citlivý obsah. Automatizované skripty mohou pokrýt běžné případy, ale okrajové případy a konečné přijetí je stále třeba provádět ručně.

Vyzkoušejte to hned: Nahrajte dokument a začněte překládat při zachování původního rozvržení

Aktualizováno 2026-11-14