Первый обход глубины на дереве разбора BeautifulSoup - PullRequest
10 голосов
/ 27 января 2011

Есть ли способ сделать DFT на дереве разбора BeautifulSoup?Я пытаюсь сделать что-то вроде запуска в корне, обычно получить все дочерние элементы, а затем для каждого дочернего элемента получить их дочерние элементы и т.д.,Проблема в том, что я не могу найти метод, который позволил бы мне сделать это.Я нашел метод findChildren, но он, кажется, просто помещает всю страницу в список несколько раз, с уменьшением каждой последующей записи.Я мог бы использовать это для выполнения обхода, однако, кроме последней записи в списке, он не появляется, есть какой-либо способ идентифицировать записи как терминальные узлы или нет.Есть идеи?

Ответы [ 2 ]

10 голосов
/ 27 января 2011

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

Вывод

Для html из ответа @ msalvadores :

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> тега.

5 голосов
/ 27 января 2011

Я думаю, вы можете использовать метод 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.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...