我有以下HTML内容:
content = """
<div>
<div> <div>div A</div> </div>
<p>P A</p>
<div> <div>div B</div> </div>
<p> P B1</p>
<p> P B2</p>
<div> <div>div C</div> </div>
<p> P C1 <div>NODE</div> </p>
</div>
"""
如果我使用以下代码:
soup = bs4.BeautifulSoup(content, "lxml")
firstDiv = soup.div
allElem = firstDiv.findAll( recursive = False)
for i, el in enumerate(allElem):
print "element ", i , " : ", el
我明白了:
element 0 : <div> <div>div A</div> </div>
element 1 : <p>P A</p>
element 2 : <div> <div>div B</div> </div>
element 3 : <p> P B1</p>
element 4 : <p> P B2</p>
element 5 : <div> <div>div C</div> </div>
element 6 : <p> P C1 </p>
element 7 : <div>NODE</div>
正如您所看到的,与元素0,2或5不同,元素6不包含其子元素。如果我将其<p>
更改为<b>
或<div>
,则会将其视为例外。为什么与<p>
有这么小的差别?我还有这个问题(如果是这个?)从4.3.2升级到4.4.6。
答案 0 :(得分:4)
p
elements只能包含phrasing content,因此您所拥有的实际上是无效的HTML。以下是it's parsed:
例如,在措辞内容中不允许使用
form
元素, 因为当解析为HTML时,form
元素的开始标记将暗示ap
元素的结束标记。因此,以下标记导致两个 段落,而不是一个:<p>Welcome. <form><label>Name:</label> <input></form>
解析完全如下:
<p>Welcome. </p><form><label>Name:</label> <input></form>
您可以确认这是浏览器解析HTML的方式(如图64所示):
lxml
正确处理此问题,html5lib
也是如此。 html.parser
并未实施大部分HTML5规范,也不关心这些怪癖。
如果您不希望将来因这些解析差异而感到沮丧,我建议您坚持使用lxml
和html5lib
。当您在浏览器的DOM检查器中看到的内容与您的代码解析它的方式不同时,这很烦人。