BeautifulSoup Parse Tree上的深度优先遍历

时间:2011-01-27 08:54:33

标签: python beautifulsoup tree-traversal

有没有办法在BeautifulSoup解析树上进行DFT?我正在尝试做一些事情,比如从根开始,通常,获取所有子元素,然后为每个子元素获取他们的孩子等等,直到我点击终端节点,此时我将建立我的方式备份树。问题是我似乎找不到允许我这样做的方法。我找到了findChildren方法,但这似乎只是将整个页面放在一个列表中多次,每个后续条目都减少了。我可能能够使用它来进行遍历,但是除了列表中的最后一个条目之外,它似乎没有任何方法可以将条目标识为终端节点。有什么想法吗?

2 个答案:

答案 0 :(得分:10)

recursiveChildGenerator()已经这样做了:

soup = BeautifulSoup.BeautifulSoup(html)
for child in soup.recursiveChildGenerator():
     name = getattr(child, "name", None)
     if name is not None:
         print name
     elif not child.isspace(): # leaf node, don't print spaces
         print child

输出

来自@msalvadores's answer的html:

html
ul
li
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
li
Aliquam tincidunt mauris eu risus.
li
Vestibulum auctor dapibus neque.
html

注意:html打印两次,因为the example包含两个打开<html>标记。

答案 1 :(得分:5)

我认为您可以使用方法“childGenerator”并以递归方式使用此方法以DFT方式解析树。

def recursiveChildren(x):
   if "childGenerator" in dir(x):
      for child in x.childGenerator():
          name = getattr(child, "name", None)
          if name is not None:
             print "[Container Node]",child.name
          recursiveChildren(child)
    else:
       if not x.isspace(): #Just to avoid printing "\n" parsed from document.
          print "[Terminal Node]",x

if __name__ == "__main__":
    soup = BeautifulSoup(your_data)
    for child in soup.childGenerator():
        recursiveChildren(child)

使用"childGenerator" in dir(x),我们确保元素是容器,NavigableStrings等终端节点不是容器,不包含子节点。

对于某些示例HTML,例如:

<html>
<ul>
   <li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
   <li>Aliquam tincidunt mauris eu risus.</li>
   <li>Vestibulum auctor dapibus neque.</li>
</ul>
</html>

此脚本打印...

[Container Node] ul
[Container Node] li
[Terminal Node] Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
[Container Node] li
[Terminal Node] Aliquam tincidunt mauris eu risus.
[Container Node] li
[Terminal Node] Vestibulum auctor dapibus neque.