Headers, footers et pagination
Extraction des en-têtes et pieds de page
Depuis la version OCR 2512 (décembre 2025), le modèle OCR 3 peut extraire séparément les en-têtes (headers) et pieds de page (footers) de chaque page. Cette fonctionnalité est particulièrement utile pour les documents formels : contrats, rapports annuels, documents réglementaires.
Pourquoi séparer headers et footers ?
Dans un workflow de traitement documentaire, les en-têtes et pieds de page posent un problème récurrent :
- Ils se répètent sur chaque page (nom de l’entreprise, numéro de page, date)
- Ils polluent le contenu principal lors de l’indexation
- Ils créent du bruit dans les résultats de recherche RAG
- Mais ils contiennent parfois des métadonnées utiles (version du document, classification)
En les extrayant séparément, vous pouvez décider de les inclure ou non selon votre cas d’usage.
Accéder aux headers et footers
Les champs header et footer sont disponibles directement dans la réponse de chaque page :
import os
from mistralai import Mistral
client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])
ocr_response = client.ocr.process(
model="mistral-ocr-latest",
document={
"type": "document_url",
"document_url": "https://exemple.com/contrat.pdf"
}
)
for page in ocr_response.pages:
print(f"--- Page {page.index + 1} ---")
if page.header:
print(f"En-tête : {page.header}")
print(f"Contenu : {page.markdown[:100]}...")
if page.footer:
print(f"Pied de page : {page.footer}")
print()
Gestion de la pagination
Numérotation des pages
Chaque page est indexée à partir de 0. Pour des documents multi-pages, vous pouvez reconstruire la pagination :
def extraire_avec_pagination(ocr_response) -> dict:
"""Extrait le contenu en préservant la pagination."""
document = {
"nombre_pages": len(ocr_response.pages),
"pages": []
}
for page in ocr_response.pages:
page_data = {
"numero": page.index + 1,
"contenu": page.markdown,
"header": page.header or "",
"footer": page.footer or "",
"dimensions": {
"largeur": page.dimensions.width if page.dimensions else None,
"hauteur": page.dimensions.height if page.dimensions else None,
},
"nombre_images": len(page.images) if page.images else 0,
}
document["pages"].append(page_data)
return document
Dimensions des pages
Les dimensions sont retournées en points PDF (1 point = 1/72 pouce). Les formats courants :
- A4 : 595 x 842 points
- Letter : 612 x 792 points
- A3 : 842 x 1191 points
for page in ocr_response.pages:
if page.dimensions:
largeur_cm = page.dimensions.width * 2.54 / 72
hauteur_cm = page.dimensions.height * 2.54 / 72
print(f"Page {page.index + 1}: {largeur_cm:.1f} x {hauteur_cm:.1f} cm")
Filtrer le contenu principal
Pour vos pipelines RAG, vous voudrez souvent exclure les headers et footers répétitifs :
def contenu_principal(ocr_response) -> str:
"""Extrait uniquement le contenu principal, sans headers/footers."""
parties = []
for page in ocr_response.pages:
contenu = page.markdown
# Optionnel : retirer les headers/footers du markdown
# s'ils sont inclus dans le contenu principal
if page.header and contenu.startswith(page.header):
contenu = contenu[len(page.header):].strip()
if page.footer and contenu.endswith(page.footer):
contenu = contenu[:-len(page.footer)].strip()
parties.append(contenu)
return "\n\n".join(parties)
Extraction des métadonnées depuis les footers
Les pieds de page contiennent souvent des informations utiles :
import re
def extraire_metadonnees_footer(ocr_response) -> dict:
"""Extrait les métadonnées depuis les pieds de page."""
metadonnees = {
"numeros_page": [],
"dates": [],
"versions": [],
"classifications": [],
}
for page in ocr_response.pages:
footer = page.footer or ""
# Recherche de numéro de page
match_page = re.search(r"(\d+)\s*/\s*(\d+)", footer)
if match_page:
metadonnees["numeros_page"].append(
f"{match_page.group(1)}/{match_page.group(2)}"
)
# Recherche de date
match_date = re.search(r"\d{2}/\d{2}/\d{4}", footer)
if match_date:
metadonnees["dates"].append(match_date.group())
# Recherche de version
match_version = re.search(r"v(?:ersion)?\s*(\d+\.?\d*)", footer, re.I)
if match_version:
metadonnees["versions"].append(match_version.group(1))
# Classification (Confidentiel, Public, etc.)
for classification in ["confidentiel", "public", "interne", "secret"]:
if classification in footer.lower():
metadonnees["classifications"].append(classification)
return metadonnees
Traitement par plages de pages
Pour les documents volumineux, vous pouvez vouloir traiter uniquement certaines pages :
def extraire_plage(ocr_response, debut: int, fin: int) -> str:
"""Extrait le contenu d'une plage de pages (1-indexé)."""
parties = []
for page in ocr_response.pages:
numero = page.index + 1
if debut <= numero <= fin:
parties.append(page.markdown)
return "\n\n---\n\n".join(parties)
# Extraire les pages 5 à 10
contenu_partiel = extraire_plage(ocr_response, 5, 10)
Points clés à retenir
- Les headers et footers sont extraits séparément depuis OCR 2512
- Filtrez-les pour éviter le bruit dans vos pipelines RAG
- Les dimensions de page sont en points PDF (72 points = 1 pouce)
- Les footers contiennent souvent des métadonnées utiles (version, date, classification)
- Traitez par plages de pages pour les documents volumineux