2012-06-16 19 views
8

Ho questo problema nel tentativo di ottenere tutti i nodi di testo in un documento HTML usando lxml, ma ottengo un errore UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 8995: ordinal not in range(128). Tuttavia, quando provo a scoprire il tipo di codifica di questa pagina (encoding = chardet.detect(response)['encoding']), si dice che sia utf-8. Sembra strano che una singola pagina abbia utf-8 e ascii. In realtà, questo:UnicodeEncodeError durante il recupero dell'URL

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

risolve il problema.

qui è il mio codice:

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

uscita:

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

Cosa posso fare per risolvere questo problema ?. Tieni presente che voglio farlo con poche altre pagine, quindi non voglio codificarlo su base individuale.

UPDATE:

Forse c'è qualcos'altro qui. Quando eseguo questo script sul terminale, ottengo un output corretto ma quando lo eseguo in SublimeText, ottengo UnicodeEncodeError ... ¿?

UPDATE2:

E 'anche accadere quando creo un file con questa uscita. .encode('ascii', 'replace') sta funzionando, ma mi piacerebbe avere una soluzione più generale.

saluti

+1

"print u" \ u00A9 "' all'interno dello script genera anche l'errore? – jfs

+0

Sì.UnicodeEncodeError: il codec 'ascii' non può codificare il carattere u '\ xa9' in posizione 0: ordinale non compreso nell'intervallo (128) :-) –

+0

è possibile impostare PYTHONIOENCODING su qualsiasi codifica di carattere accettata da SublimeText. – jfs

risposta

5

Puoi provare a racchiudere la stringa con repr()? This article potrebbe aiutare.

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

Funziona bene in Sublime Text e anche nel terminale. Immagino che questo sia un workarond. Grazie! –

0

Basato sul primo aggiornamento direi che il terminale ha detto Python per l'uscita utf-8 e SublimeText ha chiarito che si aspetta ascii. Quindi penso che la soluzione sarà trovare le giuste impostazioni in SublimeText.

Tuttavia, se non è possibile modificare ciò che SublimeText si aspetta, è meglio utilizzare la funzione encode come già fatto in una funzione separata.

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

È possibile utilizzare questa funzione al posto di print. Tieni presente che l'output del tuo programma eseguito in SublimeText è diverso da Terminal. A causa dei caratteri accentati di replace, i loro accenti diminuiscono quando questo codice viene eseguito in SublimeText, ad es. é verrà visualizzato come e.

3

Per quanto riguarda la scrittura in un file, come ha detto in tua modifica, mi sento di raccomandare l'apertura del file con il modulo codecs:

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

Non so SublimeText, ma sembra tentare di leggere l'output come ASCII, quindi l'errore di codifica.

+0

Lavoro. Grazie! –

Problemi correlati