17

在 BeautifulSoup 3 之前的版本中,我可以获取任何 HTML 块并以这种方式获得字符串表示:

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 解析器不如BS4 中可用的lxml或解析器好。html5lib

4

2 回答 2

8

如果您希望您的代码在每个人的机器上工作,无论他们安装了哪个解析器等(基于2.9 和 2.8lxml构建的相同版本的行为非常不同,stdlib在 2.7.2 和 2.7 之间有一些根本性的变化.3, ...),您几乎需要处理所有合法结果。libxml2html.parser

如果你知道你有一个片段,像这样的东西会给你这个片段:

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

当然,如果你知道你的片段是一个 single div,那就更容易了——但是想一个你知道的用例并不容易:

soup4 = BeautifulSoup('<div><b>soup 4</b></div>')
return soup4.div

如果你想知道为什么会这样:

BeautifulSoup用于解析 HTML 文档。HTML 片段不是有效的文档。它非常接近于文档,但这还不足以保证您能准确地取回您所提供的内容。

正如解析器之间的差异所说:

HTML解析器之间也存在差异。如果你给 Beautiful Soup 一个格式完美的 HTML 文档,这些差异就无关紧要了。一个解析器会比另一个更快,但它们都会为您提供一个看起来与原始 HTML 文档完全相同的数据结构。

但是如果文档的格式不完美,不同的解析器会给出不同的结果。

因此,虽然没有记录这种确切的差异,但它只是一种特殊情况。

于 2013-04-12T21:54:22.320 回答
1

正如旧BeautifulStoneSoup 文档中所述:

BeautifulSoup 类充满了类似网络浏览器的启发式方法,用于预测 HTML 作者的意图。但是 XML 没有固定的标记集,因此这些启发式方法不适用。所以 BeautifulSoup 不能很好地处理 XML。

使用 BeautifulStoneSoup 类来解析 XML 文档。这是一个通用类,没有任何 XML 方言的特殊知识和非常简单的标签嵌套规则......

BeautifulSoup4 文档中:

不再有用于解析 XML 的 BeautifulStoneSoup 类。要解析 XML,您将“xml”作为第二个参数传递给 BeautifulSoup 构造函数。出于同样的原因,BeautifulSoup 构造函数不再识别 isHTML 参数。

也许这会产生你想要的。

于 2013-04-12T21:29:29.857 回答