2013-11-25 13 views
16

Używam programu w języku Python, który pobiera stronę kodowaną w UTF-8, a ja rozpakowuję tekst z kodu HTML za pomocą BeautifulSoup.Jak poprawnie parsować kodowany kodowany w UTF-8 kod HTML do ciągów Unicode z BeautifulSoup?

Jednak, kiedy piszę ten tekst do pliku (lub wypiszę go na konsoli), zostanie zapisany w nieoczekiwanym kodowaniu.

Przykładowy program:

import urllib2 
from BeautifulSoup import BeautifulSoup 

# Fetch URL 
url = 'http://www.voxnow.de/' 
request = urllib2.Request(url) 
request.add_header('Accept-Encoding', 'utf-8') 

# Response has UTF-8 charset header, 
# and HTML body which is UTF-8 encoded 
response = urllib2.urlopen(request) 

# Parse with BeautifulSoup 
soup = BeautifulSoup(response) 

# Print title attribute of a <div> which uses umlauts (e.g. können) 
print repr(soup.find('div', id='navbutton_account')['title']) 

Running to daje wynik:

# u'Hier k\u0102\u015bnnen Sie sich kostenlos registrieren und/oder einloggen!' 

Jednak Spodziewam się ciąg Python Unicode do renderowania ö w słowie können jak \xf6:

# u'Hier k\xf6bnnen Sie sich kostenlos registrieren und/oder einloggen!' 

Próbowałem przekazać "z Kodowanie 'parametru do BeautifulSoup i próbowanie obiektu read() i decode(), ale albo nie robi różnicy, albo powoduje błąd.

Z polecenia curl www.voxnow.de | hexdump -C, widzę, że strona internetowa jest rzeczywiście kodowanie UTF-8 (czyli zawiera 0xc3 0xb6) dla ö Charakter:

 20 74 69 74 6c 65 3d 22 48 69 65 72 20 6b c3 b6 | title="Hier k..| 
     6e 6e 65 6e 20 53 69 65 20 73 69 63 68 20 6b 6f |nnen Sie sich ko| 
     73 74 65 6e 6c 6f 73 20 72 65 67 69 73 74 72 69 |stenlos registri| 

jestem poza granicy moich możliwości Pythona , więc nie mam pojęcia, jak dalej to debugować. Jakakolwiek rada?

+0

Dziwne .. jak '\ u0102 \ u015b 'to' 'Ăś'' .. – aIKid

+2

Czy nie jest to duplikat tego pytania: http://stackoverflow.com/questions/7219361/python-and-beautifulsoup-encoding-issues?rq=1 – justhalf

+0

@justhalf Myślę, że widziałem to pytanie, ale nie myślę, że mam te same wyniki. Ale sprawdzę jeszcze raz, dziękuję. –

Odpowiedz

19

Jak justhalf zwraca uwagę powyżej, tutaj moje pytanie jest w zasadzie kopią this question.

Treść HTML została zgłoszona jako zakodowana w systemie UTF-8 i, w większości przypadków, z wyjątkiem jednego lub dwóch fałszywych znaków UTF-8.

To najwyraźniej myli BeautifulSoup o których kodowanie jest w użyciu, a przy próbie pierwszego dekodowania jako UTF-8 przy przechodzeniu zawartości do BeautifulSoup jak tym:

soup = BeautifulSoup(response.read().decode('utf-8')) 

bym pojawia się błąd:

UnicodeDecodeError: 'utf8' codec can't decode bytes in position 186812-186813: 
        invalid continuation byte 

Przyglądając się dokładniej sygnałowi wyjściowemu, było wystąpieniem znaku Ü które błędnie zakodowany jako nieprawidłową sekwencją bajtów 0xe3 0x9c, zamiast odpowiedniego 0xc3 0x9c.

Ponieważ obecnie highest-rated answer na to pytanie wskazuje, nieprawidłowych znaków UTF-8 mogą być usunięte podczas analizowania, tak, że tylko prawidłowe dane są przekazywane do BeautifulSoup:

soup = BeautifulSoup(response.read().decode('utf-8', 'ignore')) 
3

Kodowanie wynik utf-8 wydaje się działać dla mnie:

print (soup.find('div', id='navbutton_account')['title']).encode('utf-8') 

To daje:

Hier können Sie sich kostenlos registrieren und/oder einloggen! 
+0

Hmm .. Próbowałem na kilku maszynach (z Pythonem 2.7.3); ten kod daje mi cztery bajty zamiast dwóch, które otrzymujesz dla znaku 'ö': c4 82 c5 9b' –

Powiązane problemy