Mój kod po prostu zeskrobuje stronę internetową, a następnie konwertuje ją na Unicode.
html = urllib.urlopen(link).read()
html.encode("utf8","ignore")
self.response.out.write(html)
Ale dostaję 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)
Zakładam, że to znaczy, że HTML zawiera jakąś źle sformułowaną próbę gdzieś na Unicode. Czy mogę po prostu upuścić wszystkie bajty kodu, które powodują problem, zamiast otrzymać błąd?
c2
bajtem lub prawdopodobnie wystąpiłby błąd dekodowania: hexutf8.com/?q=C2A0Odpowiedzi:
Aktualizacja 2018:
Od lutego 2018 r. Stosowanie kompresji takich jak
gzip
stało się dość popularne (korzysta z niej około 73% wszystkich witryn, w tym duże witryny, takie jak Google, YouTube, Yahoo, Wikipedia, Reddit, Stack Overflow i Stack Exchange Network).Jeśli wykonasz proste dekodowanie, jak w oryginalnej odpowiedzi, z odpowiedzią spakowaną gzipem, pojawi się błąd podobny do tego:
Aby zdekodować odpowiedź z gzpipem, musisz dodać następujące moduły (w Pythonie 3):
Uwaga: w Pythonie 2 używałbyś
StringIO
zamiastio
Następnie możesz przeanalizować zawartość w następujący sposób:
Ten kod odczytuje odpowiedź i umieszcza bajty w buforze.
gzip
Moduł odczytuje się bufor za pomocąGZipFile
funkcji. Następnie spakowany plik gzip można ponownie wczytać do bajtów i na końcu zdekodować do normalnie czytelnego tekstu.Oryginalna odpowiedź z 2010 r .:
Czy możemy uzyskać rzeczywistą wartość używaną do
link
?Ponadto zwykle napotykamy ten problem tutaj, gdy próbujemy
.encode()
już zakodowany ciąg bajtów. Więc możesz spróbować najpierw go zdekodować, jak wJako przykład:
Niepowodzenie
Podczas:
Sukces bez błędów. Zwróć uwagę, że użyłem przykładu „windows-1252” . Dostałem to od Chardeta i miałem 0,5 pewności, że to prawda! (cóż, jak w przypadku łańcucha o długości 1 znaku, czego oczekujesz) Powinieneś zmienić to na kodowanie zwracanego ciągu bajtów z
.urlopen().read()
na to, co dotyczy pobranej zawartości.Innym problemem, jaki widzę, jest to, że
.encode()
metoda string zwraca zmodyfikowany ciąg i nie modyfikuje źródła w miejscu. Więc jest to trochę bezużyteczne,self.response.out.write(html)
ponieważ html nie jest zakodowanym ciągiem z html.encode (jeśli to jest to, do czego pierwotnie dążyłeś).Jak zasugerował Ignacio, sprawdź na źródłowej stronie internetowej rzeczywiste kodowanie zwróconego ciągu znaków z
read()
. Znajduje się w jednym z metatagów lub w nagłówku ContentType odpowiedzi. Użyj tego jako parametru dla.decode()
.Należy jednak pamiętać, że nie należy zakładać, że inni programiści są wystarczająco odpowiedzialni, aby upewnić się, że deklaracje nagłówka i / lub zestawu metaznaków odpowiadają rzeczywistej zawartości. (Co jest PITA, tak, należy wiedzieć, że był jednym z tych wcześniej).
źródło
encoded_str = decoded_str.encode("utf8")
raise IOError, 'Not a gzipped file'
. Jaka jest wina, którą popełniłem?Zdekoduj otrzymany ciąg, używając zestawu znaków w odpowiednim
meta
tagu w odpowiedzi lub wContent-Type
nagłówku, a następnie zakoduj.Metoda
encode(encoding, errors)
akceptuje niestandardowe programy obsługi dla błędów. Poza tym wartościami domyślnymiignore
są:Zobacz https://docs.python.org/3/library/stdtypes.html#str.encode
źródło
Jako rozszerzenie odpowiedzi Ignacio Vazquez-Abramsa
Czasami pożądane jest usunięcie akcentów ze znaków i wydrukowanie formy podstawowej. Można to osiągnąć za pomocą
Możesz również chcieć przetłumaczyć inne znaki (takie jak interpunkcja) na ich najbliższe odpowiedniki, na przykład znak Unicode PRAWEGO POJEDYNCZEGO CYTATU nie jest konwertowany na ascii APOSTROPHE podczas kodowania.
Chociaż istnieją skuteczniejsze sposoby na osiągnięcie tego. Zobacz to pytanie, aby uzyskać więcej informacji. Gdzie jest „najlepszy ASCII dla tej bazy danych Unicode” w Pythonie?
źródło
Używaj unidecode - natychmiast konwertuje nawet dziwne znaki na ascii, a nawet konwertuje chiński na fonetyczny ascii.
następnie:
źródło
Używam tej funkcji pomocnika we wszystkich moich projektach. Jeśli nie może przekonwertować Unicode, ignoruje go. To wiąże się z biblioteką django, ale przy odrobinie badań można ją ominąć.
Po użyciu tego nie otrzymuję już żadnych błędów Unicode.
źródło
W przypadku zepsutych konsol, takich jak
cmd.exe
i wyjścia HTML, zawsze możesz użyć:Pozwoli to zachować wszystkie znaki inne niż ASCII, jednocześnie umożliwiając ich drukowanie w czystym ASCII i HTML.
OSTRZEŻENIE : Jeśli użyjesz tego w kodzie produkcyjnym, aby uniknąć błędów, najprawdopodobniej w Twoim kodzie jest coś nie tak . Jedynym prawidłowym przypadkiem użycia jest drukowanie do konsoli innej niż Unicode lub łatwa konwersja do jednostek HTML w kontekście HTML.
I wreszcie, jeśli jesteś w
chcp 65001
systemie Windows i używasz cmd.exe, możesz wpisać, aby włączyć wyjście utf-8 (działa z czcionką Lucida Console). Może być konieczne dodaniemyUnicodeString.encode('utf8')
.źródło
Napisałeś "" "Zakładam, że oznacza to, że HTML zawiera gdzieś źle sformułowaną próbę unicode." ""
Oczekuje się, że kod HTML NIE będzie zawierał żadnego rodzaju „próby wprowadzenia kodu Unicode”, poprawnie sformułowanego lub nie. Musi z konieczności zawierać znaki Unicode zakodowane w jakimś kodowaniu, które jest zwykle dostarczane z góry ... poszukaj "charset".
Wydaje się, że zakładasz, że zestaw znaków to UTF-8… na jakiej podstawie? Bajt „\ xA0” wyświetlany w komunikacie o błędzie wskazuje, że możesz mieć jednobajtowy zestaw znaków, np. Cp1252.
Jeśli nie możesz wyciągnąć żadnego sensu z deklaracji na początku HTML, spróbuj użyć programu chardet, aby dowiedzieć się, jakie jest prawdopodobne kodowanie.
Dlaczego oznaczyłeś swoje pytanie „wyrażeniem regularnym”?
Zaktualizuj po zastąpieniu całego pytania pytaniem innym niż pytanie:
źródło
Jeśli masz ciąg
line
, możesz użyć.encode([encoding], [errors='strict'])
metody dla ciągów do konwersji typów kodowania.line = 'my big string'
line.encode('ascii', 'ignore')
Aby uzyskać więcej informacji na temat obsługi ASCII i Unicode w Pythonie, jest to naprawdę przydatna witryna: https://docs.python.org/2/howto/unicode.html
źródło
Myślę, że odpowiedź jest, ale tylko w kawałkach, co utrudnia szybkie rozwiązanie problemu, np
Weźmy przykład, załóżmy, że mam plik, który ma pewne dane w następującej formie (zawierającej znaki ascii i non-ascii)
10.01.17, 21:36 - Ziemia: Witamy ��
a my chcemy zignorować i zachować tylko znaki ascii.
Ten kod zrobi:
i wpisz (rline)
źródło
Pracuje dla mnie
źródło
Wygląda na to, że używasz Pythona 2.x. Python 2.x domyślnie używa ascii i nie ma informacji o Unicode. Stąd wyjątek.
Po prostu wklej poniższą linię po shebang, zadziała
źródło
coding
komentarz nie jest magicznym lekarstwem na wszystko. Musisz wiedzieć, dlaczego generowany jest błąd, to rozwiązuje problem tylko wtedy, gdy w źródle Pythona są złe znaki. Wydaje się, że tak nie jest w przypadku tego pytania.