La même ligne de texte est divisée en plus de dix travées par PyMuPDF ? Ceci détermine s'il doit être fusionné

PyMuPDF divise la même ligne de mots en plus d'une douzaine de travées. La plupart du temps, la police, la taille ou le style de police ont changé, pas nécessairement la segmentation. Cet article explique comment distinguer les changements de style et les limites de paragraphe, et donne des exemples de logique de fusion et de formulaire d'acceptation pour éviter de découper une phrase lors de la traduction.

Lorsque vous utilisez extractDICT() de PyMuPDF pour extraire du texte PDF, vous constaterez peut-être qu'une phrase cohérente est découpée en sept, huit span ou plus dans le résultat renvoyé. Il ne s'agit généralement pas d'une erreur d'analyse, mais d'un véritable reflet de la structure sous-jacente du PDF : le changement de police, les changements de couleur ou les ajustements de style locaux peuvent interrompre le flux du texte lors du rendu.

Si ce « découpage de style » est confondu avec une « segmentation de paragraphe », un nettoyage, une traduction ou une récupération ultérieure entraînera facilement des erreurs de segmentation de phrases. Cet article explique comment distinguer les changements de style des limites de paragraphe, donne un exemple fusionné de logique de fusion et fournit un formulaire d'acceptation pour vous aider à éviter de découper une phrase.

Une ligne de texte dans le PDF est divisée en plusieurs plages. Faut-il les fusionner ? Conclusion en une phrase

Lorsqu'il y a plusieurs span dans le même line et que les coordonnées y sont les mêmes, il s'agit principalement de la police, de la taille de la police ou du changement de couleur, qui peuvent être épissés en toute sécurité ; la limite du paragraphe doit être basée sur la structure de block et line, et non sur le nombre de span.

votre situationPratiques recommandéesraison
Plusieurs travées au sein de la même ligne ont les mêmes coordonnées ySpan d'épissage sécurisé.textPrincipalement changement de police ou de couleur
Il y a un écart horizontal évident entre les travéesVérifiez l'espacement des bbox et insérez des espaces ou des tabulations si nécessairePeut être un caractère de tabulation ou un résidu de saut de colonne, nécessite des règles
La différence entre les coordonnées y des travées au sein d'une même ligne dépasse 10 % de la taille de la police.Conserver la structure de travée d'origine sans fusionnerPeut être des formules en ligne ou des indices
L'étendue d'un seul mot et la bbox ne sont pas ordonnéesMarquer comme faible qualité, convertir en manuel ou OCRManque de base fiable pour le tri et le regroupement
Texte sémantiquement continu à travers les blocsUn jugement contextuel est requis et la fusion automatique n’est pas effectuée.Il peut s'agir d'un fragment de pagination

Clarifiez d'abord la relation hiérarchique entre Block, Line et Span

Structure du dictionnaire de PyMuPDF

La sortie du dictionnaire de PyMuPDF suit strictement la structure de flux de contenu du PDF, et la hiérarchie de l'extérieur vers l'intérieur est la suivante :

  • block : Une zone de composition indépendante sur la page, comme un paragraphe de texte, une cellule de tableau ou une légende.
  • line : ligne unique de texte visuel à l'intérieur de block.
  • span : line est une séquence interne de caractères consécutifs avec la même police, la même taille, la même couleur et le même style.

Pour plus de descriptions des champs de chaque couche, veuillez vous référer à Documentation officielle de PyMuPDF TextPage.

Pourquoi le changement de style génère-t-il un nouveau span ?

Tant qu'il y a du gras, de l'italique, un changement de couleur ou un remplacement de police au milieu d'une ligne de texte (par exemple, les caractères chinois sont mélangés avec l'anglais et les chiffres), un nouveau span sera généré. Ces span appartiennent au même line et partagent la même ligne de base et la même position verticale.

Que faut-il regarder au niveau des limites des paragraphes

La vraie fin d'un paragraphe est marquée par la fin de la liste line et le début d'un nouveau block, et non par le numéro de span. Confondre les deux peut entraîner des problèmes pratiques : par exemple, "Conseil important" est reconnu par erreur comme deux phrases distinctes, ce qui empêche la mémoire de traduction de faire correspondre le terme complet.

Exemple de synthèse : sortie correcte et cas extrêmes

