A menudo trabajo con texto utf-8 que contiene caracteres como:
\ xc2 \ x99
- ¿Hay un sustituto listo para Unicode que pueda usar para urllib.quote y urllib.unquote en Python 2.6.5?
- ¿Cómo leer un archivo que se puede guardar como ansi o unicode en python?
- Pandas y unicode
- ¿Un equivalente a string.ascii_letters para cadenas Unicode en Python 2.x?
- json.dump - UnicodeDecodeError: el códec 'utf8' no puede decodificar el byte 0xbf en la posición 0: el byte de inicio no es válido
\ xc2 \ x95
\ xc2 \ x85
etc
Estos caracteres confunden otras bibliotecas con las que trabajo, por lo que deben ser reemplazados.
¿Qué es una forma eficiente de hacer esto, en lugar de:
text.replace('\xc2\x99', ' ').replace('\xc2\x85, '...')
Siempre hay expresiones regulares; simplemente enumera todos los caracteres ofensivos dentro de corchetes, así:
import re print re.sub(r'[\xc2\x99]'," ","Hello\xc2There\x99")
Esto imprime: ‘Hola’, con los caracteres no deseados reemplazados por espacios.
Alternativamente, si tienes un personaje de reemplazo diferente para cada uno:
# remove annoying characters chars = { '\xc2\x82' : ',', # High code comma '\xc2\x84' : ',,', # High code double comma '\xc2\x85' : '...', # Tripple dot '\xc2\x88' : '^', # High carat '\xc2\x91' : '\x27', # Forward single quote '\xc2\x92' : '\x27', # Reverse single quote '\xc2\x93' : '\x22', # Forward double quote '\xc2\x94' : '\x22', # Reverse double quote '\xc2\x95' : ' ', '\xc2\x96' : '-', # High hyphen '\xc2\x97' : '--', # Double hyphen '\xc2\x99' : ' ', '\xc2\xa0' : ' ', '\xc2\xa6' : '|', # Split vertical bar '\xc2\xab' : '<<', # Double less than '\xc2\xbb' : '>>', # Double greater than '\xc2\xbc' : '1/4', # one quarter '\xc2\xbd' : '1/2', # one half '\xc2\xbe' : '3/4', # three quarters '\xca\xbf' : '\x27', # c-single quote '\xcc\xa8' : '', # modifier - under curve '\xcc\xb1' : '' # modifier - under line } def replace_chars(match): char = match.group(0) return chars[char] return re.sub('(' + '|'.join(chars.keys()) + ')', replace_chars, text)
Creo que hay un problema subyacente aquí, y podría ser una buena idea investigar y resolverlo, en lugar de tratar de encubrir los síntomas.
\xc2\x95
es la encoding UTF-8 del carácter U + 0095, que es un carácter de control C1 (MESSAGE WAITING). No es de extrañar que su biblioteca no pueda manejarlo. Pero la pregunta es, ¿cómo llegó a sus datos?
Bueno, una posibilidad muy probable es que comenzó como el carácter 0x95 (BULLET) en la encoding de Windows-1252 , se decodificó erróneamente como U + 0095 en lugar del U + 2022 correcto, y luego se codificó en UTF-8. (El término japonés mojibake describe este tipo de error).
Si esto es correcto, entonces puede recuperar los caracteres originales volviéndolos a colocar en Windows-1252 y luego decodificarlos en Unicode correctamente esta vez. (En estos ejemplos estoy usando Python 3.3; estas operaciones son un poco diferentes en Python 2.)
>>> b'\x95'.decode('windows-1252') '\u2022' >>> import unicodedata >>> unicodedata.name(_) 'BULLET'
Si desea hacer esta corrección para todos los caracteres en el rango 0x80–0x99 que son caracteres válidos de Windows-1252, puede utilizar este método:
def restre_windows_1252_characters(s): """Replace C1 control characters in the Unicode string s by the characters at the corresponding code points in Windows-1252, where possible. """ import re def to_windows_1252(match): try: return bytes([ord(match.group(0))]).decode('windows-1252') except UnicodeDecodeError: # No character at the corresponding code point: remove it. return '' return re.sub(r'[\u0080-\u0099]', to_windows_1252, s)
Por ejemplo:
>>> restre_windows_1252_characters('\x95\x99\x85') '•™…'
Si desea eliminar todos los caracteres que no son ASCII de una cadena, puede usar
text.encode("ascii", "ignore")
import unicodedata # Convert to unicode text_to_uncicode = unicode(text, "utf-8") # Convert back to ascii text_fixed = unicodedata.normalize('NFKD',text_to_unicode).encode('ascii','ignore')
Esto no es “caracteres Unicode”; se parece más a esto a una cadena codificada en UTF-8. (Aunque su prefijo debe ser \ xC3, no \ xC2 para la mayoría de los caracteres). No debe tirarlos en el 95% de los casos, a menos que se esté comunicando con un back-end de COBOL. El mundo no se limita a 26 caracteres, ya sabes.
Hay una lectura concisa para explicar las diferencias entre las cadenas Unicode (lo que se usa como un objeto Unicode en Python 2 y como las cadenas en Python 3 aquí: http://www.joelonsoftware.com/articles/Unicode.html – por favor, para Lea todo esto. Incluso si nunca planea tener algo que no sea el inglés en todas sus aplicaciones, seguirá tropezando con símbolos como € o º que no caben en ASCII de 7 bits. Ese artículo le ayudará .
Dicho esto, tal vez las bibliotecas que estás utilizando acepten objetos Python Unicode, y puedes transformar tus cadenas UTF-8 Python 2 en unidoce haciendo lo siguiente:
var_unicode = var.decode("utf-8")
Si realmente necesitas un ASCII 100% puro, reemplaza todos los caracteres que no son ASCII, luego de decodificar la cadena a Unicode, recodifíquelo a ASCII, diciéndole que ignore los caracteres que no encajan en el conjunto de caracteres con:
var_ascii = var_unicode.encode("ascii", "replace")
Estos caracteres no están en la Biblioteca ASCII
y esa es la razón por la que está recibiendo los errores. Para evitar estos errores, puede hacer lo siguiente mientras lee el archivo.
import codecs f = codecs.open('file.txt', 'r',encoding='utf-8')
Para saber más sobre este tipo de errores, vaya a través de este enlace .