Piękna zupa - kodowanie
Wszystkie dokumenty HTML lub XML są zapisywane w określonym kodowaniu, takim jak ASCII lub UTF-8. Jednak po załadowaniu tego dokumentu HTML / XML do BeautifulSoup został on przekonwertowany na Unicode.
>>> markup = "<p>I will display £</p>"
>>> Bsoup = BeautifulSoup(markup)
>>> Bsoup.p
<p>I will display £</p>
>>> Bsoup.p.string
'I will display £'
Powyższe zachowanie wynika z tego, że BeautifulSoup wewnętrznie używa podbiblioteki o nazwie Unicode, Dammit do wykrywania kodowania dokumentu, a następnie konwertuje go na Unicode.
Jednak nie zawsze, Unicode, Dammit odgaduje poprawnie. Ponieważ dokument jest przeszukiwany bajt po bajcie, aby odgadnąć kodowanie, zajmuje to dużo czasu. Możesz zaoszczędzić trochę czasu i uniknąć błędów, jeśli znasz już kodowanie, przekazując je do konstruktora BeautifulSoup jako from_encoding.
Poniżej znajduje się przykład, w którym BeautifulSoup błędnie identyfikuje dokument ISO-8859-8 jako ISO-8859-7 -
>>> markup = b"<h1>\xed\xe5\xec\xf9</h1>"
>>> soup = BeautifulSoup(markup)
>>> soup.h1
<h1>νεμω</h1>
>>> soup.original_encoding
'ISO-8859-7'
>>>
Aby rozwiązać powyższy problem, przekaż go do BeautifulSoup za pomocą from_encoding -
>>> soup = BeautifulSoup(markup, from_encoding="iso-8859-8")
>>> soup.h1
<h1>ולש </h1>
>>> soup.original_encoding
'iso-8859-8'
>>>
Kolejną nową funkcją dodaną z BeautifulSoup 4.4.0 jest exclude_encoding. Można go użyć, gdy nie znasz prawidłowego kodowania, ale jesteś pewien, że Unicode, Cholera pokazuje zły wynik.
>>> soup = BeautifulSoup(markup, exclude_encodings=["ISO-8859-7"])
Kodowanie wyjściowe
Dane wyjściowe z BeautifulSoup to dokument UTF-8, niezależnie od dokumentu wprowadzonego do BeautifulSoup. Poniżej dokument, w którym znajdują się polskie znaki w formacie ISO-8859-2.
html_markup = """
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=iso-8859-2">
</HEAD>
<BODY>
ą ć ę ł ń ó ś ź ż Ą Ć Ę Ł Ń Ó Ś Ź Ż
</BODY>
</HTML>
"""
>>> soup = BeautifulSoup(html_markup)
>>> print(soup.prettify())
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
</head>
<body>
ą ć ę ł ń ó ś ź ż Ą Ć Ę Ł Ń Ó Ś Ź Ż
</body>
</html>
W powyższym przykładzie, jeśli zauważysz, tag <meta> został przepisany, aby odzwierciedlić wygenerowany dokument z BeautifulSoup jest teraz w formacie UTF-8.
Jeśli nie chcesz generować danych wyjściowych w UTF-8, możesz przypisać żądane kodowanie w prettify ().
>>> print(soup.prettify("latin-1"))
b'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\n<html>\n <head>\n <meta content="text/html; charset=latin-1" http-equiv="content-type"/>\n </head>\n <body>\n ą ć ę ł ń \xf3 ś ź ż Ą Ć Ę Ł Ń \xd3 Ś Ź Ż\n </body>\n</html>\n'
W powyższym przykładzie zakodowaliśmy cały dokument, jednak możesz zakodować dowolny element w zupie tak, jakby był ciągiem znaków Pythona -
>>> soup.p.encode("latin-1")
b'<p>0My first paragraph.</p>'
>>> soup.h1.encode("latin-1")
b'<h1>My First Heading</h1>'
Wszelkie znaki, których nie można przedstawić w wybranym kodowaniu, zostaną przekonwertowane na numeryczne odniesienia do encji XML. Poniżej znajduje się jeden taki przykład -
>>> markup = u"<b>\N{SNOWMAN}</b>"
>>> snowman_soup = BeautifulSoup(markup)
>>> tag = snowman_soup.b
>>> print(tag.encode("utf-8"))
b'<b>\xe2\x98\x83</b>'
Jeśli spróbujesz zakodować powyższe w „latin-1” lub „ascii”, wygeneruje „☃”, co oznacza, że nie ma dla tego reprezentacji.
>>> print (tag.encode("latin-1"))
b'<b>☃</b>'
>>> print (tag.encode("ascii"))
b'<b>☃</b>'
Unicode, cholera
Unicode, Dammit jest używany głównie wtedy, gdy przychodzący dokument jest w nieznanym formacie (głównie w języku obcym) i chcemy zakodować w jakimś znanym formacie (Unicode), a także nie potrzebujemy do tego Beautifulsoup.