使用Unicode的Beautiful Soup,Dammit

优质
小牛编辑
134浏览
2023-12-01

当你的文档被剖析之后,它就自动被转换为unicode。 Beautiful Soup 只存储Unicode字符串。

from BeautifulSoup import BeautifulSoup
soup = BeautifulSoup("Hello")
soup.contents[0]
# u'Hello'
soup.originalEncoding
# 'ascii'

使用UTF-8编码的日文文档例子:

from BeautifulSoup import BeautifulSoup
soup = BeautifulSoup("\xe3\x81\x93\xe3\x82\x8c\xe3\x81\xaf")
soup.contents[0]
# u'\u3053\u308c\u306f'
soup.originalEncoding
# 'utf-8'

str(soup)
# '\xe3\x81\x93\xe3\x82\x8c\xe3\x81\xaf'

# Note: this bit uses EUC-JP, so it only works if you have cjkcodecs
# installed, or are running Python 2.4.
soup.__str__('euc-jp')
# '\xa4\xb3\xa4\xec\xa4\xcf'

Beautiful Soup 使用一个称为UnicodeDammit 的类去来检测文档的编码,并将其转换为Unicode。 如果你需要为其他文档(没有石油Beautiful Soup剖析过得文档)使用这转换,你也可以 直接使用UnicodeDammit。 它是基于Universal Feed Parser开发的。

如果你使用Python2.4之前的版本,请下载和安装cjkcodecs 以及iconvcodec 是python支持更多的编码,特别是CJK编码。要想更好地自动检测, 你也要安装chardet

Beautiful Soup 会按顺序尝试不同的编码将你的文档转换为Unicode:

  • 可以通过fromEncoding参数传递编码类型给soup的构造器
  • 通过文档本身找到编码类型:例如XML的声明或者HTML文档http-equiv的META标签。 如果Beautiful Soup在文档中发现编码类型,它试着使用找到的类型转换文档。 但是,如果你明显的指定一个编码类型, 并且成功使用了编码:这时它会忽略任何它在文档中发现的编码类型。
  • 通过嗅探文件开头的一下数据,判断编码。如果编码类型可以被检测到, 它将是这些中的一个:UTF-*编码,EBCDIC或者ASCII。
  • 通过chardet 库,嗅探编码,如果你安装了这个库。
  • UTF-8
  • Windows-1252

Beautiful Soup总是会猜对它可以猜测的。但是对于那些没有声明以及有着奇怪编码 的文档,它会常常会失败。这时,它会选择Windows-1252编码,这个可能是错误的编码。 下面是EUC-JP的例子,Beautiful Soup猜错了编码。(重申一下:因为它使用了EUC-JP, 这个例子只会在 python 2.4或者你安装了cjkcodecs的情况下才工作。):

from BeautifulSoup import BeautifulSoup
euc_jp = '\xa4\xb3\xa4\xec\xa4\xcf'

soup = BeautifulSoup(euc_jp)
soup.originalEncoding
# 'windows-1252'

str(soup)
# '\xc2\xa4\xc2\xb3\xc2\xa4\xc3\xac\xc2\xa4\xc3\x8f'     # Wrong!

但如果你使用fromEncoding参数指定编码, 它可以正确的剖析文档,并可以将文档转换为UTF-8或者转回EUC-JP。

soup = BeautifulSoup(euc_jp, fromEncoding="euc-jp")
soup.originalEncoding
# 'windows-1252'

str(soup)
# '\xe3\x81\x93\xe3\x82\x8c\xe3\x81\xaf'                 # Right!

soup.__str__(self, 'euc-jp') == euc_jp
# True

如果你指定Beautiful Soup使用 Windows-1252编码(或者类似的编码如ISO-8859-1,ISO-8859-2), Beautiful Soup会找到并破坏文档的smart quotes以及其他的Windows-specific 字符。 这些字符不会转换为相应的Unicode,而是将它们变为HTML entities(BeautifulSoup) 或者XML entitis(BeautifulStoneSoup)。

但是,你可以指定参数smartQuotesTo=None 到soup构造器:这时 smart quotes会被正确的转换为Unicode。你也可以指定smartQuotesTo为"xml"或"html" 去改变BeautifulSoupBeautifulStoneSoup的默认操作。

from BeautifulSoup import BeautifulSoup, BeautifulStoneSoup
text = "Deploy the \x91SMART QUOTES\x92!"

str(BeautifulSoup(text))
# 'Deploy the ‘SMART QUOTES’!'

str(BeautifulStoneSoup(text))
# 'Deploy the ‘SMART QUOTES’!'

str(BeautifulSoup(text, smartQuotesTo="xml"))
# 'Deploy the ‘SMART QUOTES’!'

BeautifulSoup(text, smartQuotesTo=None).contents[0]
# u'Deploy the \u2018SMART QUOTES\u2019!'