如何防止BeautifulSoup4在汤中添加额外的标签?

时间:2013-04-12 21:01:17

标签: python beautifulsoup

在3之前的BeautifulSoup版本中,我可以使用任何一块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>'
     ^^^^^^^^^^^^                        ^^^^^^^^^^^^^^ 

我不需要BS4添加的外部 <html><body>..</body></html> 标记。我查看了BS4文档并在类中搜索但是找不到任何设置来抑制输出中的额外标记。我该怎么做?降级到v3不是一种选择,因为BS3中使用的SGML解析器不如BS4可用的lxmlhtml5lib解析器好。

2 个答案:

答案 0 :(得分:7)

如果您希望您的代码能够在每个人的计算机上运行,​​无论他们安装了哪些解析器等(基于lxml构建的libxml2版本2.9与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所说:

  

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

     

但如果文档形式不完整,不同的解析器会给出不同的结果。

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

答案 1 :(得分:1)

正如旧BeautifulStoneSoup documentation中所述:

  

BeautifulSoup类充满了类似Web浏览器的启发式方法,用于划分HTML作者的意图。但XML没有固定的标记集,因此这些启发式方法不适用。所以BeautifulSoup不能很好地完成XML。

     

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

BeautifulSoup4 docs

  

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

也许这会产生你想要的东西。