Corriger le résultat

Pour illustrer le problème, nous construisons un scénario synthétique. Supposons qu'il y ait une ligne de texte dans le PDF d'entrée : "Veuillez noter : le système redémarrera dans 5 minutes." Parmi eux, "Veuillez noter :" utilise une police en gras, "le système redémarrera dans 5 minutes" revient à la police Song.

La sortie extractDICT() correcte doit contenir quatre span sous un objet line. Les bbox de chaque span se chevauchent fortement dans la direction verticale et les coordonnées y de origin sont fondamentalement cohérentes. Ces quatre fragments sont assemblés pour former une unité sémantique complète.

Entrée de mauvaise qualité

Une situation d'erreur typique est que le PDF numérisé n'a pas été traité par OCR ou que le générateur de PDF écrit chaque caractère chinois comme un objet texte distinct. Dans ce cas, extractDICT() peut renvoyer des dizaines de span à un seul mot, et il peut y avoir de petits écarts ou des chevauchements irréguliers entre leurs bbox.

Cette situation ne peut pas être résolue simplement par concaténation de chaînes car il n’existe aucune base fiable pour le tri et le regroupement. Il est plus sûr de marquer la page comme « données structurées de mauvaise qualité » et de l'envoyer à une relecture manuelle ou à un processus OCR dédié plutôt que de forcer une fusion.

Logique de fusion Span basée sur des caractéristiques géométriques

Exemple de code

L'exemple Python suivant montre comment émuler la structure de sortie de extractDICT() en mémoire et implémenter une fonction de fusion sécurisée entre homologues. Remarque : Cet exemple construit des données synthétiques uniquement à partir de la mémoire et ne lit aucun fichier PDF réel. Il est uniquement utilisé pour vérifier la logique de l'algorithme de fusion.

Pour une utilisation réelle, veuillez confirmer que la version PyMuPDF prend en charge la méthode extractDICT (1.23.x et supérieur recommandé) et exécutez-la dans votre propre environnement de dépendances verrouillé.

# 合成示例:演示同行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)}"

Précautions avant utilisation

  • Une valeur de 2,0 pour y_tolerance est uniquement un exemple synthétique de paramètre et ne constitue pas une norme industrielle.
  • Dans les projets réels, cette valeur peut être calculée dynamiquement en fonction de la taille moyenne de la police du document ; si line lui-même a été correctement divisé, il n'est généralement pas nécessaire de procéder à une vérification supplémentaire des coordonnées y.
  • Les exemples de cet article représentent uniquement des démonstrations au niveau du code et ne représentent pas une garantie de tous les fichiers réels ou effets du produit.

📊 Comparaison de base

Le tableau suivant compare plusieurs méthodes de traitement et indique si elles conviennent à la fusion automatique en fonction de la situation observée, sur la base des règles d'acceptation ci-dessus.

Situation observéeMéthode de traitementEst-il adapté à la fusion automatique ?
Les coordonnées y des travées au sein d'une même ligne sont cohérentesÉpissage sécuriséOui
Il y a un écart horizontal évident entre les travéesInsérer des espaces ou des tabulations après avoir vérifié l'espacementSoyez prudent et avez besoin de règles
Les formules en ligne, les exposants et les indices entraînent de grandes différences dans les coordonnées yConserver la structure de travée d'origineNon
L'étendue d'un seul mot et la bbox ne sont pas ordonnéesSignaler une mauvaise qualité, convertir en manuel ou OCRNon
Texte sémantiquement continu à travers les blocsJugement basé sur le contexteNon, une assistance PNL est requise

Critères d'acceptation et limites de révision manuelle

