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 для всего этого.