在HTML文档中使用Python和lxml向上搜索



我有一个结构如下的HTML文档:

<html>
  <li>
     <a href="" />a1</a>
     <other tags ... />
     <li>
        <a href="">a2</a>
        <another one tag ... />
        <a name=3>
     </li>
  </li>
  <li>
    ...
  </li>

我需要找到位于 li 元素下的所有父元素,并为 name=3 的元素构建路径。在此示例中,它应该是 a1/a2。我使用 lxml 并编写了以下 Python 代码:

import lxml
...
def get_path_for_series(self, html, series):
    current = html.xpath('//a[@name="%s"]' % series)[0]
    path = list()
    while True:
        category = current.xpath('.//ancestor::li[1]//a[1]')
        if len(category) == 0:
            break
        path.append(self.clear(category[0].text_content()))
        current = category[0]
    return '/'.join(path)

它正确地找到了第一个元素,但随后我有一个无限循环。我做错了什么?

您的 while 循环首先遍历到祖先 li 并获取后代a[1]。然后从当前a,在下一个循环中,您的 XPath 将再次遍历到同一个li祖先并返回相同的a元素,这将永远持续下去(添加print current进行验证。我在同一内存位置看到了Element,这意味着它们是同一个实例,一遍又一遍地打印)。

您可以尝试从目标a[@name="%s"]向上移动树状态,并反向连接收集的路径步骤,如下所示:

def get_path_for_series(self, html, series):
    current = html.xpath('//a[@name="%s"]' % series)[0]
    path = list()
    parent = current.xpath('parent::li')
    while parent:
        a = parent[0].xpath('a[1]')[0]
        path.append(a.text)
        parent = parent[0].xpath('parent::li')
    # join `path` in reversed order
    return '/'.join(path[::-1])

最新更新