0Pricing
AI Engineering Academy · Leçon

Chargement des documents et extraction de texte

Chargez des PDF, des documents Word et des fichiers texte brut à l’aide de bibliothèques Python, nettoyez le texte extrait et préparez-le pour la segmentation et la création d’embeddings.

Chargement des documents et extraction de texte est une leçon AI Engineering Academy gratuite sur CoddyKit. Ceci est la leçon 1 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage AI Engineering Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours AI Engineering Academy comprend 4 leçons au total.

Pourquoi le chargement des documents n’est pas trivial

La première étape de tout pipeline RAG consiste à extraire le texte brut de vos documents. Cela semble simple, mais s’avère étonnamment complexe en pratique. Les fichiers PDF peuvent intégrer du texte sous forme de caractères, d’images ou d’un mélange des deux. Les documents Word contiennent des balises de mise en forme qu’il faut supprimer. Les pages HTML incluent des menus de navigation et des publicités en plus du contenu réel. Un chargeur robuste doit gérer tous ces cas et produire un texte propre et cohérent pour le découpage en fragments.

Charger des PDF avec pypdf

pypdf est la bibliothèque Python standard pour lire les fichiers PDF contenant du texte intégré. Elle extrait le texte page par page, en conservant les limites de pages d’origine, qui constituent des métadonnées précieuses. Toutefois, pypdf ne peut pas lire les PDF numérisés (images de texte) : ceux-ci nécessitent l’OCR. Extrayez toujours les numéros de page en même temps que le texte afin de pouvoir citer la page exacte dans vos citations RAG.

from pypdf import PdfReader

def load_pdf(file_path):
    reader = PdfReader(file_path)
    pages = []
    for page_num, page in enumerate(reader.pages, start=1):
        text = page.extract_text()
        if text and text.strip():  # skip blank pages
            pages.append({
                'text': text,
                'metadata': {
                    'source': file_path,
                    'page': page_num,
                    'doc_type': 'pdf'
                }
            })
    return pages

docs = load_pdf('annual_report.pdf')
print(f'Loaded {len(docs)} non-empty pages')

Charger des documents Word avec python-docx

Les fichiers Microsoft Word (.docx) stockent leur contenu au format XML. La bibliothèque python-docx analyse ce XML et expose les paragraphes, les tableaux et les titres sous forme d’objets Python. Extrayez séquentiellement le texte des paragraphes et capturez les niveaux de titre afin de préserver la structure du document : les titres de section constituent un contexte précieux qui améliore la qualité du découpage en fragments et de la récupération lorsqu’ils sont inclus avec le texte qu’ils introduisent.

from docx import Document

def load_docx(file_path):
    doc = Document(file_path)
    sections = []
    current_section = {'heading': '', 'text': ''}

    for para in doc.paragraphs:
        if para.style.name.startswith('Heading'):
            if current_section['text'].strip():
                sections.append(current_section.copy())
            current_section = {'heading': para.text, 'text': ''}
        else:
            current_section['text'] += para.text + '\n'

    if current_section['text'].strip():
        sections.append(current_section)

    return [{'text': f"{s['heading']}\n{s['text']}",
             'metadata': {'source': file_path, 'section': s['heading']}}
            for s in sections]

Charger des pages web et du HTML

Les pages HTML contiennent beaucoup de bruit : barres de navigation, pieds de page, bannières de consentement aux cookies et blocs publicitaires. Utilisez BeautifulSoup pour analyser le HTML et n’extraire que la zone de contenu principale. Ciblez des éléments comme <article>, <main> ou des classes CSS propres au contenu. Supprimez les balises script, style et nav avant d’extraire le texte afin d’éviter de polluer vos fragments avec du code JavaScript ou des éléments de menu.

import requests
from bs4 import BeautifulSoup

def load_url(url):
    response = requests.get(url, timeout=10)
    response.raise_for_status()

    soup = BeautifulSoup(response.text, 'html.parser')

    # Remove noise elements
    for tag in soup(['script', 'style', 'nav', 'footer', 'header', 'aside']):
        tag.decompose()

    # Try to find main content
    main = soup.find('article') or soup.find('main') or soup.find('body')
    text = main.get_text(separator='\n', strip=True)

    return [{'text': text, 'metadata': {'source': url, 'doc_type': 'html'}}]

Gérer les PDF numérisés avec l’OCR

Les PDF numérisés stockent les pages sous forme d’images, sans texte intégré. Pour extraire le texte, vous avez besoin de la reconnaissance optique de caractères (OCR). La bibliothèque pytesseract encapsule le moteur OCR Tesseract de Google. L’OCR est plus lent et moins précis que l’extraction de texte (précision de 80 à 95 % des caractères sur de bons scans), privilégiez donc toujours les PDF numériques lorsqu’ils sont disponibles. Indiquez dans les métadonnées que l’OCR a été utilisé afin de pouvoir examiner les extractions peu fiables.