Observer les phénomènesRaisons possiblesdécision de traitementS'il faut appliquer la fusion automatique
Plusieurs travées au sein de la même ligne ont les mêmes coordonnées yChangement de police/couleurSpan d'épissage sécurisé.textOui
Il y a un écart horizontal évident entre les travées (>largeur de l'espace)Caractères de tabulation et résidus de colonneVérifiez l'espacement des bbox, insérez des espaces ou des tabulationsSoyez prudent et avez besoin de règles
Différence de coordonnées y au sein d'une même ligne > taille de police 10 %Formules en ligne, exposants et indicesConserver la structure de travée d'origine sans fusionnerNon
L'étendue d'un seul mot et la bbox ne sont pas ordonnéesPDF numérisé ou endommagéMarquer comme faible qualité, convertir en manuel ou OCRNon
Continuité sémantique du texte entre les blocsSaut de pageLa fusion entre blocs nécessite un jugement contextuelNon, une assistance PNL est requise

Ce tableau ne couvre que la vérification structurelle au niveau de la démonstration de code, et l'effet de bout en bout doit être combiné avec des modèles de langage ou un échantillonnage manuel. La fusion automatique ne doit pas être utilisée pour les documents sensibles au format tels que les contrats juridiques, les dossiers médicaux, etc., sauf vérification par un expert du domaine.

Avant utilisation, veuillez préparer vous-même le PDF du test de désensibilisation, exécutez page.get_text("dict", sort=True) pour exporter JSON, puis vérifiez chaque élément.

Utilisé pour vérifier avant la traduction du document

Vérifiez d’abord l’ordre des pages, l’emplacement de la source et l’intégrité du texte, puis soumettez le même échantillon désensibilisé au processus de traduction. Après la traduction, vous devez encore vérifier si le titre, le texte et les illustrations correspondent correctement, et pas seulement si le texte est fluide.

OmniDoc (portail produit) fournit un portail de traduction de documents multiformat et le site officiel présente des fonctions d'OCR, de glossaire et de comparaison bilingue. Pour les équipes qui souhaitent travailler directement à partir des fichiers, il s’agit d’une voie qui mérite d’être évaluée avec des échantillons réels. Veuillez utiliser les fichiers désensibilisés que vous êtes autorisé à télécharger et utilisez les éléments de vérification de cet article pour examiner les résultats. Rien ne prétend ici qu'OmniDoc utilise les bibliothèques open source ou les algorithmes internes de cet article, et l'exemple ne remplace pas non plus les tests de performances du produit.

🎯 Quelle méthode vous convient ?

Si vous souhaitez simplement organiser le texte sur la même ligne

  • Regroupez par line et épissez en toute sécurité span.text lorsque les coordonnées y sont cohérentes.

Si vous rencontrez des formules en ligne ou des exposants

  • Conserver la structure span d'origine sans fusionner.

Si vous traitez des scans ou des PDF comportant de nombreux mots composés d'un seul mot

  • Marquez d'abord comme mauvaise qualité, puis transférez vers une relecture manuelle ou un processus OCR dédié.

Si vous souhaitez effectuer une traduction multi-blocs ou multi-pages

  • Sur la base d'un jugement contextuel, il n'est pas approprié de fusionner directement et automatiquement.

❓ Questions fréquemment posées (FAQ)

1. Une ligne de texte est divisée en plusieurs étendues. Faut-il procéder à une segmentation ?

Pas nécessairement, cela est principalement dû à des changements de police, de taille ou de couleur. Les span au sein du même line partagent la même ligne de base et la même position verticale.

2. Que dois-je lire à la fin du paragraphe ?

Vérifiez si la liste line se termine et qu'un nouveau block commence, pas le numéro de span.

3. La concaténation de chaînes peut-elle être utilisée pour résoudre le problème de l'étendue d'un seul mot ?

Non recommandé. De tels cas ne disposent pas d’une base fiable pour le tri et le regroupement, et il est plus prudent de les signaler comme étant de mauvaise qualité et de les transmettre à un processus manuel ou OCR.

4. À quel point y_tolerance doit-il être défini lors de la fusion ?

Le 2.0 dans l’exemple est uniquement un exemple de paramètre synthétique et ne constitue pas une norme industrielle. Les éléments réels peuvent être calculés dynamiquement en fonction de la taille de police moyenne ou faire directement confiance au regroupement de line.

5. La fusion automatique peut-elle être utilisée dans les contrats juridiques ?

Ne convient pas sauf vérification par des experts du domaine.

📝Résumé

La clé pour juger si span peut être fusionné est d'examiner d'abord la structure de line et block, puis d'examiner la position géométrique. Lorsque vous rencontrez des formules, des documents numérisés ou une sémantique de blocs croisés, il est préférable de les conserver tels quels ou de les convertir manuellement plutôt que de les assembler de force.

Essayez-le maintenant : téléchargez le document pour lancer la traduction, en conservant la mise en page d'origine.

Mis à jour le 2026-11-15