Un humain lit peut-être cinquante documents par jour. Une machine, elle, peut en parcourir des millions. Le seul vrai obstacle, ce n'est pas la vitesse : c'est la compréhension. Pour qu'un programme « comprenne » un texte, il doit d'abord réussir une tâche que ton cerveau fait sans réfléchir : repérer qu'« Emmanuel Macron » est une personne, que « Bruxelles » est un lieu, et que « la Commission européenne » est une organisation. Cette tâche s'appelle la reconnaissance d'entités nommées, ou NER pour Named Entity Recognition. Dans ce tutoriel, on va l'implémenter en quelques lignes avec spaCy, la bibliothèque de traitement du langage naturel la plus utilisée en production aujourd'hui.
Pourquoi le NER change la donne
Prends un exemple concret. Imagine que tu collectes des milliers d'articles de presse. Tu veux savoir quelles entreprises sont citées, par qui, et dans quel pays. Lire les articles un par un prendrait des semaines. Avec le NER, tu extrais automatiquement la liste des personnes, des organisations et des lieux en quelques secondes, et tu peux ensuite compter, croiser, cartographier.
Le NER est partout, souvent sans que tu le remarques. Les moteurs de recherche l'utilisent pour indexer des faits et répondre à des questions du type « qui a fondé telle entreprise ». Les outils de veille s'en servent pour détecter les mentions d'une marque dans la presse et sur les réseaux. Les assistants vocaux le mobilisent pour comprendre « réserve un vol pour Paris ». Et les banques ou les hôpitaux l'appliquent pour anonymiser automatiquement des documents sensibles en masquant noms et lieux.
Ce qui rend le NER si utile, c'est qu'il transforme du texte libre — difficile à exploiter — en données structurées, faciles à compter et à croiser. Une fois que tu sais extraire des entités, un océan de cas d'usage s'ouvre à toi, bien au-delà du simple « analyser un texte ».
Pourquoi spaCy plutôt qu'un autre outil ? Parce que spaCy est pensé pour la production : il est rapide, robuste, et son pipeline regroupe tout ce qu'il faut — tokenisation, étiquetage grammatical, lemmatisation et reconnaissance d'entités — derrière une API simple et cohérente. Là où d'autres bibliothèques te demandent de bricoler des assemblages, spaCy te donne un objet unique, le Doc, qui contient toutes les annotations. Une fois que tu sais charger un modèle et parcourir cet objet, tu sais déjà faire 80 % du travail.
Comprendre le pipeline de spaCy
Avant de coder, un peu de vocabulaire. Un pipeline, en traitement du langage, est une succession d'étapes qui transforment un texte brut en un document annoté. Quand tu appelles nlp(texte), spaCy exécute ces étapes dans l'ordre :
- La tokenisation : le texte est découpé en tokens, c'est-à-dire en mots, signes de ponctuation et nombres.
- Le tagger : chaque token reçoit une étiquette grammaticale fine (verbe, nom, déterminant...).
- Le parser : spaCy analyse la structure de la phrase et les relations de dépendance entre les mots.
- Le NER : enfin, les groupes de tokens qui forment des entités nommées sont détectés et étiquetés.
Chaque étape s'appuie sur la précédente : une tokenisation approximative fausserait tout le reste. La bonne nouvelle, c'est que tu n'as pas à te soucier de cette mécanique interne. Tu charges un modèle, tu lances nlp(), et le Doc que tu récupères contient déjà toutes les annotations.
Prérequis : installer spaCy et le modèle français
On commence par installer le paquet Python, puis on télécharge un modèle de langue. Un modèle, c'est un ensemble de poids pré-entraînés : il contient le vocabulaire, les règles et les statistiques qui permettent d'étiqueter le texte. Pour le français, spaCy propose des modèles de plusieurs tailles, du plus léger au plus complet.
# Installation du paquet
pip install spacy
# Téléchargement du modèle français « small » (léger et rapide)
python -m spacy download fr_core_news_sm- fr_core_news_sm : le modèle léger (small), rapide, parfait pour débuter et pour du prototypage.
- fr_core_news_md : le modèle medium, avec des vecteurs de mots, utile pour la similarité sémantique.
- fr_core_news_lg : le modèle large, plus précis mais plus lent et plus gourmand en mémoire.
Pour ce tutoriel, le modèle « sm » suffit largement : il est rapide et contient déjà le NER. Si tu utilises un environnement virtuel, pense à l'activer avant d'installer, histoire de ne pas polluer ton Python système.
Charger le pipeline et analyser un premier texte
Charger le modèle et analyser un texte tient en deux lignes. L'objet renvoyé par nlp() s'appelle un Doc : c'est ton texte annoté, une séquence de tokens enrichis de toutes les informations du pipeline.
import spacy
# On charge le modèle français une seule fois (opération un peu coûteuse)
nlp = spacy.load("fr_core_news_sm")
texte = "Emmanuel Macron et Ursula von der Leyen se sont rencontrés à Bruxelles, au siège de la Commission européenne."
# La ligne qui fait tout : elle traverse le pipeline complet
doc = nlp(texte)Le chargement du modèle est l'opération la plus lente du script : fais-le une seule fois, idéalement au démarrage, puis réutilise l'objet nlp pour tous tes textes. C'est un réflexe important dès que tu traites de gros volumes.
Tokeniser et étiqueter chaque mot
Chaque mot du Doc est un Token, un objet qui expose sa nature grammaticale et sa forme de base. C'est la brique élémentaire sur laquelle tout le reste se construit. On commence par regarder ce que spaCy a trouvé :
for token in doc:
print(f"{token.text:26} -> {token.pos_:8} | lemme : {token.lemma_}")La propriété pos_ donne la catégorie grammaticale du mot. Voici les étiquettes que tu croiseras le plus souvent :
- PROPN : un nom propre (Emmanuel, Macron, Bruxelles...).
- VERB : un verbe (rencontrer, être, avoir...).
- AUX : un auxiliaire (être, avoir utilisés comme auxiliaires).
- NOUN : un nom commun (siège, commission...).
- ADP : une préposition (à, de, dans...).
- DET : un déterminant (le, la, un, une...).
- ADJ : un adjectif, et PRON : un pronom.
Remarque la distinction entre nom propre et nom commun : c'est précisément le signal qui aide spaCy à reconnaître les entités un peu plus loin. Le lemme, lui, est la forme canonique du mot — « rencontrés » devient « rencontrer », « sont » devient « être ». C'est précieux pour normaliser du texte avant de faire des statistiques : compter des occurrences de « être » sans distinguer « suis », « est », « sont » et « étaient », par exemple.
Repérer les entités nommées
Le clou du spectacle : la reconnaissance d'entités nommées. Chaque entité détectée est exposée dans doc.ents, avec son texte et son étiquette. On itère et on affiche :
for ent in doc.ents:
print(f"{ent.text:26} -> {ent.label_} ({spacy.explain(ent.label_)})")Le résultat, pour notre phrase, ressemble à ceci : « Emmanuel Macron » est détecté comme PERSON, « Ursula von der Leyen » comme PERSON, « Bruxelles » comme GPE (une entité géopolitique, c'est-à-dire un pays ou une ville) et « la Commission européenne » comme ORG (une organisation). Le modèle a compris, sans qu'on lui donne aucune règle, que ces groupes de mots désignent des choses nommables.
Derrière cette apparente simplicité, le modèle combine deux types de signaux : des indices internes au mot (une majuscule, une position dans la phrase) et le contexte (le mot qui précède, le mot qui suit). C'est ce mélange qui lui permet de distinguer « Apple » l'entreprise de « apple » le fruit, selon la phrase.
Traduire les étiquettes avec spacy.explain()
spacy.explain() traduit chaque étiquette en clair. C'est l'outil de secours à garder sous la main quand tu tombes sur un code inconnu. Voici les étiquettes les plus courantes du modèle français :
- PERSON : une personne réelle ou fictive.
- ORG : une organisation, une entreprise, une institution.
- GPE : une entité géopolitique (pays, ville, région).
- LOC : un lieu qui n'est pas géopolitique (montagne, fleuve, bâtiment).
- DATE et TIME : des expressions de date et d'heure.
- MONEY : une somme d'argent, et PERCENT : un pourcentage.
- MISC : tout le reste, fourre-tout des entités diverses.
Visualiser le résultat avec displacy
Rien de tel qu'une image pour valider un résultat. spaCy embarque un visualiseur, displacy, qui colore les entités directement dans le navigateur. Pratique pour débuguer ou pour montrer le résultat à un collègue :
from spacy import displacy
# Génère un fichier HTML que tu ouvres dans ton navigateur
html = displacy.render(doc, style="ent", jupyter=False)
with open("entites.html", "w", encoding="utf-8") as f:
f.write(html)
# Alternative : lancer un petit serveur local
# displacy.serve(doc, style="ent")Ouvre le fichier entites.html : tu verras chaque entité surlignée dans une couleur propre à sa catégorie. C'est le moyen le plus rapide de repérer les erreurs — par exemple un prénom mal découpé ou un lieu confondu avec une organisation.
Une mini-app qui regroupe et compte les entités
On assemble tout dans un script qui, à partir d'un texte un peu plus long, produit un annuaire propre : chaque type d'entité, avec les valeurs rencontrées, sans doublon.
from collections import defaultdict
texte = """Emmanuel Macron et Ursula von der Leyen se sont rencontrés à Bruxelles,
au siège de la Commission européenne. Apple a annoncé l'ouverture d'un nouveau
centre de recherche à Paris, tandis que Google investit à Londres."""
doc = nlp(texte)
groupes = defaultdict(set)
for ent in doc.ents:
groupes[ent.label_].add(ent.text)
for label, valeurs in sorted(groupes.items()):
print(f"{spacy.explain(label)} : {', '.join(sorted(valeurs))}")Quelques lignes de logique, et tu obtiens un annuaire exploitable : la liste des personnes, des organisations et des lieux mentionnés dans un document. Multiplie ce script sur un corpus de milliers d'articles, et tu as un outil de veille rudimentaire mais fonctionnel.
Cas pratique : anonymiser un texte
Un des usages les plus concrets du NER est l'anonymisation. En remplaçant chaque entité de type PERSON ou GPE par son étiquette, tu retires d'un document les informations directement identifiantes. C'est précieux avant de partager des données, de publier un extrait ou d'alimenter un modèle en données sensibles.
def anonymiser(texte):
doc = nlp(texte)
resultat = texte
# On remplace les entités sensibles, de la plus longue à la plus courte
# pour éviter les chevauchements (ex. "Paris" dans "Paris Match")
for ent in sorted(doc.ents, key=lambda e: len(e.text), reverse=True):
if ent.label_ in ("PER", "PERSON", "GPE", "LOC"):
resultat = resultat.replace(ent.text, f"[{ent.label_}]")
return resultat
print(anonymiser("Emmanuel Macron a rencontré Ursula von der Leyen à Bruxelles."))
# -> "[PER] a rencontré [PER] à [GPE]."Deux subtilités dans ce code : on trie les entités par longueur décroissante pour traiter d'abord les plus longues (sinon, « Paris » serait remplacé avant « Paris Match »), et on cible les étiquettes sensibles sans toucher aux organisations, qu'on préfère parfois conserver. Adapte la liste des étiquettes à ton propre besoin de confidentialité.
Personnaliser la détection avec EntityRuler
Le modèle pré-entraîné ne connaît pas tout : les sigles de ton entreprise, tes codes produits, ou les noms propres de ton domaine lui échappent. EntityRuler permet d'ajouter tes propres règles, sous forme de motifs, sans réentraîner le modèle. C'est un excellent premier pas vers du NER sur mesure.
from spacy.pipeline import EntityRuler
# On ajoute un composant de règles au pipeline
regles = EntityRuler(nlp)
regles.add_patterns([
{"label": "ORG", "pattern": "IANCR"},
{"label": "PRODUIT", "pattern": [{"LOWER": "modèle"}, {"LOWER": "x1"}]},
])
nlp.add_pipe(regles, before="ner")
nouveau = nlp("IANCR vient de lancer son modèle X1, disponible dès aujourd'hui.")
for ent in nouveau.ents:
print(ent.text, "->", ent.label_)Le composant s'insère avant le NER, de sorte que ses règles priment sur la détection statistique. Tu peux créer des motifs simples (une chaîne exacte) ou plus fins, basés sur la forme des mots, leur lemme ou leur catégorie grammaticale. C'est ainsi que, progressivement, on adapte un pipeline générique à un métier précis.
Les limites du NER, et comment les contourner
Le modèle « sm » est entraîné sur des textes de presse généraliste. Il est excellent sur ce registre, mais il bute sur certains cas : les domaines spécialisés (médecine, droit), les noms très récents, ou les textes écrits dans un style inhabituel. Un nom d'entreprise inconnu du corpus d'entraînement risque d'être ignoré ou mal étiqueté.
Trois stratégies pour améliorer les résultats :
- Choisir un modèle plus grand (md ou lg) : plus précis, au prix d'un temps de calcul supérieur.
- Ajouter des règles personnalisées avec EntityRuler, pour détecter des entités spécifiques à ton domaine.
- Entraîner ton propre modèle NER sur des exemples annotés, quand ton domaine est très éloigné de la presse.
Pour la majorité des cas, le modèle pré-entraîné suffit largement. Le réflexe à retenir : commence toujours par un modèle standard, mesure la qualité sur tes données réelles, et n'investis dans du sur-mesure que si les erreurs sont réellement gênantes.
Compter les entités d'un corpus entier
Le NER prend tout son sens quand tu l'appliques non plus à une phrase, mais à des centaines de documents. La logique reste la même : on boucle sur les textes, on accumule les entités, et on trie les plus fréquentes. Avec Counter de la bibliothèque standard, le comptage tient en quelques lignes.
from collections import Counter
# Une petite liste de textes, comme un mini-corpus de presse
documents = [
"Emmanuel Macron a rencontré Ursula von der Leyen à Bruxelles.",
"Apple ouvre un centre de recherche à Paris.",
"Emmanuel Macron et Apple étaient au sommet de Paris.",
]
compteur = Counter()
for texte in documents:
for ent in nlp(texte).ents:
if ent.label_ in ("PERSON", "ORG", "GPE"):
compteur[(ent.text, ent.label_)] += 1
for (nom, label), nb in compteur.most_common(5):
print(f"{nom:24} ({label}) : {nb} fois")Le résultat te dit, en un coup d'oeil, quelles personnes et quelles organisations dominent ton corpus. C'est exactement le genre de pipeline qui alimente une veille automatisée : tu collectes les articles, tu comptes les entités, et tu repères immédiatement les acteurs qui montent.
Un conseil d'optimisation pour les gros volumes : active nlp.pipe() plutôt qu'une simple boucle. Cette méthode traite les textes en parallèle et en flux, ce qui réduit nettement le temps de calcul sur des milliers de documents.
Conclusion
Tu sais désormais installer spaCy, charger un modèle français, analyser un texte, étiqueter ses mots et en extraire les entités nommées. Tu sais aussi visualiser le résultat, le transformer en annuaire exploitable, anonymiser un document et étendre la détection avec tes propres règles. C'est un socle solide, et chaque brique est directement réutilisable dans un vrai projet.
Le mieux est de passer à la pratique : prends un article de presse, colle-le dans le script, et observe ce que le modèle repère. Puis teste sur un texte de ton domaine — tu verras très vite où sont les forces et les limites de l'outil, et quelles règles personnalisées valent la peine d'ajouter.






