[英]BeautifulSoup lowest common ancestor
Python 的 BeautifulSoup 库是否有任何函数可以获取节点列表并返回最低的共同祖先?
如果没有,你们有没有人实现过这样的功能并愿意分享它?
我认为这就是您想要的,link1 是一个元素,而 link2 是另一个元素;
link_1_parents = list(link1.parents)[::-1]
link_2_parents = list(link2.parents)[::-1]
common_parent = [x for x,y in zip(link_1_parents, link_2_parents) if x is y][-1]
print common_parent
print common_parent.name
它基本上会从根向下遍历两个元素的父母,并返回最后一个共同的父母。
如果输入列表中的标签到最低共同祖先的距离对于输入中的每个节点都不完全相同,则接受的答案不起作用。
它还使用每个节点的每个祖先,这是不必要的,并且在某些情况下可能非常昂贵。
import collections
def lowest_common_ancestor(parents=None, *args):
if parents is None:
parents = collections.defaultdict(int)
for tag in args:
if not tag:
continue
parents[tag] += 1
if parents[tag] == len(args):
return tag
return lowest_common_ancestor(parents, *[tag.parent if tag else None for tag in args])
由于亚瑟的回答在某些情况下是不正确的。 我修改了亚瑟的答案,并给出了我的答案。 我已经用两个节点作为输入测试了 LCA 的代码。
import collections
def lowest_common_ancestor(parents=None, *args):
if parents is None:
parents = collections.defaultdict(int)
for tag in args:
parents[tag] += 1
if parents[tag] == NUM_OF_NODES:
return tag
next_arg_list = [tag.parent for tag in args if tag.parent is not None]
return lowest_common_ancestor(parents, *next_arg_list)
像这样调用函数:
list_of_tag = [tag_a, tag_b]
NUM_OF_NODES = len(list_of_tag)
lca = lowest_common_ancestor(None, *list_of_tag)
print(lca)
您还可以计算所有元素的 XPath,然后使用os.path.commonprefix
。 我不熟悉 BeautifulSoup,但在lxml
中,我已经这样做了:
def lowest_common_ancestor(nodes: list[lxml.html.HtmlElement]):
if len(set(nodes)) == 1: # all nodes are the same
return nodes[0]
tree: lxml.etree._ElementTree = nodes[0].getroottree()
xpaths = [tree.getpath(node) for node in nodes]
lca_xpath = os.path.commonprefix(xpaths)
lca_xpath = lca_xpath.rsplit('/', 1)[0] # strip partially matching tag names
return tree.xpath(lca_xpath)[0]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.