15

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

4

2 回答 2

16

mytag.find_all()已经这样做了:

如果您调用 mytag.find_all(),Beautiful Soup 将检查 mytag 的所有后代:它的孩子、孩子的孩子等等

from bs4 import BeautifulSoup  # pip install beautifulsoup4

soup = BeautifulSoup("""<!doctype html>
<div id=a>A
  <div id=1>A1</div>
  <div id=2>A2</div>
</div>
<div id=b>B
  <div id=I>BI</div>
  <div id=II>BII</div>
</div>
""")

for div in soup.find_all("div", recursive=True):
    print(div.get('id'))

输出

a
1
2
b
I
II

输出证实,这是深度优先遍历。


老美汤 3 答案:

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 答案的 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由于示例包含两个开始<html>标签,因此打印了两次。

于 2011-01-27T10:53:48.643 回答
6

我认为您可以使用方法“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.
于 2011-01-27T09:27:12.090 回答