Beautiful Soup和Python. 递归获取所有节点时出现“超出最大递归深度”错误
我在使用一个叫FreeMind的程序,这个程序可以创建树状结构,并将它们导出为HTML文件。我需要获取这棵树的每一个“路径”,然后把它们放到一个列表里,这样我就可以单独处理每一个“路径”。

比如说,从这段代码中:
<body>
<p>Example</p>
<ul>
<li>
The First List
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</li>
<li>
The Second List
<ul>
<li>4.1</li>
<li>4.2</li>
</ul>
</li>
</ul>
</body>
我需要提取出接下来的几个独立的代码分支:
<body>
<p>Example</p>
<ul>
<li>
The First List
<ul>
<li>1</li>
</ul>
</li>
</ul>
</body>
<body>
<p>Example</p>
<ul>
<li>
The First List
<ul>
<li>2</li>
</ul>
</li>
</ul>
</body>
<body>
<p>Example</p>
<ul>
<li>
The First List
<ul>
<li>3</li>
</ul>
</li>
</ul>
</body>
<body>
<p>Example</p>
<ul>
<li>
The Second List
<ul>
<li>4.1</li>
</ul>
</li>
</ul>
</body>
<body>
<p>Example</p>
<ul>
<li>
The Second List
<ul>
<li>4.2</li>
</ul>
</li>
</ul>
</body>
我尝试了这段代码,但出现了错误:“调用Python对象时超出了最大递归深度”。
from bs4 import BeautifulSoup
parsed = BeautifulSoup(open("example.html"))
body = parsed.body
def all_nodes(obj):
for node in obj:
print node
all_nodes(node)
print all_nodes(body)
我想我应该解释一下我后面想用这些东西做什么。我在FreeMind里写测试用例,并且我正在尝试写一个工具,能够生成一个包含所有测试用例的CSV表格。但现在我只是想把所有的测试用例提取成文本。
1 个回答
2
这里有一种方法可以做到。虽然这并不是最简单或最符合Python风格的做法。我个人不太喜欢这个解决方案,但对你来说应该是一个不错的起点。我敢打赌还有更优雅、更简洁的方法可以实现同样的功能。
这个思路是遍历所有没有子元素的元素。对于每一个这样的元素,递归地遍历它的父元素,直到我们找到body
为止:
from bs4 import BeautifulSoup, Tag
data = """
your xml goes here
"""
soup = BeautifulSoup(data)
for element in soup.body.find_all():
children = element.find_all()
if not children:
tag = Tag(name=element.name)
tag.string = element.string
for parent in element.parentGenerator():
parent = Tag(name=parent.name)
parent.append(tag)
tag = parent
if tag.name == 'body':
break
print tag
这样会产生:
<body><p>Example</p></body>
<body><ul><li><ul><li>1</li></ul></li></ul></body>
<body><ul><li><ul><li>2</li></ul></li></ul></body>
<body><ul><li><ul><li>3</li></ul></li></ul></body>
<body><ul><li><ul><li>4.1</li></ul></li></ul></body>
<body><ul><li><ul><li>4.2</li></ul></li></ul></body>
更新(也写入父元素的文本):
soup = BeautifulSoup(data)
for element in soup.body.find_all():
children = element.find_all()
if not children:
tag = Tag(name=element.name)
tag.string = element.string
for parent in element.parentGenerator():
parent_tag = Tag(name=parent.name)
if parent.string:
parent_tag.string = parent.string
parent_tag.append(tag)
tag = parent_tag
if tag.name == 'body':
break
print tag
希望这对你有帮助。