在 BeautifulSoup 3 之前的版本中,我可以采用任何 HTML block 并以这种方式获得字符串表示形式:
from BeautifulSoup import BeautifulSoup
soup3 = BeautifulSoup('<div><b>soup 3</b></div>')
print unicode(soup3)
'<div><b>soup</b></div>'
然而,对于 BeautifulSoup4,相同的操作会创建额外的标签:
from bs4 import BeautifulSoup
soup4 = BeautifulSoup('<div><b>soup 4</b></div>')
print unicode(soup4)
'<html><body><div><b>soup 4</b></div></body></html>'
^^^^^^^^^^^^ ^^^^^^^^^^^^^^
我不需要外面的 <html><body>..</body></html>
BS4 正在添加的标签。我查看了 BS4 文档并在类内部进行了搜索,但找不到任何用于抑制输出中额外标签的设置。我该怎么做?降级到 v3 不是一个选项,因为 BS3 中使用的 SGML 解析器不如 lxml
好。或 html5lib
BS4 可用的解析器。
如果你想让你的代码在每个人的机器上工作,不管他们安装了哪个解析器,等等(相同的 lxml
版本建立在 libxml2
2.9 vs. 2.8 的行为非常不同,stdlib html.parser
在 2.7.2 和 2.7.3 之间有一些根本性的变化,...),你几乎需要处理所有合法的结果。
如果你知道你有一个片段,像这样的东西会给你这个片段:
soup4 = BeautifulSoup('<div><b>soup 4</b></div>')
if soup4.body:
return soup4.body.next
elif soup4.html:
return soup4.html.next
else:
return soup4
当然,如果您知道您的片段是单个 div
,那就更容易了——但要想到一个您知道的用例就没那么容易了:
soup4 = BeautifulSoup('<div><b>soup 4</b></div>')
return soup4.div
如果您想知道为什么会发生这种情况:
BeautifulSoup
用于解析 HTML 文档。 HTML 片段不是有效文档。它非常接近文档,但这还不足以保证您会准确地取回您提供的内容。
作为Differences between parsers说:
There are also differences between HTML parsers. If you give Beautiful Soup a perfectly-formed HTML document, these differences won’t matter. One parser will be faster than another, but they’ll all give you a data structure that looks exactly like the original HTML document.
But if the document is not perfectly-formed, different parsers will give different results.
因此,虽然没有记录这种确切的差异,但这只是某些事物的特例。