BeautifulSoup:<p>的奇怪行为

时间:2018-02-09 18:41:03

标签: python beautifulsoup

我有以下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>
"""

可以看到这样(不确定它是否有帮助,但我喜欢图表): enter image description here

如果我使用以下代码:

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。

1 个答案:

答案 0 :(得分:4)

p elements只能包含phrasing content,因此您所拥有的实际上是无效的HTML。以下是it's parsed

的示例
  

例如,在措辞内容中不允许使用form元素,   因为当解析为HTML时,form元素的开始标记将暗示a   p元素的结束标记。因此,以下标记导致两个   段落,而不是一个:

<p>Welcome. <form><label>Name:</label> <input></form>
     

解析完全如下:

<p>Welcome. </p><form><label>Name:</label> <input></form>

您可以确认这是浏览器解析HTML的方式(如图64所示):

Chrome parsing invalid HTML

lxml正确处理此问题,html5lib也是如此。 html.parser并未实施大部分HTML5规范,也不关心这些怪癖。

如果您不希望将来因这些解析差异而感到沮丧,我建议您坚持使用lxmlhtml5lib。当您在浏览器的DOM检查器中看到的内容与您的代码解析它的方式不同时,这很烦人。