import pytesseract
from pdf2image import convert_from_path

def load_scanned_pdf(file_path):
    # Convert PDF pages to PIL images
    pages_as_images = convert_from_path(file_path, dpi=300)
    results = []
    for page_num, img in enumerate(pages_as_images, start=1):
        text = pytesseract.image_to_string(img, lang='eng')
        results.append({
            'text': text,
            'metadata': {
                'source': file_path,
                'page': page_num,
                'ocr': True  # flag for quality review
            }
        })
    return results

Utiliser Unstructured pour tous les formats

La bibliothèque unstructured est un véritable couteau suisse pour le chargement de documents : elle prend en charge les PDF, les documents Word, Excel, PowerPoint, HTML, les e-mails et bien plus encore grâce à une API unifiée. Elle utilise des heuristiques pour identifier les éléments d’un document (titre, texte narratif, tableau, en-tête) et les renvoie sous forme d’objets structurés. Elle est particulièrement utile lorsque votre corpus contient des types de documents variés et que vous souhaitez disposer de métadonnées au niveau des éléments sans écrire d’analyseurs spécifiques à chaque format.

from unstructured.partition.auto import partition

def load_any_document(file_path):
    elements = partition(filename=file_path)
    docs = []
    for element in elements:
        docs.append({
            'text': str(element),
            'metadata': {
                'source': file_path,
                'element_type': type(element).__name__,
                'category': element.category
            }
        })
    return docs

# Works on .pdf, .docx, .pptx, .html, .eml, .xlsx
docs = load_any_document('presentation.pptx')

Nettoyage du texte après l’extraction

Le texte extrait brut est rarement propre. L’extraction de PDF produit souvent des coupures de lignes avec traits d’union dues à la mise en colonnes, des espaces superflus, des en-têtes de page répétés sur chaque page et des caractères spéciaux mal interprétés. Appliquez une chaîne de nettoyage : supprimez les espaces excessifs, réunissez les mots coupés par un trait d’union entre deux lignes, supprimez les en-têtes et pieds de page identifiés par correspondance de motifs, puis normalisez les caractères Unicode. Un texte propre améliore considérablement la cohérence des segments.

import re

def clean_text(text):
    # Rejoin hyphenated line breaks (PDF column artifacts)
    text = re.sub(r'-(\n)([a-z])', r'\2', text)
    # Normalize whitespace
    text = re.sub(r' +', ' ', text)
    text = re.sub(r'\n{3,}', '\n\n', text)
    # Remove page numbers standing alone on a line
    text = re.sub(r'^\d+$', '', text, flags=re.MULTILINE)
    # Strip leading/trailing whitespace from each line
    lines = [line.strip() for line in text.split('\n')]
    return '\n'.join(lines).strip()

Chargement depuis des bases de données et des API

Toutes les connaissances ne se trouvent pas dans des fichiers. Les bases de données internes, les systèmes CRM, les outils de gestion des tickets et les API REST sont également des sources. Chargez les lignes structurées d’une base de données en reliant les tables pertinentes et en concaténant les valeurs des champs dans des paragraphes en langage naturel que le modèle d’embeddings peut comprendre. Pour les API, récupérez les résultats paginés et sérialisez chaque enregistrement sous forme de document texte composé de paires clé-valeur.

import psycopg2

def load_from_database(conn_string, query):
    conn = psycopg2.connect(conn_string)
    cursor = conn.cursor()
    cursor.execute(query)
    columns = [desc[0] for desc in cursor.description]
    docs = []
    for row in cursor.fetchall():
        # Convert row to natural language text
        parts = [f'{col}: {val}' for col, val in zip(columns, row) if val]
        text = '\n'.join(parts)
        docs.append({'text': text, 'metadata': {'source': 'database'}})
    conn.close()
    return docs

Suivi de la provenance des documents

Chaque document chargé doit conserver des métadonnées de provenance tout au long de la chaîne : URL ou chemin du fichier source, titre du document, auteur, date de création et date de dernière modification. Ces métadonnées accompagnent chaque segment jusque dans la base vectorielle et apparaissent dans les citations du LLM. Sans provenance, vous ne pouvez pas indiquer aux utilisateurs d’où vient une réponse, mettre à jour des documents précis dans l’index ni filtrer la recherche selon les attributs de la source.

import os
from datetime import datetime

