Skip to content

Extraction et nettoyage de texte depuis des PDF

Impossible d’ouvrir un PDF avec un simple open() : son contenu est structuré en objets de mise en page, pas en texte brut. La bibliothèque pypdf fait ce travail d’extraction.

from pypdf import PdfReader
reader = PdfReader("runbooks/rollback.pdf")
texte = reader.pages[0].extract_text()
print(texte.split("\n"))
['CloudOps Interne - Procedure de rollback de deploiement',
'Procedure de rollback de deploiement',
'Tout deploiement en production doit pouvoir etre annule (rollback) en moins de 10 minutes, via la reactivation',
'automatique de la version precedente du pipeline CI/CD.',
...
'Document confidentiel - Page 1']

Des lignes parasites, réelles et répétitives

Section titled “Des lignes parasites, réelles et répétitives”

La première ligne (CloudOps Interne - Procedure de rollback de deploiement) est un en-tête répété sur chaque page ; la dernière (Document confidentiel - Page 1) est un pied de page. Aucune des deux n’apporte d’information utile à un système de question-réponse — pire, les conserver dilue le contenu réellement pertinent et pourrait fausser une recherche par similarité.

def extract_clean_text(pdf_path):
reader = PdfReader(pdf_path)
pages_nettoyees = []
for page in reader.pages:
lignes = page.extract_text().split("\n")
pages_nettoyees.append("\n".join(lignes[1:-1])) # retire 1ere et derniere ligne
return "\n".join(pages_nettoyees)

lignes[1:-1] retire systématiquement la première et la dernière ligne de chaque page — une heuristique simple, qui suppose une mise en page cohérente (vraie ici, car les 5 documents partagent le même gabarit). Sur une documentation réelle plus hétérogène, un nettoyage plus robuste (expressions régulières ciblant le texte répété, détection automatique de motifs récurrents) serait nécessaire.

Données réelles, nettoyage obligatoire : c’est une constante de tout projet NLP appliqué à des documents produits pour des humains (PDF, pages web, exports Word) plutôt que pour des machines. Le temps passé à nettoyer dépasse souvent celui passé à modéliser.

chunks, sources = [], []
for filename in sorted(os.listdir("runbooks")):
texte = extract_clean_text(os.path.join("runbooks", filename))
chunks.append(texte)
sources.append(filename)
astreinte.pdf: 827 caracteres
escalade.pdf: 796 caracteres
failover-bdd.pdf: 934 caracteres
rollback.pdf: 749 caracteres
sauvegardes.pdf: 756 caracteres

Chaque document devient ici un chunk unique (une unité de recherche) — un choix simple qui convient à des documents courts comme ces runbooks ; un corpus plus long découperait généralement chaque document en plusieurs chunks (par section, ou par fenêtre de mots avec chevauchement).

👉 Embeddings et recherche sémantique


Junior TSAFACK – 12/09/2026