python - 使用 BeautifulSoup 4 和递归捕获 HTML 嵌套标签的结构

标签 python python-3.x beautifulsoup

我一直在尝试使用 BeautifulSoup4 和递归来捕获 HTML 页面的布局。这个想法是将 parent 的数据结构链接到 child ,例如,这样的布局:

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

将存储在这样的列表中:

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

我很难找到关于这个特定问题的问答,所以我尝试使用递归来建模一个函数来遍历 directories因为它们非常相似。

这是我在 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

解析Wikipedia Home Page给我一个输出:

------
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

这正是我所需要的,但是它需要两个 for 循环,并且需要更多循环才能获得所有子级。此外,我不知道将来的网站嵌套了多少标签。所以我将 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多次,似乎没有内置功能。有什么建议吗?或者这不是实现我所寻求目标的可行方法吗?

最佳答案

我不认为嵌套列表正是您在这里寻找的。如果您要做的只是构建一个标签树,我会使用嵌套字典。如果您要提取任何其他信息,我仍会使用它们。

这个递归函数将构建一个嵌套字典“树”

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': []}]}]}]}]}]}

关于python - 使用 BeautifulSoup 4 和递归捕获 HTML 嵌套标签的结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52863277/

相关文章:

python - 在运行时获取进程的输出

python - 打印 csv 文件中的信息

python - Pytest:如何解决测试文件夹中缺少 __init__.py 的问题?

python - psycopg2.sql 使用 sql.Identifier 插入变量类型导致类型 "integer"不存在

python - Seaborn:如何在 catplot 中设置自定义 "hue"标签而不是自动标签

python-3.x - 分割图像上的重叠预测

python - 将 Pip 包传输到 conda

python - Beautiful Soup - 任何指定的编码都会破坏美化格式

python - 使用 BS4 将 HTML 表抓取为 CSV 以与 Pandas 一起使用

python - 迭代列表元组