def load_pdf_with_provenance(file_path):
    from pypdf import PdfReader
    reader = PdfReader(file_path)
    stat = os.stat(file_path)
    base_metadata = {
        'source': file_path,
        'title': reader.metadata.get('/Title', os.path.basename(file_path)),
        'author': reader.metadata.get('/Author', 'Unknown'),
        'doc_type': 'pdf',
        'file_size_kb': stat.st_size // 1024,
        'loaded_at': datetime.utcnow().isoformat()
    }
    pages = []
    for i, page in enumerate(reader.pages, 1):
        text = page.extract_text()
        if text and text.strip():
            pages.append({'text': text, 'metadata': {**base_metadata, 'page': i}})
    return pages

Chargement par lots de grandes collections de documents

Lors de l’indexation de milliers de documents, chargez-les en parallèle à l’aide de concurrent.futures afin d’exploiter au maximum les ressources d’E/S et du CPU. Mettez en place un suivi de la progression et un journal des erreurs pour que les échecs de chargement ne suppriment pas silencieusement du contenu de votre index. Ne laissez jamais un seul fichier corrompu interrompre toute la tâche de chargement : interceptez les exceptions pour chaque document et passez au suivant.

from concurrent.futures import ThreadPoolExecutor, as_completed

def batch_load_documents(file_paths, max_workers=8):
    all_docs = []
    errors = []
    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        future_to_path = {
            executor.submit(load_pdf_with_provenance, p): p
            for p in file_paths
        }
        for future in as_completed(future_to_path):
            path = future_to_path[future]
            try:
                docs = future.result()
                all_docs.extend(docs)
                print(f'Loaded {len(docs)} pages from {path}')
            except Exception as e:
                errors.append({'path': path, 'error': str(e)})
    return all_docs, errors

Validation de la qualité du contenu chargé

Après le chargement, vérifiez que vous avez extrait un contenu pertinent. Contrôlez notamment : la longueur minimale du texte (ignorez les segments de moins de 50 caractères), la détection de la langue (si votre RAG est limité à l’anglais, filtrez les pages dans d’autres langues) et la détection de texte mal interprété (une forte proportion de caractères non ASCII peut indiquer un échec de l’OCR ou des problèmes d’encodage). Consignez des statistiques telles que le nombre de pages chargées, la longueur moyenne des pages et le taux d’erreur afin de repérer rapidement les problèmes de chargement.

def validate_documents(docs, min_length=100):
    valid = []
    skipped = 0
    for doc in docs:
        text = doc['text']
        if len(text) < min_length:
            skipped += 1
            continue
        # Check for high non-ASCII ratio (garbled OCR)
        non_ascii = sum(1 for c in text if ord(c) > 127)
        if non_ascii / max(len(text), 1) > 0.3:
            skipped += 1
            continue
        valid.append(doc)
    print(f'Valid: {len(valid)}, Skipped: {skipped}')
    return valid

Vérification rapide

Vérifiez votre compréhension des concepts d’ingénierie de l’IA présentés dans cette leçon.

Récapitulatif de la leçon

Dans cette leçon, vous avez découvert : les chargeurs propres à chaque format pour les PDF avec pypdf, les documents Word avec python-docx, le HTML avec BeautifulSoup et les documents numérisés avec l’OCR ; la bibliothèque unstructured comme chargeur unifié pour plusieurs formats ; ainsi que les bonnes pratiques de production, notamment le nettoyage du texte, les métadonnées de provenance, le chargement parallèle par lots et la validation du contenu. Nous allons maintenant aborder les stratégies de segmentation, qui déterminent la manière dont le texte récupéré s’intègre au contexte du modèle.

Questions Fréquemment Posées

La leçon « Chargement des documents et extraction de texte » est-elle gratuite ?

Oui — le texte complet de « Chargement des documents et extraction de texte » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours AI Engineering Academy, passe à CoddyKit PRO. Le cours AI Engineering Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Chargement des documents et extraction de texte » ?

Chargez des PDF, des documents Word et des fichiers texte brut à l’aide de bibliothèques Python, nettoyez le texte extrait et préparez-le pour la segmentation et la création d’embeddings. Tu pratiques AI Engineering Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer AI Engineering Academy ?

Aucune expérience préalable n'est requise. AI Engineering Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 1 sur 4.

Combien de temps prend la leçon « Chargement des documents et extraction de texte » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon AI Engineering Academy ?

Oui. Chaque leçon AI Engineering Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Chargement des documents et extraction de texte
  2. Stratégies de segmentation : fixe, par phrases ou récursive
  3. Indexer : créer et stocker les segments
  4. Interroger, récupérer et générer
← Retour à AI Engineering Academy