2010-10-06 20 views
5

tengo una cadena decir s = 'Chocolate Moelleux-M\xe8re' cuando estoy haciendo:cómo decodificar un carácter no unicode en python?

In [14]: unicode(s) 
--------------------------------------------------------------------------- 
UnicodeDecodeError      Traceback (most recent call last) 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 20: ordinal not in range(128) 

Del mismo modo, cuando estoy tratando de descifrar esto usando s.decode() devuelve el mismo error.

In [13]: s.decode() 
--------------------------------------------------------------------------- 
UnicodeDecodeError      Traceback (most recent call last) 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 20: ordinal not in range(128) 

Cómo decodificar tal cadena en unicode.

Respuesta

10

He tenido que enfrentar este problema demasiadas veces. El problema que tuve contenía cadenas en diferentes esquemas de codificación. Así que escribí un método para decodificar una cadena de forma heurística en función de ciertas características de diferentes codificaciones.

def decode_heuristically(string, enc = None, denc = sys.getdefaultencoding()): 
    """ 
    Try to interpret 'string' using several possible encodings. 
    @input : string, encode type. 
    @output: a list [decoded_string, flag_decoded, encoding] 
    """ 
    if isinstance(string, unicode): return string, 0, "utf-8" 
    try: 
     new_string = unicode(string, "ascii") 
     return string, 0, "ascii" 
    except UnicodeError: 
     encodings = ["utf-8","iso-8859-1","cp1252","iso-8859-15"] 

     if denc != "ascii": encodings.insert(0, denc) 

     if enc: encodings.insert(0, enc) 

     for enc in encodings: 
      if (enc in ("iso-8859-15", "iso-8859-1") and 
       re.search(r"[\x80-\x9f]", string) is not None): 
       continue 

      if (enc in ("iso-8859-1", "cp1252") and 
       re.search(r"[\xa4\xa6\xa8\xb4\xb8\xbc-\xbe]", string)\ 
       is not None): 
       continue 

      try: 
       new_string = unicode(string, enc) 
      except UnicodeError: 
       pass 
      else: 
       if new_string.encode(enc) == string: 
        return new_string, 0, enc 

     # If unable to decode,doing force decoding i.e.neglecting those chars. 
     output = [(unicode(string, enc, "ignore"), enc) for enc in encodings] 
     output = [(len(new_string[0]), new_string) for new_string in output] 
     output.sort() 
     new_string, enc = output[-1][1] 
     return new_string, 1, enc 

Para añadir a esto este enlace da una buena retroalimentación sobre qué codificación etc - Why we need sys.setdefaultencoging in py script

4

Necesita decirle a s.decode su codificación. En su caso s.decode('latin-1') parece apropiado.

+0

se va a ayudarme en todas las situaciones? ¿Hay alguna solución generalizada? – user12345

+0

Podemos eliminar esos caracteres como '\ x' en mi ejemplo, de la cadena original. – user12345

+0

@alis: Puede usar chardet (http://chardet.feedparser.org/) para adivinar la codificación. – johnbaum

Cuestiones relacionadas