Déterminer l'encodage du texte en Python

j'ai reçu du texte codé, mais je ne sais pas quel charset a été utilisé. Est-il un moyen de déterminer l'encodage d'un fichier texte à l'aide de Python? Comment puis-je détecter l'encodage/codepage d'un fichier texte traite avec C#.

150
demandé sur Community 2009-01-12 20:30:27

8 réponses

détecter correctement l'encodage en tout temps est impossible .

(tiré de chardet FAQ:)

cependant, certains encodages sont optimisés pour des langues spécifiques, et des langues ne sont pas aléatoires. Certains de ces caractères les séquences surgissent tout le temps, tandis que d'autres séquences n'ont pas de sens. Un personne parlant couramment l'anglais qui ouvre un journal et trouve " txzqJv 2!dasd0a QqdKjvz " reconnaîtra instantanément que que n'est pas l'anglais (même si c'est composé entièrement de lettres anglaises). En étudiant beaucoup de texte "typique", un algorithme d'ordinateur peut simuler cette une sorte de fluidité et de faire un devinez à propos d'un texte de langue.

il y a la bibliothèque chardet qui utilise cette étude pour essayer de détecter l'encodage. chardet est un port du code de détection automatique de Mozilla.

vous pouvez également utiliser UnicodeDammit . Il va essayer les méthodes suivantes:

  • un encodage découvert dans le document lui-même: par exemple, dans une déclaration XML ou (pour les documents HTML) une MÉTABALISE http-equiv. Si Beautiful Soup trouve ce genre d'encodage dans le document, il efface le document dès le début et donne un essai au nouveau codage. La seule exception est si vous avez spécifié explicitement un encodage, et que l'encodage a réellement fonctionné: alors il va ignorez tout encodage qu'il trouve dans le document.
  • Un encodage reniflé en regardant les premiers octets du fichier. Si un encodage est détecté à ce stade, il sera L'un des encodages UTF -*, EBCDIC, ou ASCII.
  • un encodage reniflé par la bibliothèque chardet , si vous l'avez installé.
  • UTF-8
  • Windows-1252
160
répondu nosklo 2017-04-03 15:54:53

une Autre option pour l'encodage à utiliser libmagic (qui est le code fichier "151940920 de la commande"). Il y a une profusion de fixations python disponibles.

les fixations python qui vivent dans l'arbre des sources de fichier sont disponibles en tant que python-magie (ou python3-magie ) paquet debian. Si peut déterminer l'encodage d'un fichier en faisant:

import magic

blob = open('unknown-file').read()
m = magic.open(magic.MAGIC_MIME_ENCODING)
m.load()
encoding = m.buffer(blob)  # "utf-8" "us-ascii" etc

il y a un paquet pip sur pypi qui utilise aussi libmagic et qui porte un nom identique, mais incompatible, python-magic . Il peut aussi obtenir l'encodage, en faisant:

import magic

blob = open('unknown-file').read()
m = magic.Magic(mime_encoding=True)
encoding = m.from_buffer(blob)
43
répondu Hamish Downer 2014-09-03 14:42:50

Certains codant pour des stratégies, décommentez du goût :

#!/bin/bash
#
tmpfile=
echo '-- info about file file ........'
file -i $tmpfile
enca -g $tmpfile
echo 'recoding ........'
#iconv -f iso-8859-2 -t utf-8 back_test.xml > $tmpfile
#enca -x utf-8 $tmpfile
#enca -g $tmpfile
recode CP1250..UTF-8 $tmpfile

vous pouvez vérifier l'encodage en ouvrant et en lisant le fichier sous forme de boucle... mais vous pourriez avoir besoin de vérifier le filesize d'abord:

encodings = ['utf-8', 'windows-1250', 'windows-1252' ...etc]
            for e in encodings:
                try:
                    fh = codecs.open('file.txt', 'r', encoding=e)
                    fh.readlines()
                    fh.seek(0)
                except UnicodeDecodeError:
                    print('got unicode error with %s , trying different encoding' % e)
                else:
                    print('opening the file with encoding:  %s ' % e)
                    break              
21
répondu zzart 2015-06-02 15:23:22

voici un exemple de lecture et de prise en compte à la valeur nominale d'un chardet prédiction d'encodage, la lecture n_lines à partir du fichier dans le cas où il est grand.

chardet vous donne aussi une probabilité (i.e. confidence ) de sa prédiction d'encodage (n'ont pas regardé comment ils viennent avec cela), qui est retourné avec sa prédiction de chardet.predict() , de sorte que vous pouvez travailler en quelque sorte si vous voulez.

