Cómo determinar la codificación del texto.
Recibí un texto codificado, pero no sé qué juego de caracteres se utilizó. ¿Existe alguna manera de determinar la codificación de un archivo de texto usando Python? ¿Cómo puedo detectar la codificación/página de códigos de un archivo de texto con C#?
EDITAR: chardet parece no estar mantenido pero la mayor parte de la respuesta se aplica. Consulte https://pypi.org/project/charset-normalizer/ para obtener una alternativa
Detectar correctamente la codificación en todo momento es imposible .
(De las preguntas frecuentes de Chardet :)
Sin embargo, algunas codificaciones están optimizadas para idiomas específicos y los idiomas no son aleatorios. Algunas secuencias de personajes aparecen todo el tiempo, mientras que otras secuencias no tienen sentido. Una persona que habla inglés con fluidez y abre un periódico y encuentra “txzqJv 2!dasd0a QqdKjvz” reconocerá instantáneamente que eso no es inglés (aunque esté compuesto enteramente de letras inglesas). Al estudiar muchos textos “típicos”, un algoritmo informático puede simular este tipo de fluidez y hacer una conjetura fundamentada sobre el lenguaje de un texto.
Existe la biblioteca chardet que utiliza ese estudio para intentar detectar la codificación. chardet es una adaptación del código de detección automática de Mozilla.
También puedes usar UnicodeMaldita sea . Probará los siguientes métodos:
- Una codificación descubierta en el propio documento: por ejemplo, en una declaración XML o (para documentos HTML) una etiqueta META equivalente a http. Si Beautiful Soup encuentra este tipo de codificación dentro del documento, analiza el documento nuevamente desde el principio y prueba la nueva codificación. La única excepción es si especificó explícitamente una codificación y esa codificación realmente funcionó: entonces ignorará cualquier codificación que encuentre en el documento.
- Una codificación detectada al observar los primeros bytes del archivo. Si se detecta una codificación en esta etapa, será una de las codificaciones UTF-*, EBCDIC o ASCII.
- Una codificación detectada por la biblioteca chardet , si la tienes instalada.
- UTF-8
- Windows-1252
Otra opción para resolver la codificación es usar libmagic (que es el código detrás del comando file ). Hay una gran cantidad de enlaces de Python disponibles.
Los enlaces de Python que se encuentran en el árbol de fuentes de archivos están disponibles como el paquete Debian python-magic (o python3-magic ). Puede determinar la codificación de un archivo haciendo:
import magic
blob = open('unknown-file', 'rb').read()
m = magic.open(magic.MAGIC_MIME_ENCODING)
m.load()
encoding = m.buffer(blob) # "utf-8" "us-ascii" etc
Hay un paquete python-magic pip con el mismo nombre, pero incompatible, en pypi que también usa libmagic
. También puede obtener la codificación haciendo:
import magic
blob = open('unknown-file', 'rb').read()
m = magic.Magic(mime_encoding=True)
encoding = m.from_buffer(blob)
Algunas estrategias de codificación, descomente al gusto:
#!/bin/bash
#
tmpfile=$1
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
Es posible que desee verificar la codificación abriendo y leyendo el archivo en forma de bucle... pero es posible que primero deba verificar el tamaño del archivo:
# PYTHON
encodings = ['utf-8', 'windows-1250', 'windows-1252'] # add more
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
A continuación se muestra un ejemplo de cómo leer y tomar al pie de la letra una chardet
predicción de codificación, leyendo n_lines
del archivo en caso de que sea grande.
chardet
también le brinda una probabilidad (es decir confidence
) de su predicción de codificación (no he visto cómo se les ocurrió eso), que se devuelve con su predicción de chardet.predict()
, por lo que podría trabajar eso de alguna manera si lo desea.
import chardet
from pathlib import Path
def predict_encoding(file_path: Path, n_lines: int=20) -> str:
'''Predict a file's encoding using chardet'''
# Open the file as binary data
with Path(file_path).open('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']
Esto podría ser útil
from bs4 import UnicodeDammit
with open('automate_data/billboard.csv', 'rb') as file:
content = file.read()
suggestion = UnicodeDammit(content)
suggestion.original_encoding
#'iso-8859-1'