在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可用的lxml
或html5lib
解析器好。
答案 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方言的特殊知识和关于标记嵌套的非常简单的规则......
不再有用于解析XML的BeautifulStoneSoup类。要解析XML,请将“xml”作为BeautifulSoup构造函数的第二个参数传递。出于同样的原因,BeautifulSoup构造函数不再识别isHTML参数。
也许这会产生你想要的东西。