def predict_encoding(file_path, n_lines=20):
    '''Predict a file's encoding using chardet'''
    import chardet

    # Open the file as binary data
    with open(file_path, 'rb') as f:
        # Join binary lines for specified number of lines
        rawdata = b''.join([f.readline() for _ in range(n_lines)])

    return chardet.detect(rawdata)['encoding']
10
répondu ryanjdillon 2017-07-18 13:01:49
# Function: OpenRead(file)

# A text file can be encoded using:
#   (1) The default operating system code page, Or
#   (2) utf8 with a BOM header
#
#  If a text file is encoded with utf8, and does not have a BOM header,
#  the user can manually add a BOM header to the text file
#  using a text editor such as notepad++, and rerun the python script,
#  otherwise the file is read as a codepage file with the 
#  invalid codepage characters removed

import sys
if int(sys.version[0]) != 3:
    print('Aborted: Python 3.x required')
    sys.exit(1)

def bomType(file):
    """
    returns file encoding string for open() function

    EXAMPLE:
        bom = bomtype(file)
        open(file, encoding=bom, errors='ignore')
    """

    f = open(file, 'rb')
    b = f.read(4)
    f.close()

    if (b[0:3] == b'\xef\xbb\xbf'):
        return "utf8"

    # Python automatically detects endianess if utf-16 bom is present
    # write endianess generally determined by endianess of CPU
    if ((b[0:2] == b'\xfe\xff') or (b[0:2] == b'\xff\xfe')):
        return "utf16"

    if ((b[0:5] == b'\xfe\xff\x00\x00') 
              or (b[0:5] == b'\x00\x00\xff\xfe')):
        return "utf32"

    # If BOM is not provided, then assume its the codepage
    #     used by your operating system
    return "cp1252"
    # For the United States its: cp1252


def OpenRead(file):
    bom = bomType(file)
    return open(file, 'r', encoding=bom, errors='ignore')


#######################
# Testing it
#######################
fout = open("myfile1.txt", "w", encoding="cp1252")
fout.write("* hi there (cp1252)")
fout.close()

fout = open("myfile2.txt", "w", encoding="utf8")
fout.write("\u2022 hi there (utf8)")
fout.close()

# this case is still treated like codepage cp1252
#   (User responsible for making sure that all utf8 files
#   have a BOM header)
fout = open("badboy.txt", "wb")
fout.write(b"hi there.  barf(\x81\x8D\x90\x9D)")
fout.close()

# Read Example file with Bom Detection
fin = OpenRead("myfile1.txt")
L = fin.readline()
print(L)
fin.close()

# Read Example file with Bom Detection
fin = OpenRead("myfile2.txt")
L =fin.readline() 
print(L) #requires QtConsole to view, Cmd.exe is cp1252
fin.close()

# Read CP1252 with a few undefined chars without barfing
fin = OpenRead("badboy.txt")
L =fin.readline() 
print(L)
fin.close()

# Check that bad characters are still in badboy codepage file
fin = open("badboy.txt", "rb")
fin.read(20)
fin.close()
1
répondu Bill Moore 2017-06-16 14:06:49

Il est, en principe, impossible de déterminer l'encodage d'un fichier texte, dans le cas général. Donc non, il n'y a pas de bibliothèque standard Python pour faire ça pour vous.

si vous avez des connaissances plus spécifiques sur le fichier texte (par exemple QU'il S'agit de XML), il peut y avoir des fonctions de bibliothèque.

0
répondu Martin v. Löwis 2009-01-12 17:32:27

si vous connaissez un peu le contenu du fichier, vous pouvez essayer de le décoder avec plusieurs encodages et voir ce qui manque. En général, il n'y a pas de chemin depuis un fichier texte est un fichier texte et ceux qui sont stupides ;)

0
répondu Martin Thurau 2009-01-12 17:36:42

selon votre plate-forme, j'opte pour la commande Linux shell file . Cela fonctionne pour moi puisque je l'utilise dans un script qui tourne exclusivement sur une de nos machines linux.

évidemment, ce n'est pas une solution ou une réponse idéale, mais elle pourrait être modifiée pour répondre à vos besoins. Dans mon cas, je dois juste déterminer si un fichier est UTF-8 ou non.

import subprocess
file_cmd = ['file', 'test.txt']
p = subprocess.Popen(file_cmd, stdout=subprocess.PIPE)
cmd_output = p.stdout.readlines()
# x will begin with the file type output as is observed using 'file' command
x = cmd_output[0].split(": ")[1]
return x.startswith('UTF-8')
0
répondu MikeD 2017-06-22 17:04:38