python import - UnicodeEncodeError:el codec 'ascii' no puede codificar el carácter u '\ xa0' en la posición 20:ordinal no está dentro del rango(128)




beautifulsoup tutorial (17)

Tengo problemas para tratar con 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 . He intentado casi todo lo que puedo pensar, y sin embargo, no he encontrado nada que funcione de manera coherente sin lanzar 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 un seguimiento de pila producido en ALGUNAS cadenas cuando se ejecuta el fragmento de código 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 tienen su sede en el Reino Unido y proporcionan datos destinados al consumo del Reino Unido, por lo que no hay problemas relacionados con la internalización o el tratamiento de textos escritos en otro idioma que no sea el inglés.

¿Alguien tiene alguna idea sobre cómo resolver esto para que así pueda solucionar este problema DE FORMA CONSISTENTE?


Answers

Agregue la línea a continuación al comienzo de su script (o como segunda línea):

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

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


El problema es que está intentando imprimir un carácter Unicode, pero su terminal no lo admite.

Puedes intentar instalar language-pack-en 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 un paquete de idioma diferente si es necesario (dependiendo de los caracteres que intenta imprimir).

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

Luego, cuando escriba 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, verifique nuevamente la configuración de su sistema, como:

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

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

  • Compruebe qué configuración regional admite su shell por:

    locale -a | grep "UTF-8"
    

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

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

    vagrant init ubuntu/trusty64; vagrant up; vagrant ssh
    

    Ver: cajas de Ubuntu disponibles . .

  2. Imprimir caracteres Unicode (como el signo de marca like ):

    $ 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");'
    ™
    

Siempre coloco el código a continuación en las dos primeras líneas de los archivos de python:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

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

Básicamente, deje de usar str para convertir de unicode a texto codificado / bytes.

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

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

O trabajar completamente en Unicode.


Para mí, lo que funcionó fue:

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

Espero que esto ayude a alguien.


Nos encontramos con este error cuando manage.py migrate en Django con dispositivos localizados.

Nuestra fuente contenía la declaración # -*- coding: utf-8 -*- , MySQL se configuró correctamente para utf8 y Ubuntu tenía el paquete de idioma y los valores adecuados en /etc/default/locale .

El problema era simplemente que al contenedor Django (usamos la ventana acoplable) le faltaba la var.

La configuración de LANG en en_US.UTF-8 y el reinicio del contenedor antes de volver a ejecutar las migraciones solucionó el problema.


Acabo de tener este problema y Google me guió aquí, así que solo para agregar a las soluciones generales aquí, esto es lo que funcionó para mí:

# 'value' contains the problematic data
unic = u''
unic += value
value = unic

Tuve esta idea después de leer http://nedbatchelder.com/text/unipain.html .

Sin embargo, no pretendo entender completamente por qué funciona esto. Entonces, si alguien puede editar esta respuesta o hacer un comentario para explicar, se lo agradeceré.


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

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

Acabo de usar lo siguiente:

import unicodedata
message = unicodedata.normalize("NFKD", message)

Compruebe lo que dice la documentación al respecto:

unicodedata.normalize (form, unistr) Devuelve la forma normal para la cadena Unicode unistr. Los valores válidos para la forma son 'NFC', 'NFKC', 'NFD' y 'NFKD'.

El estándar de Unicode define varias formas de normalización de una cadena de Unicode, según la definición de equivalencia canónica y la equivalencia de compatibilidad. En Unicode, varios caracteres se pueden expresar de varias maneras. Por ejemplo, el carácter U + 00C7 (LATINA CAPITAL LATINA C CON CEDILLA) también se puede expresar como la secuencia U + 0043 (LETRA CAPITAL LETRA C) U + 0327 (COMBINANDO CEDILLA).

Para cada personaje, hay dos formas normales: la forma normal C y la forma normal D. La forma normal D (NFD) también se conoce como descomposición canónica y traduce cada carácter a su forma descompuesta. La forma normal C (NFC) primero aplica una descomposición canónica, luego vuelve a componer los caracteres pre-combinados.

Además de estas dos formas, hay dos formas normales adicionales basadas en la equivalencia de compatibilidad. En Unicode, se admiten ciertos caracteres que normalmente se unificarían con otros caracteres. Por ejemplo, U + 2160 (ROMAN NUMERAL ONE) es realmente lo mismo que U + 0049 (LETRA MAYÚSCULA LATINA I). Sin embargo, es compatible con Unicode para la compatibilidad con conjuntos de caracteres existentes (por ejemplo, gb2312).

La forma normal KD (NFKD) aplicará la descomposición de compatibilidad, es decir, reemplazará todos los caracteres de compatibilidad con sus equivalentes. La forma normal KC (NFKC) primero aplica la descomposición de compatibilidad, seguida de la composición canónica.

Incluso si dos cadenas de Unicode están normalizadas y tienen el mismo aspecto que un lector humano, si una tiene caracteres combinados y la otra no, pueden no ser iguales.

Lo resuelve por mi. Simple y fácil.


Solo agregue a una codificación variable ('utf-8')

agent_contact.encode('utf-8')

Funciones de ayuda simples que se encuentran here .

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')

Este es un clásico punto de dolor Python Unicode! 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 chapuzón, eso no va a hacer ningún bien a nadie! Para corregir el error, codifique los bytes explícitamente con .encode y dígale 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 probar y codificar los bytes que le diste, que en tu caso a veces son representaciones de caracteres Unicode. Para solucionar el problema, debes decirle a Python cómo lidiar con la cadena que le das usando .encode ('whatever_unicode'). La mayoría de las veces, debería estar bien usando utf-8.

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


Debajo de la solución funcionó para mí, Sólo añadido

u "cadena"

(representando la cadena como unicode) antes de mi cadena.

result_html = result.to_html(col_space=1, index=False, justify={'right'})

text = u"""
<html>
<body>
<p>
Hello all, <br>
<br>
Here's weekly summary report.  Let me know if you have any questions. <br>
<br>
Data Summary <br>
<br>
<br>
{0}
</p>
<p>Thanks,</p>
<p>Data Team</p>
</body></html>
""".format(result_html)

Si tienes algo como packet_data = "This is data" , hazlo en la siguiente línea, justo después de inicializar packet_data :

unic = u''
packet_data = unic

Encontré un trabajo elegante alrededor para que elimine los símbolos y continúe manteniendo la cadena como la siguiente:

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

Es importante notar que usar la opción de ignorar es peligroso porque descarta silenciosamente 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'

Aquí hay una repetición de algunas de las llamadas respuestas "de salida". Hay situaciones en las que simplemente tirar los molestos caracteres / cuerdas es una buena solución, a pesar de las protestas que se expresan aquí.

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

Probandolo

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 como toAscii en toAscii lugar? Esa es una cuestión de preferencia.


Use Encode::Locale :

use Encode::Locale;

decode_argv Encode::FB_CROAK;

Esto funciona, también en Win32, bastante bien para mí.







python unicode beautifulsoup python-2.x python-unicode