Uniformisation d’encodage en deux étapes

La lecture préalable de l’article Fiabilité de chardet est fortement conseillée.

Lorsqu’on travaille avec un corpus textuel composé de nombreux fichiers dont l’encodage n’est pas uniforme, l’une des premières étapes de traitement est de convertir l’ensemble du corpus vers un encodage unique et reconnu par les outils qui seront utilisés ensuite. Il existe plusieurs façons d’y parvenir, telle que celle présentée dans cet article, qui fait appel à chardet.

Toutefois, en fonction de la composition du corpus et des objectifs poursuivis, détecter et convertir en masse l’encodage de l’ensemble des fichiers n’est pas forcément la solution la plus efficace. Voici une alternative où la détection et la conversion constituent deux étapes distinctes.

Détection de l’encodage

Les scripts de cet article sont librement téléchargeables sur Github. Le script minimal_encoding_table.py est consacré à la détection de l’encodage telle que présentée ici. Un exemple de fichier de sortie est également disponible.

Afin de commenter les résultats de chardet.detect(), j’avais proposé un script permettant de créer une table regroupant les encodages détectés pour un corpus composé d’un ensemble de fichiers. Concrètement, son fichier de sortie (voici un exemple) est un fichier TSV comportant trois colonnes : l’identifiant du fichier, son encodage1 et l’indice de confiance retourné par chardet.detect().

Ce fichier de sortie va ici être utilisé comme fichier d’entrée2, moyennant quelques petits ajustements. Dans l’exemple proposé, l’identifiant du fichier (colonne File number) est un simple numéro correspondant au compte des fichiers par ordre de traitement (explication ici). Pour qu’il puisse maintenant servir d’entrée, il est indispensable de remplacer cet identifiant par le chemin d’accès du fichier. Par ailleurs, la colonne correspondant à l’indice de confiance ne sert à rien dans le cas présent, donc si vous n’en avez pas besoin par ailleurs vous pouvez vous en passer.

La construction de ce script a déjà été expliquée et ne sera pas détaillée ici, mais un exemple de script permettant de produire le fichier à utiliser est disponible sur Github3, avec un exemple de fichier de sortie.

Conversion de l’encodage

Pour cette étape de conversion, le script Python est disponible sur Github (encode_from_table.py). Sa construction ne sera pas intégralement décrite ici (la lecture des articles de ce carnet relatifs à l’encodage peut vous aider si besoin).

À ce stade, nous avons donc les contenus suivants :

  • Le répertoire contenant les fichiers du corpus (appelé my_corpus dans les fichiers téléchargeables). Le répertoire et les fichiers qu’il contient n’ont subi aucune modification.
  • Une table permettant d’associer chaque fichier à l’encodage des caractères de son contenu textuel, sous forme de fichier TSV.
La table des encodages devrait ressembler à ceci.

Créer des copies utf-8 des fichiers du corpus est alors très simple, puisque l’encodage d’origine est connu : il suffit de lire le contenu en binaire et le décoder sur la base de cet encodage d’origine pour qu’il soit réécrit correctement.

Pour ce faire, tout se base sur la lecture de la table d’encodage (fichier de sortie de l’étape précédente) en créant un objet DictReader()4. Chaque ligne du tableau correspond à un fichier du corpus, donc le traitement à appliquer à chaque fichier est à placer dans une boucle parcourant l’objet DictReader() (appelé reader dans le script proposé sur Github).

Le fichier est d’abord lu en mode binaire, en récupérant son chemin d’accès à la clé File :

for row in reader:
    filepath = f"{input_rep}/{row['File']}"
    f = open(filepath, 'rb').read()

Pour la suite, il faut tenir compte du fait que dans certains cas l’encodage n’est pas détecté. Dans ce cas, la valeur correspondant à la clé Encoding sera une chaîne de caractères vide. La structure du code se présentera comme ceci :

    if row['Encoding'] != '':
        # écrire un nouveau fichier dont le contenu est encodé en utf-8
    else:
        print(f"/!\ Unknown encoding = {row['File']}")

Dans le cas où la clé Encoding est associée à une valeur, il s’agit d’une chaîne de caractères correspondant au nom de l’encodage d’origine, détecté par chardet.detect(). Récupérer cette valeur va permettre de décoder le contenu afin de le réécrire dans un nouveau fichier, en spécifiant que celui-ci doit être en utf-8 :

    if row['Encoding'] != '':
        copy = f"{data_rep}/{row['File']}"
        fnew = open(copy, "w", encoding="utf-8")
        fnew.write(f.decode(row['Encoding'], 'ignore'))
        fnew.close()
        print(f"Processed = {row['File']}")
    else:
        print(f"/!\ Unknown encoding = {row['File']}")

On obtient ainsi un nouveau répertoire (appelé my_utf8_corpus5 dans l’exemple), contenant une copie utf-8 de chacun des fichiers du corpus d’origine : le résultat du traitement est le même que pour celui présenté dans l’article Uniformiser l’encodage d’un corpus avec Python. Appliquer le script minimal_encoding_table.py sur ce nouveau corpus confirme que tous les fichiers traités sont maintenant en utf-8.

Encodages dans le corpus d’origine
Encodage uniforme après traitement

Le traitement proposé ici est très basique : par exemple les fichiers pour lesquels aucun encodage n’a été détecté ont simplement été ignorés, et les fichiers qui étaient initialement en utf-8 ont quand même été réécrits. Si vous voulez l’utiliser pour vos fichiers, n’hésitez pas à modifier le script pour l’adapter à vos besoins ou pour optimiser son fonctionnement.

Citer ce billet : “Uniformisation d’encodage en deux étapes”, par Alexander Delaporte. Publié sur Tekipaki le 29/09/2020. Lien : https://tekipaki.hypotheses.org/669.
  1. Tel que détecté par chardet.detect(). []
  2. En plus des fichiers du corpus à uniformiser. []
  3. Pour l’utiliser sur votre propre projet, il faudra modifier la valeur de la variable input_rep (chemin d’accès du dossier contenant les fichiers à traiter) et éventuellement l’extension indiquée dans input_path. []
  4. DictReader() fait partie du module csv, présenté plus en détail dans cet article. []
  5. Associé à la variable data_rep. []

Auteur/autrice : Alexander Delaporte

Ingénieur d'études au Centre de recherches linguistiques sur l'Asie Orientale

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.

Rechercher dans OpenEdition Search

Vous allez être redirigé vers OpenEdition Search