2012-06-16 24 views
8

Tengo este problema tratando de obtener todos los nodos de texto en un documento HTML utilizando lxml pero obtengo un UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 8995: ordinal not in range(128). Sin embargo, cuando trato de averiguar el tipo de codificación de esta página (encoding = chardet.detect(response)['encoding']), dice que es utf-8. Parece raro que una sola página tenga utf-8 y ascii. En realidad, esto:UnicodeEncodeError al recuperar url

fromstring(response).text_content().encode('ascii', 'replace') 

resuelve el problema.

Aquí está mi código:

from lxml.html import fromstring 
import urllib2 
import chardet 
request = urllib2.Request(my_url) 
request.add_header('User-Agent', 
        'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)') 
request.add_header("Accept-Language", "en-us") 
response = urllib2.urlopen(request).read() 

print encoding 
print fromstring(response).text_content() 

Salida:

utf-8 
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 8995: ordinal not in range(128) 

¿Qué puedo hacer para solucionar este problema ?. Tenga en cuenta que quiero hacer esto con algunas otras páginas, por lo que no quiero codificar de forma individual.

ACTUALIZACIÓN:

Tal vez hay algo más en juego aquí. Cuando ejecuto este script en el terminal, obtengo una salida correcta pero cuando lo ejecuto dentro de SublimeText, obtengo UnicodeEncodeError ... ¿?

Update2:

También está sucediendo cuando se crea un archivo con esta salida. .encode('ascii', 'replace') está funcionando pero me gustaría tener una solución más general.

Saludos

+1

¿'print u" \ u00A9 "' dentro de su script también produce el error? – jfs

+0

Sí.UnicodeEncodeError: el códec 'ascii' no puede codificar el carácter u '\ xa9' en la posición 0: ordinal no en el rango (128) :-) –

+0

puede establecer PYTHONIOENCODING en cualquier codificación de caracteres que acepte SublimeText. – jfs

Respuesta

5

¿Puedes intentar envolver tu cadena con repr()? This article podría ayudar.

print repr(fromstring(response).text_content()) 
+0

Esto funciona bien en Sublime Text y también en terminal. Supongo que esto es un problema para el trabajo. ¡Gracias! –

0

en base a su primera actualización, diría que el terminal de Python dijo a la salida UTF-8 y Sublime Text dejó claro que espera ascii. Así que creo que la solución será encontrar la configuración correcta en SublimeText.

Sin embargo, si no puede cambiar lo que SublimeText espera, es mejor usar la función encode como lo hizo en otra función.

def smartprint(text) : 
    if sys.stdout.encoding == None : 
     print text 
    else : 
     print text.encode(sys.stdout.encoding , 'replace') 

Puede utilizar esta función en lugar de print. Tenga en cuenta que la salida de su programa cuando se ejecuta en SublimeText difiere de la Terminal. Debido a los caracteres acentuados replace, perderán sus acentos cuando este código se ejecute en SublimeText, p. é se mostrará como e.

3

En lo que escribir en un archivo como dijo en su edición, recomendaría abrir el archivo con el módulo de códecs:

import codecs 
output_file = codecs.open('filename.txt','w','utf8') 

No sé Sublime Text, pero parece intente leer su salida como ASCII, de ahí el error de codificación.

+0

trabajando. ¡Gracias! –

Cuestiones relacionadas