Pregunta UnicodeEncodeError: el códec 'ascii' no puede codificar el carácter u '\ xa0' en la posición 20: ordinal no en el rango (128)


Tengo problemas para tratar los caracteres Unicode del texto obtenido de diferentes páginas web (en diferentes sitios). Estoy usando BeautifulSoup.

El problema es que el error no siempre es reproducible; a veces funciona con algunas páginas, y a veces, barfs lanzando un UnicodeEncodeError. Intenté casi todo lo que se me ocurre y, sin embargo, no encontré nada que funcione de manera consistente sin arrojar algún tipo de error relacionado con Unicode.

A continuación, se muestra una de las secciones de código que está causando problemas:

agent_telno = agent.find('div', 'agent_contact_number')
agent_telno = '' if agent_telno is None else agent_telno.contents[0]
p.agent_info = str(agent_contact + ' ' + agent_telno).strip()

Aquí hay una traza de pila producida en ALGUNAS cadenas cuando se ejecuta el fragmento anterior:

Traceback (most recent call last):
  File "foobar.py", line 792, in <module>
    p.agent_info = str(agent_contact + ' ' + agent_telno).strip()
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 20: ordinal not in range(128)

Sospecho que esto se debe a que algunas páginas (o más específicamente, las páginas de algunos de los sitios) pueden estar codificadas, mientras que otras pueden estar sin codificar. Todos los sitios se basan en el Reino Unido y brindan datos destinados al consumo del Reino Unido, por lo que no hay problemas relacionados con la internalización ni con el texto escrito en otro idioma que no sea el inglés.

¿Alguien tiene alguna idea de cómo resolver esto para poder solucionar este problema de forma CONSISTENTE?


937
2018-03-30 12:06


origen


Respuestas:


Necesitas leer el Python CÓMO de Unicode. Este error es el primer ejemplo.

Básicamente, deja de usar str para convertir de unicode a texto / bytes codificados.

En su lugar, use correctamente .encode() para codificar la cadena:

p.agent_info = u' '.join((agent_contact, agent_telno)).encode('utf-8').strip()

o trabaje completamente en Unicode.


1052
2018-03-30 12:21



¡Este es un punto de dolor unicode clásico de python! Considera lo siguiente:

a = u'bats\u00E0'
print a
 => batsà

Todo bien hasta ahora, pero si llamamos a str (a), veamos qué sucede:

str(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)

Oh, no, eso no le hará ningún bien a nadie. Para corregir el error, codifique los bytes explícitamente con .encode y diga a python qué códec usar:

a.encode('utf-8')
 => 'bats\xc3\xa0'
print a.encode('utf-8')
 => batsà

Voil \ u00E0!

El problema es que cuando llamas a str (), python usa la codificación de caracteres predeterminada para intentar codificar los bytes que le diste, que en su caso a veces son representaciones de caracteres Unicode. Para solucionar el problema, debes decirle a python cómo tratar con la cadena que le das usando .encode ('whatever_unicode'). La mayoría de las veces, deberías estar bien usando utf-8.

Para una exposición excelente sobre este tema, vea la charla PyCon de Ned Batchelder aquí: http://nedbatchelder.com/text/unipain.html


366
2018-03-30 12:25



Encontré un trabajo elegante para que elimine los símbolos y sigo manteniendo la cadena como una cadena de la siguiente manera:

yourstring = yourstring.encode('ascii', 'ignore').decode('ascii')

Es importante notar que usar la opción ignorar es peligroso porque silenciosamente elimina cualquier soporte de unicode (e internacionalización) del código que lo usa, como se ve aquí (convertir unicode):

>>> u'City: Malmö'.encode('ascii', 'ignore').decode('ascii')
'City: Malm'

165
2017-08-20 10:13



Bueno, probé todo, pero no sirvió, después de buscar en Google, pensé lo siguiente y me ayudó. Python 2.7 está en uso.

# encoding=utf8
import sys
reload(sys)
sys.setdefaultencoding('utf8')

107
2017-09-02 13:10



Un problema sutil que causa que incluso la impresión falle es tener sus variables de entorno configuradas incorrectamente, ej. aquí LC_ALL establecido en "C". En Debian desaconsejan establecerlo: Wiki de Debian en Locale

