L’utilisation de chardet
a déjà été évoquée sur ce carnet, dans cet article consacré à l’uniformisation de l’encodage d’un corpus textuel.
J’y indiquais que chardet.detect()
permettait d’identifier l’encodage d’un fichier ouvert en binaire, afin de le décoder correctement. Le résultat retourné par cette fonction se présente sous forme d’un dictionnaire : celui-ci contient le nom de l’encodage reconnu à la clé encoding
, mais également un indice de confiance dont la valeur correspond à la clé confidence
.
Comprendre ce qu’est cet indice peut s’avérer utile, notamment pour repérer dans quels cas l’encodage risque d’être mal détecté.
Comment fonctionne chardet ?
La documentation de chardet
décrit de façon assez détaillée le fonctionnement de l’algorithme de détection de l’encodage1. En (très) gros :
- Il recherche dans un premier temps une séquence caractéristique d’une des 5 catégories d’encodages reconnues.
- Puis lance une série de tests en fonction de la catégorie et des différents encodages qu’elle regroupe.
- Enfin, il retourne l’encodage identifié, avec un indice de confiance compris entre 0 et 1 (il s’agit de l’encodage ayant l’indice de confiance le plus haut parmi ceux dont les tests n’ont pas soulevé d’erreur).
Un exemple concret
Le code utilisé pour cet exemple est un très petit script, disponible sous forme de snippet sur Gitlab. Je ne fournis pas les fichiers d’entrée, mais ils peuvent être recréés très facilement en copiant le contenu dans un fichier encodé en Shift-JIS.
La détection n’est donc pas infaillible, et il peut être intéressant de la vérifier avant de convertir des fichiers en masse. Voyons un exemple un peu extrême, avec un fichier encodé en Shift-JIS, un encodage pour le japonais, mais qui contient uniquement le texte suivant :
Fichier encode en Shift-JIS Ce fichier est encode en Shift-JIS mais le texte de cette ligne est ecrit en francais. Cette ligne est a nouveau en francais.
Voici ce que retourne chardet.detect
pour ce fichier (en utilisant ce petit script) :
{'encoding': 'ascii', 'confidence': 1.0, 'language': ''}
L’indice de confiance est à sa valeur maximale, pourtant l’encodage n’est pas détecté correctement. Comme dit précédemment, cet exemple est extrême parce qu’il suffit d’ajouter un peu de contenu en japonais pour que la détection fonctionne :
Fichier encode en Shift-JIS Ce fichier est encode en Shift-JIS mais le texte de cette ligne est ecrit en francais. このラインは日本語で書かれている。 Cette ligne est a nouveau en francais.
Retourne (toujours avec ce script) :
{'encoding': 'SHIFT_JIS', 'confidence': 0.99, 'language': 'Japanese'}
Il est probablement très rare qu’un fichier dont l’encodage est prévu pour des caractères d’une langue donnée contienne exclusivement du texte relevant d’une langue utilisant un autre système d’écriture. Cependant cet exemple montre assez clairement que, si on tend à se méfier intuitivement d’un indice de confiance qui serait très bas, il faut aussi parfois faire attention lorsque chardet
retourne un indice valant 1.0.
Vérifier un corpus
Le script commenté ici est téléchargeable sur Github, avec un exemple de fichier de sortie.
Si vous composez un corpus à partir de nombreux fichiers, il est préférable de ne pas vérifier chaque fichier individuellement, et également d’enregistrer la sortie dans un fichier plutôt que l’afficher à l’écran.
Pourquoi vérifier l’encodage ?
Faire cette vérification peut être utile avant de se lancer dans l’uniformisation de l’encodage d’un corpus en utilisant chardet
(en suivant la méthode décrite dans cet article par exemple), notamment pour les raisons suivantes :
- Si on ne connaît pas l’encodage des fichiers, il est plus prudent de vérifier son uniformité avant d’agréger les fichiers.
- Il est intéressant de savoir combien d’encodages différents coexistent. Le traitement de détection/conversion avec
chardet
n’est pas d’une grande rapidité. S’il y a peu d’encodages différents, il sera probablement plus efficace d’écrire un traitement de conversion “sur mesure”2. - Si on a produit des copies ré-encodées des fichiers, cela permet de repérer quels fichiers risquent de comporter des erreurs.
Le fonctionnement de chardet repose grandement sur l’objet UniversalDetector()
. En se basant sur cet exemple montré dans la documentation et en exploitant la classe DictWriter()
(issue du module csv
)3, on peut facilement produire un fichier TSV regroupant les résultats obtenus à la détection de l’encodage de chacun des fichiers d’un corpus.
Le script Python
Le script (Python 3.8) est disponible ici, je ne l’explique pas en détail parce que les deux liens fournis dans le paragraphe précédent sont déjà assez informatifs. Voici juste quelques précisions concernant l’entrée et la sortie de ce script :
- J’ai utilisé le module
glob
(documentation) pour parcourir le répertoire pris en entrée, c’est pourquoi j’ai pu utiliser l’expression"corpus/**/*.html"
pour le chemin d’accès. Ici, le dossiercorpus
et ses sous-dossiers sont parcourus de façon récursive (avec l’optionrecursive=True
) pour ouvrir chaque fichier HTML qui s’y trouve. - Contrairement à la solution faisant appel au module
os
présentée dans l’article sur l’uniformisation d’encodage, cette utilisation du moduleglob
devrait fonctionner quel que soit votre système d’exploitation. - Dans le fichier de sortie fourni en exemple, le première colonne (
File number
) reprend simplement la valeur de la variablefile_num
présente dans le script, qui compte le nombre de fichiers traités. Ceci ne permet pas de retrouver de quel fichier il s’agit. Pour une utilisation réelle, il serait judicieux de la remplacer ou de la compléter par une colonne indiquant le chemin d’accès du fichier concerné (en récupérant la valeur de la variablefilename
). - En plus de l’encodage,
chardet
tente aussi d’identifier la langue du document. Je n’ai pas inclus cette donnée au fichier de sortie, mais il est possible de le faire en récupérant la valeur dedetector.result['language']
.
Interpréter le fichier de sortie
La sortie obtenue est assez explicite, il suffit d’y repérer les irrégularités pour savoir quels fichiers auront éventuellement besoin d’une vérification supplémentaire en cas d’exploitation des résultats de chardet
.
Dans le cas présent, par exemple :
- Il y a quelques cas où l’encodage identifié est ascii avec indice de confiance de 1.04. Ceci ressemble à l’exemple montré précédemment, et correspond si je ne me trompe pas à une sorte de résultat par défaut lorsque les autres possibilités ont été écartées.
- Certains indices de confiance sont particulièrement bas5. Il est toutefois à noter que les indices correspondant à Windows-1254 semblent globalement plus bas que pour d’autres types d’encodage.
- Pour certains fichiers, l’encodage n’a pas pu être détecté6. Il ne sera pas possible de se baser sur le résultat de
chardet.detect
pour les ré-encoder.
Par ailleurs, même si ces quelques observations peuvent se déduire en parcourant manuellement le tableau, l’intérêt d’enregistrer les résultats dans un fichier est que celui-ci peut être traité automatiquement.
- Voir également cette page. [↩]
- Par exemple, si les fichiers sont soit en UTF-8 soit en Windows-1254, ce sera beaucoup plus rapide d’essayer de décoder en UTF-8, puis de décoder systématiquement en Windows-1254 si ça ne fonctionne pas. [↩]
- Un exemple détaillé de son fonctionnement est présenté dans cet article. [↩]
- Voir notamment fichiers (
File number
) 24, 2968, 5835 du fichier en exemple. [↩] - Voir notamment fichiers (
File number
) 725, 1713, 1727 du fichier en exemple. [↩] - Voir notamment fichiers (
File number
) 6373 à 6381 du fichier en exemple. [↩]