2012-06-16 19 views
8

Mam ten problem, próbując uzyskać wszystkie węzły tekstowe w dokumencie HTML za pomocą lxml, ale otrzymuję UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 8995: ordinal not in range(128). Jednak gdy próbuję znaleźć kodowanie tej strony (encoding = chardet.detect(response)['encoding']), jest napisane, że jest to utf-8. Wydaje się dziwne, że jedna strona ma utf-8 i ascii. W rzeczywistości:UnicodeEncodeError przy pobieraniu adresu URL

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

rozwiązuje problem.

Tu jest mój kodu:

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

wyjściowa:

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

Co mogę zrobić, aby rozwiązać ten problem ?. Pamiętaj, że chcę to zrobić na kilku innych stronach, więc nie chcę kodować osobno.

UPDATE:

Może jest coś innego dzieje się tutaj. Kiedy uruchamiam ten skrypt na terminalu, otrzymuję prawidłowy wynik, ale gdy uruchamiam go wewnątrz SublimeText, otrzymuję UnicodeEncodeError ... ¿?

Update2:

To samo dzieje się, gdy tworzę plik z tego wyjścia. .encode('ascii', 'replace') działa, ale chciałbym mieć bardziej ogólne rozwiązanie.

Pozdrowienia

+1

Czy "print u" \ u00A9 "' wewnątrz twojego skryptu również powoduje błąd? – jfs

+0

Tak.UnicodeEncodeError: kodek 'ascii' nie może kodować znaków u '\ xa9' w pozycji 0: porządkowy nie w zakresie (128) :-) –

+0

możesz ustawić PYTHONIOENCODING na dowolny kod znaków akceptowany przez SublimeText. – jfs

Odpowiedz

5

Czy możesz spróbować owinąć swój ciąg za pomocą repr()? This article może pomóc.

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

Działa to dobrze w Sublime Text, a także w terminalu. Sądzę, że to jest problem. Dzięki! –

0

oparciu o swojej pierwszej aktualizacji Powiedziałbym, że terminal powiedział Pythona do wyjściowego UTF-8 i Sublime Text jasno spodziewa ASCII. Myślę więc, że rozwiązaniem będzie znalezienie właściwych ustawień w SublimeText.

Jednakże, jeśli nie można zmienić tego, co SublimeText oczekuje, lepiej jest użyć funkcji encode, tak jak w przypadku innej funkcji.

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

Możesz użyć tej funkcji zamiast print. Należy pamiętać, że wynik programu po uruchomieniu w SublimeText różni się od terminala. Z powodu znaków akcentowanych replace utracisz swoje akcenty, gdy ten kod zostanie uruchomiony w SublimeText, np. é zostanie wyświetlony jako e.

3

Jeśli chodzi o pisanie do pliku, jak powiedział w swojej zmiany, polecam otwierania pliku z modułem kodekami:

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

nie wiem Sublime Text, ale wydaje próbuję odczytać twoje dane wyjściowe jako ASCII, stąd błąd kodowania.

+0

Praca. Dzięki! –

Powiązane problemy