Использование BeautifulSoup 4 и рекурсии для захвата структуры вложенных тегов HTML - PullRequest
0 голосов
/ 17 октября 2018

Я пытался запечатлеть макет HTML-страницы, используя BeautifulSoup4 и рекурсию.Идея состоит в том, чтобы связать структуры данных родителей с детьми, например, такую ​​разметку:

<html>
 <h1>
  <!--Contents-->
 </h1>
 <div> 
  <div> 
   <!--Contents-->
  </div>
 </div>
</html>

Будет храниться в таком списке:

html = [ h1 , div ] # Where h1 and div are also lists also containing lists

I 'У меня были трудности с поиском вопросов и ответов по этой конкретной проблеме, поэтому вместо этого я попытался смоделировать функцию, используя рекурсию для обхода каталогов , поскольку они очень похожи.

Это мойтекущая функция в Python 3, которая должна вкладывать теги в списки:

def listGen(l , hObj):
    # Where hObj is a BS4 object and l is a sorted lists containing direct children to the html tag
    z = []
    for x in l:
        z.append(hObj.find(x).children)

    def expand(xlist1):
        # Where xlist1 is a list generator 
        for n in xlist1:
            if n.name is not None:
                print(n.name)
                for n2 in hObj.find(n.name).children:
                    if n2.name is not None:
                        print(n2.name , "--") #Debugging print              
        return z #Temporary
    for x in z:
        print("------")
        expand(x , 0)
    return z

Анализ домашней страницы Википедии дает мне вывод:

------
h1
img --
div --
div
div --
strong --
div
div --
strong --
div
div --
strong --
div
div --
strong --
div
div --
strong --
hr
div
div --
strong --
p
small --
small --
small --
script
script
script
style
------
meta
title
meta
script
meta
link
link
link
style
style
link
link

именно то, что мне нужно, , однако для цикла требуется два, и еще много потребуется, чтобы получить всех детей.Кроме того, я бы не знал, сколько тегов вкладывают в будущие сайты.Поэтому я изменил функцию expand на:

def expand(xlist1 , depth): 
    l1 = list(xlist1)
    if depth < len(l1):
        for n in l1[depth]:
            if n is not None:
                if hObj.find(l1[depth].name).children:
                    return expand(hObj.find(l1[depth].name).children , 0)
            if n is None:
                print(2) # Debugging print
                return expand(xlist1 , depth + 1)
    if depth >= len(l1):
        return 0 # Temporary
    return 0 # Temporary

Только для того, чтобы дать мне максимум ошибок рекурсии, я перепробовал многие другие варианты безрезультатно.

У меня естьпросматривал BS4 Docs несколько раз, и, похоже, для этого нет встроенной функции.Любые предложения или это не жизнеспособный способ достичь того, что я ищу?

1 Ответ

0 голосов
/ 11 декабря 2018

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

Эта рекурсивная функция создаст "дерево" для вложенного словаря

def traverse(soup):
    if soup.name is not None:
        dom_dictionary = {}
        dom_dictionary['name'] = soup.name
        dom_dictionary['children'] = [ traverse(child) for child in soup.children if child.name is not None]
        return dom_dictionary

Мы можем использовать это так:

page = requests.get("http://example.com")
soup = BeautifulSoup(page.text, "html5lib")
traverse(soup)

Это дает нам:

{'name': '[document]',
 'children': [{'name': 'html',
   'children': [{'name': 'head',
     'children': [{'name': 'title', 'children': []},
      {'name': 'meta', 'children': []},
      {'name': 'meta', 'children': []},
      {'name': 'meta', 'children': []},
      {'name': 'style', 'children': []}]},
    {'name': 'body',
     'children': [{'name': 'div',
       'children': [{'name': 'h1', 'children': []},
        {'name': 'p', 'children': []},
        {'name': 'p', 'children': [{'name': 'a', 'children': []}]}]}]}]}]}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...