BeautifulSoup Parse Tree上的深度优先遍历

blc*_*llo 10 python beautifulsoup tree-traversal

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

jfs*_*jfs 11

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
Run Code Online (Sandbox Code Playgroud)

产量

对于来自@ msalvadores答案的html :

html
ul
li
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
li
Aliquam tincidunt mauris eu risus.
li
Vestibulum auctor dapibus neque.
html
Run Code Online (Sandbox Code Playgroud)

注意:html由于示例包含两个开始<html>标记,因此打印两次.

  • 谢谢 - 这对我有用!对于那些可能正在寻找相关文档的人,在 BeautifulSoup 4 中,`recursiveChildGenerator()` 被重命名为 `descendants()`。 (2认同)
  • @CharlesLanglois:要获得DFT,可以在bs4中使用`find_all(recursive=True)`。我已经更新了答案。 (2认同)

Man*_*res 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)
Run Code Online (Sandbox Code Playgroud)

随着"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>
Run Code Online (Sandbox Code Playgroud)

这个脚本打印...

[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.
Run Code Online (Sandbox Code Playgroud)