Mi código simplemente raspa una página web, luego la convierte a Unicode.
html = urllib.urlopen(link).read()
html.encode("utf8","ignore")
self.response.out.write(html)
Pero me sale un UnicodeDecodeError
:
Traceback (most recent call last):
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/webapp/__init__.py", line 507, in __call__
handler.get(*groups)
File "/Users/greg/clounce/main.py", line 55, in get
html.encode("utf8","ignore")
UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 2818: ordinal not in range(128)
Supongo que eso significa que el HTML contiene algún intento mal formado en Unicode en alguna parte. ¿Puedo descartar los bytes de código que causan el problema en lugar de obtener un error?
c2
byte o probablemente obtendría un error de decodificación: hexutf8.com/?q=C2A0Respuestas:
Actualización 2018:
A partir de febrero de 2018, el uso de compresiones se
gzip
ha vuelto bastante popular (alrededor del 73% de todos los sitios web lo usan, incluidos sitios grandes como Google, YouTube, Yahoo, Wikipedia, Reddit, Stack Overflow y Stack Exchange Network).Si realiza una decodificación simple como en la respuesta original con una respuesta comprimida, obtendrá un error similar o similar a este:
Para decodificar una respuesta gzpipped, debe agregar los siguientes módulos (en Python 3):
Nota: En Python 2 usarías en
StringIO
lugar deio
Luego puede analizar el contenido de esta manera:
Este código lee la respuesta y coloca los bytes en un búfer. El
gzip
módulo luego lee el búfer utilizando laGZipFile
función. Después de eso, el archivo comprimido puede leerse nuevamente en bytes y descodificarse al texto normalmente legible al final.Respuesta original de 2010:
¿Podemos obtener el valor real utilizado
link
?Además, generalmente encontramos este problema aquí cuando intentamos
.encode()
una cadena de bytes ya codificada. Entonces, puede intentar decodificarlo primero como enComo ejemplo:
Falla con
Mientras:
Tiene éxito sin error. Tenga en cuenta que "windows-1252" es algo que utilicé como ejemplo . ¡ Obtuve esto de chardet y tenía 0.5 confianza de que es correcto! (bueno, como se da con una cadena de 1 carácter, qué espera) Debe cambiar eso a la codificación de la cadena de bytes devuelta de
.urlopen().read()
lo que se aplica al contenido que recuperó.Otro problema que veo allí es que el
.encode()
método de cadena devuelve la cadena modificada y no modifica la fuente en su lugar. Por lo tanto, es inútil tenerlo,self.response.out.write(html)
ya que html no es la cadena codificada de html.encode (si eso es lo que originalmente buscabas).Como sugirió Ignacio, revise la página web de origen para la codificación real de la cadena devuelta
read()
. Está en una de las etiquetas Meta o en el encabezado ContentType en la respuesta. Use eso entonces como parámetro para.decode()
.Sin embargo, tenga en cuenta que no debe suponerse que otros desarrolladores son lo suficientemente responsables como para asegurarse de que las declaraciones del encabezado y / o del conjunto de caracteres meta coincidan con el contenido real. (¿Qué es un PITA, sí, debería saber, que era uno de los de antes).
fuente
encoded_str = decoded_str.encode("utf8")
raise IOError, 'Not a gzipped file'
. ¿Cuál es la culpa que hice?Decodifica la cadena que obtienes, usando el juego de caracteres en la
meta
etiqueta apropiada en la respuesta o en elContent-Type
encabezado, luego codifica.El método
encode(encoding, errors)
acepta manejadores personalizados para errores. Los valores predeterminados, ademásignore
, son:Ver https://docs.python.org/3/library/stdtypes.html#str.encode
fuente
Como una extensión a la respuesta de Ignacio Vázquez-Abrams
A veces es deseable eliminar los acentos de los caracteres e imprimir el formulario base. Esto se puede lograr con
También es posible que desee traducir otros caracteres (como la puntuación) a sus equivalentes más cercanos, por ejemplo, el carácter unicode MARCA DE COTIZACIÓN SENCILLA DERECHA no se convierte en un APÓSTROFO ASCII al codificar.
Aunque hay formas más eficientes de lograr esto. Vea esta pregunta para más detalles ¿Dónde está la base de datos "mejor ASCII para este Unicode" de Python?
fuente
Use unidecode : incluso convierte caracteres extraños en ascii al instante, e incluso convierte chino en ascii fonético.
luego:
fuente
Utilizo esta función auxiliar en todos mis proyectos. Si no puede convertir el Unicode, lo ignora. Esto se vincula con una biblioteca de django, pero con un poco de investigación podría evitarlo.
Ya no recibo ningún error Unicode después de usar esto.
fuente
Para consolas rotas como
cmd.exe
y salida HTML siempre puede usar:Esto preservará todos los caracteres no ascii mientras los hace imprimibles en ASCII puro y en HTML.
ADVERTENCIA : Si usa esto en el código de producción para evitar errores, lo más probable es que haya algo mal en su código . El único caso de uso válido para esto es imprimir en una consola no Unicode o una conversión fácil a entidades HTML en un contexto HTML.
Y, por último, si está en Windows y utiliza cmd.exe, puede escribir
chcp 65001
para habilitar la salida utf-8 (funciona con la fuente de la consola Lucida). Es posible que deba agregarmyUnicodeString.encode('utf8')
.fuente
Escribiste "" "Supongo que eso significa que el HTML contiene algún intento mal formado de unicode en alguna parte.
NO se espera que el HTML contenga ningún tipo de "intento de unicode", bien formado o no. Debe contener necesariamente caracteres Unicode codificados en alguna codificación, que generalmente se proporciona por adelantado ... busque "charset".
Parece estar asumiendo que el juego de caracteres es UTF-8 ... ¿por qué motivos? El byte "\ xA0" que se muestra en su mensaje de error indica que puede tener un conjunto de caracteres de un solo byte, por ejemplo, cp1252.
Si no puede entender la declaración al comienzo del HTML, intente usar chardet para averiguar cuál es la codificación probable.
¿Por qué has etiquetado tu pregunta con "regex"?
Actualice después de reemplazar toda su pregunta con una no pregunta:
fuente
Si tiene una cadena
line
, puede usar el.encode([encoding], [errors='strict'])
método para cadenas para convertir tipos de codificación.line = 'my big string'
line.encode('ascii', 'ignore')
Para obtener más información sobre el manejo de ASCII y Unicode en Python, este es un sitio realmente útil: https://docs.python.org/2/howto/unicode.html
fuente
Creo que la respuesta está ahí, pero solo en partes, lo que dificulta la solución rápida del problema, como
Tomemos un ejemplo, supongamos que tengo un archivo que tiene algunos datos en la siguiente forma (que contiene caracteres ascii y no ascii)
1/10/17, 21:36 - Tierra: Bienvenido ��
y queremos ignorar y preservar solo caracteres ascii.
Este código hará:
y escriba (rline) le dará
fuente
Funciona para mi
fuente
Parece que estás usando python 2.x. Python 2.x tiene como valor predeterminado ascii y no sabe acerca de Unicode. De ahí la excepción.
Simplemente pegue la siguiente línea después de shebang, funcionará
fuente
coding
comentario no es una cura mágica. Necesita saber por qué se genera el error, esto solo soluciona las cosas cuando hay caracteres malos en su fuente de Python. Ese no parece ser el caso para esta pregunta.