$ echo $LANG
en_US.utf8
$ echo $LC_ALL 
C
$ python -c "print (u'voil\u00e0')"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)
$ export LC_ALL='en_US.utf8'
$ python -c "print (u'voil\u00e0')"
voilà
$ unset LC_ALL
$ python -c "print (u'voil\u00e0')"
voilà

71
2017-12-02 17:58



De hecho, he descubierto que en la mayoría de mis casos, simplemente eliminar esos personajes es mucho más simple:

s = mystring.decode('ascii', 'ignore')

26
2017-11-01 13:44



Para mí, lo que funcionó fue:

BeautifulSoup(html_text,from_encoding="utf-8")

Espero que esto ayude a alguien.


24
2018-01-26 14:53



Agregue la línea siguiente al comienzo de su script (o como segunda línea):

# -*- coding: utf-8 -*-

Esa es la definición de la codificación de código fuente python. Más información en PEP 263.


16
2017-08-08 10:17



El problema es que estás tratando de imprimir un carácter Unicode, pero tu terminal no lo admite.

Puedes intentar instalar language-pack-en paquete para arreglar eso:

sudo apt-get install language-pack-en

que proporciona actualizaciones de datos de traducción al inglés para todos los paquetes compatibles (incluido Python). Instale paquetes de idiomas diferentes si es necesario (dependiendo de los caracteres que intente imprimir).

En algunas distribuciones de Linux es necesario para asegurarse de que las configuraciones regionales en inglés predeterminadas estén configuradas correctamente (para que los caracteres unicode puedan ser manejados por shell / terminal). A veces es más fácil de instalar que configurarlo manualmente.

Luego, al escribir el código, asegúrese de usar la codificación correcta en su código.

Por ejemplo:

open(foo, encoding='utf-8')

Si aún tiene un problema, vuelva a verificar la configuración de su sistema, como por ejemplo:

  • Su archivo de configuración regional (/etc/default/locale), que debería tener, p.

    LANG="en_US.UTF-8"
    LC_ALL="en_US.UTF-8"
    
  • Valor de LANG/LC_CTYPE en concha.

  • Compruebe qué entorno local admite su caparazón:

    locale -a | grep "UTF-8"
    

Demostrando el problema y la solución en VM fresca.

  1. Inicialice y aprovisione la máquina virtual (por ejemplo, utilizando vagrant)

    vagrant init ubuntu/trusty64; vagrant up; vagrant ssh
    

    Ver: cajas de Ubuntu disponibles..

  2. Imprimir caracteres unicode (como el signo de marca como )

    $ python -c 'print(u"\u2122");'
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    UnicodeEncodeError: 'ascii' codec can't encode character u'\u2122' in position 0: ordinal not in range(128)
    
  3. Ahora instalando language-pack-en:

    $ sudo apt-get -y install language-pack-en
    The following extra packages will be installed:
      language-pack-en-base
    Generating locales...
      en_GB.UTF-8... /usr/sbin/locale-gen: done
    Generation complete.
    
  4. Ahora el problema está resuelto:

    $ python -c 'print(u"\u2122");'
    
    

14
2017-08-13 12:07



Aquí hay una repetición de algunas otras respuestas llamadas "cop out". Hay situaciones en las que simplemente descartar los molestos personajes / cadenas es una buena solución, a pesar de las protestas expresadas aquí.

def safeStr(obj):
    try: return str(obj)
    except UnicodeEncodeError:
        return obj.encode('ascii', 'ignore').decode('ascii')
    except: return ""

Probándolo:

if __name__ == '__main__': 
    print safeStr( 1 ) 
    print safeStr( "test" ) 
    print u'98\xb0'
    print safeStr( u'98\xb0' )

Resultados:

1
test
98°
98

Sugerencia: es posible que desee nombrar esta función para toAscii ¿en lugar? Esa es una cuestión de preferencia.


10
2017-09-26 19:23



Se encontraron funciones simples de ayuda aquí.

def safe_unicode(obj, *args):
    """ return the unicode representation of obj """
    try:
        return unicode(obj, *args)
    except UnicodeDecodeError:
        # obj is byte string
        ascii_text = str(obj).encode('string_escape')
        return unicode(ascii_text)

def safe_str(obj):
    """ return the byte string representation of obj """
    try:
        return str(obj)
    except UnicodeEncodeError:
        # obj is unicode
        return unicode(obj).encode('unicode_escape')

6
2017-12-31 07:57