Beautiful Soup 简明教程

Beautiful Soup - Encoding

所有 HTML 或 XML 文档都写入一些特定编码(如 ASCII 或 UTF-8)。但是,当您将该 HTML/XML 文档加载到 BeautifulSoup 时,它已被转换成 Unicode。

Example

from bs4 import BeautifulSoup
markup = "<p>I will display £</p>"
soup = BeautifulSoup(markup, "html.parser")
print (soup.p)
print (soup.p.string)

Output

<p>I will display £</p>
I will display £

之所以会出现以上情况,是因为 BeautifulSoup 在内部使用名为 Unicode, Dammit 的子库检测文档的编码,然后将其转换成 Unicode。

但是,并非总是 Unicode, Dammit 能正确猜测。由于要逐字节搜索文档以猜测编码,因此会花费大量时间。如果您已经知道编码,可以将其作为 from_encoding 传递到 BeautifulSoup 构造器中,这样可以节省一些时间并避免错误发生。

下面是一个 BeautifulSoup 识别错误的示例,将 ISO-8859-8 文档识别为 ISO-8859-7 −

Example

from bs4 import BeautifulSoup
markup = b"<h1>\xed\xe5\xec\xf9</h1>"
soup = BeautifulSoup(markup, 'html.parser')
print (soup.h1)

print (soup.original_encoding)

Output

<h1>翴檛</h1>
ISO-8859-7

要解决上述问题,请使用 from_encoding 将其传递到 BeautifulSoup −

Example

from bs4 import BeautifulSoup
markup = b"<h1>\xed\xe5\xec\xf9</h1>"
soup = BeautifulSoup(markup, "html.parser", from_encoding="iso-8859-8")
print (soup.h1)

print (soup.original_encoding)

Output

<h1>םולש</h1>
iso-8859-8

BeautifulSoup 4.4.0 中的另一项新功能是 exclude_encoding。在您不知道正确编码但确定 Unicode, Dammit 未显示正确结果时,可以使用它。

soup = BeautifulSoup(markup, exclude_encodings=["ISO-8859-7"])

Output encoding

BeautifulSoup 的输出是 UTF-8 文档,与输入到 BeautifulSoup 的文档无关。下面的文档中,波兰语字符采用 ISO-8859-2 格式。

Example

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>
"""

from bs4 import BeautifulSoup

soup = BeautifulSoup(markup, "html.parser", from_encoding="iso-8859-8")
print (soup.prettify())

Output

<!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"))

Output

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")
soup.h1.encode("latin-1")

Output

b'<p>My first paragraph.</p>'
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"))

Output

b'<b>\xe2\x98\x83</b>'

如果您尝试使用 "latin-1" 或 "ascii" 编码以上内容,将生成 "☃",表示不存在表示。

print (tag.encode("latin-1"))
print (tag.encode("ascii"))

Output

b'<b>☃</b>'
b'<b>☃</b>'

Unicode, Dammit

Unicode, Dammit 主要用于当传入文档为未知格式(主要是外语)且我们想要编码为某些已知格式(Unicode)时,同时我们也不需要 Beautifulsoup 来完成所有这些操作。