Beautiful Soup - Кодирование
Все документы HTML или XML написаны в определенной кодировке, такой как ASCII или UTF-8. Однако при загрузке этого HTML / XML-документа в BeautifulSoup он был преобразован в Unicode.
>>> markup = "<p>I will display £</p>"
>>> Bsoup = BeautifulSoup(markup)
>>> Bsoup.p
<p>I will display £</p>
>>> Bsoup.p.string
'I will display £'
Вышеуказанное поведение связано с тем, что BeautifulSoup внутренне использует подбиблиотеку Unicode, Dammit, чтобы определять кодировку документа и затем преобразовывать ее в Unicode.
Однако не всегда Unicode, черт возьми, угадывает правильно. Поскольку документ просматривается побайтово, чтобы угадать кодировку, это занимает много времени. Вы можете сэкономить время и избежать ошибок, если вы уже знаете кодировку, передав ее конструктору BeautifulSoup как from_encoding.
Ниже приведен один пример, в котором BeautifulSoup ошибочно идентифицирует документ ISO-8859-8 как ISO-8859-7 -
>>> markup = b"<h1>\xed\xe5\xec\xf9</h1>"
>>> soup = BeautifulSoup(markup)
>>> soup.h1
<h1>νεμω</h1>
>>> soup.original_encoding
'ISO-8859-7'
>>>
Чтобы решить указанную выше проблему, передайте ее BeautifulSoup с помощью from_encoding -
>>> soup = BeautifulSoup(markup, from_encoding="iso-8859-8")
>>> soup.h1
<h1>ולש </h1>
>>> soup.original_encoding
'iso-8859-8'
>>>
Еще одна новая функция, добавленная в BeautifulSoup 4.4.0, - exclude_encoding. Его можно использовать, если вы не знаете правильную кодировку, но уверены, что Unicode, Dammit, показывает неправильный результат.
>>> soup = BeautifulSoup(markup, exclude_encodings=["ISO-8859-7"])
Кодировка вывода
Результатом BeautifulSoup является документ UTF-8, независимо от того, какой документ был введен в BeautifulSoup. Ниже документ, где есть символы полировки в формате 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>
В приведенном выше примере, если вы заметили, тег <meta> был переписан, чтобы отразить сгенерированный документ из BeautifulSoup теперь в формате UTF-8.
Если вам не нужен сгенерированный вывод в UTF-8, вы можете назначить желаемую кодировку в 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'
В приведенном выше примере мы закодировали весь документ, однако вы можете кодировать любой конкретный элемент в супе, как если бы они были строкой Python -
>>> soup.p.encode("latin-1")
b'<p>0My first paragraph.</p>'
>>> soup.h1.encode("latin-1")
b'<h1>My First Heading</h1>'
Любые символы, которые не могут быть представлены в выбранной вами кодировке, будут преобразованы в числовые ссылки на объекты XML. Ниже один из таких примеров -
>>> 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>'
Если вы попытаетесь закодировать указанное выше в «latin-1» или «ascii», будет сгенерировано «☃», указывающее, что для этого нет представления.
>>> print (tag.encode("latin-1"))
b'<b>☃</b>'
>>> print (tag.encode("ascii"))
b'<b>☃</b>'
Юникод, черт возьми
Unicode, Dammit используется в основном, когда входящий документ находится в неизвестном формате (в основном на иностранном языке), и мы хотим кодировать в каком-то известном формате (Unicode), а также нам не нужен Beautifulsoup для всего этого.