Aller au contenu principal

Extraction de tableaux et structure

Les tableaux : le point faible de l’OCR classique

L’extraction de tableaux est historiquement l’un des problèmes les plus difficiles en OCR. Les solutions traditionnelles comme Tesseract ne comprennent pas la notion de structure tabulaire : elles extraient le texte ligne par ligne, sans préserver les relations entre colonnes et rangées.

OCR 3 change fondamentalement la donne grâce à sa compréhension visuelle de la page.

Le paramètre table_format

Vous contrôlez le format de sortie des tableaux via le paramètre table_format :

import os
from mistralai import Mistral

client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])

# Format Markdown (recommandé pour la plupart des cas)
ocr_response = client.ocr.process(
    model="mistral-ocr-latest",
    document={
        "type": "document_url",
        "document_url": "https://exemple.com/rapport-financier.pdf"
    },
    table_format="markdown"
)

Les trois options

1. null (défaut) — Tableaux en ligne

Les tableaux sont intégrés directement dans le flux Markdown sans formatage tabulaire spécifique. Utile quand vous ne traitez pas de documents tabulaires.

2. "markdown" — Tableaux Markdown

Les tableaux sont rendus en format Markdown standard avec pipes :

| Produit | Quantité | Prix unitaire | Total |
|---------|----------|---------------|-------|
| Widget A | 100 | 12,50 € | 1 250 € |
| Widget B | 50 | 25,00 € | 1 250 € |
| **Total** | **150** | | **2 500 €** |

3. "html" — Tableaux HTML

Les tableaux sont rendus en HTML complet, préservant les fusions de cellules et la mise en forme avancée :

<table>
  <thead>
    <tr>
      <th>Produit</th>
      <th>Quantité</th>
      <th>Prix unitaire</th>
      <th>Total</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Widget A</td>
      <td>100</td>
      <td>12,50 €</td>
      <td>1 250 €</td>
    </tr>
  </tbody>
</table>

Quand utiliser quel format ?

  • Markdown : pour l’indexation RAG, la recherche, l’affichage dans un éditeur Markdown
  • HTML : pour les tableaux complexes avec cellules fusionnées, ou pour l’intégration web
  • null : quand les tableaux ne sont pas importants dans votre workflow

Extraction et parsing des tableaux

Voici un script complet pour extraire les tableaux et les convertir en données structurées :

import os
import re
import json
from mistralai import Mistral

client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])

def extraire_tableaux_markdown(markdown: str) -> list[list[list[str]]]:
    """Extrait les tableaux Markdown et les convertit en listes."""
    tableaux = []
    lignes = markdown.split("\n")
    tableau_courant = []
    dans_tableau = False

    for ligne in lignes:
        if "|" in ligne and ligne.strip().startswith("|"):
            # Ignorer la ligne de séparation (|---|---|)
            if re.match(r"^\|[\s\-:|]+\|$", ligne.strip()):
                continue
            cellules = [
                c.strip() for c in ligne.strip().strip("|").split("|")
            ]
            tableau_courant.append(cellules)
            dans_tableau = True
        else:
            if dans_tableau and tableau_courant:
                tableaux.append(tableau_courant)
                tableau_courant = []
            dans_tableau = False

    if tableau_courant:
        tableaux.append(tableau_courant)

    return tableaux


# Extraction OCR avec tableaux Markdown
ocr_response = client.ocr.process(
    model="mistral-ocr-latest",
    document={
        "type": "document_url",
        "document_url": "https://exemple.com/facture.pdf"
    },
    table_format="markdown"
)

# Parcours des pages et extraction des tableaux
for page in ocr_response.pages:
    tableaux = extraire_tableaux_markdown(page.markdown)
    for i, tableau in enumerate(tableaux):
        print(f"Page {page.index + 1}, Tableau {i + 1}:")
        print(json.dumps(tableau, indent=2, ensure_ascii=False))

Conversion en DataFrame pandas

Pour une analyse plus poussée, convertissez directement en DataFrame :

import pandas as pd

def tableaux_vers_dataframes(markdown: str) -> list[pd.DataFrame]:
    """Convertit les tableaux Markdown en DataFrames pandas."""
    tableaux = extraire_tableaux_markdown(markdown)
    dataframes = []

    for tableau in tableaux:
        if len(tableau) < 2:
            continue
        en_tetes = tableau[0]
        donnees = tableau[1:]
        df = pd.DataFrame(donnees, columns=en_tetes)
        dataframes.append(df)

    return dataframes

# Utilisation
for page in ocr_response.pages:
    dfs = tableaux_vers_dataframes(page.markdown)
    for df in dfs:
        print(df.to_string())
        print()

Gestion des tableaux complexes

Pour les tableaux avec cellules fusionnées ou mises en page irrégulières, préférez le format HTML et utilisez BeautifulSoup :

from bs4 import BeautifulSoup
import pandas as pd

ocr_response = client.ocr.process(
    model="mistral-ocr-latest",
    document={
        "type": "document_url",
        "document_url": "https://exemple.com/rapport-complexe.pdf"
    },
    table_format="html"
)

for page in ocr_response.pages:
    soup = BeautifulSoup(page.markdown, "html.parser")
    tables = soup.find_all("table")

    for table in tables:
        df = pd.read_html(str(table))[0]
        print(df)

Points clés à retenir

  • Le paramètre table_format contrôle le rendu des tableaux (null, markdown, html)
  • Le format Markdown convient à la majorité des cas d’usage
  • Le format HTML préserve les cellules fusionnées et la mise en forme avancée
  • Les tableaux extraits peuvent être convertis en DataFrames pandas pour l’analyse
  • OCR 3 reconstruit fidèlement la structure tabulaire, même sur des mises en page complexes