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的子库来进行编码检测,并将其转换为Unicode。
然而,并不是所有时候,Unicode能够正确猜测编码。由于文档是逐字节搜索以猜测编码,这会花费很多时间。如果您已经知道编码,可以通过将其作为from_encoding传递给BeautifulSoup构造函数来节省时间并避免错误。
以下是一个示例,其中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,却出现错误结果时,可以使用它。
>>> 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>
在上面的例子中,如果你注意到,标签已经被重写以反映出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,该死
Unicode,该死主要用于当输入的文档格式未知(主要是外语)时,我们希望将其编码为某种已知格式(Unicode),同时我们不需要Beautifulsoup来完成所有这些。