首页 > 解决方案 > beautifulsoup:在某个元素之后查找元素,不一定是兄弟姐妹或孩子

问题描述

示例 html:

<div>
    <p>p1</p>
    <p>p2</p>
    <p>p3<span id="target">starting from here</span></p>
    <p>p4</p>
</div>
<div>
    <p>p5</p>
    <p>p6</p>
</div>
<p>p7</p>

我想搜索<p>s 但前提是它的位置在 之后span#target

在上面的示例中,它应该返回 p4、p5、p6 和 p7。

我试图先获取所有<p>s 然后过滤,但是我也不知道如何判断一个元素是否在之后span#target

标签: beautifulsoup

解决方案


您可以通过使用find_all_nextbeautifulsoup 中的函数来做到这一点。

from bs4 import BeautifulSoup

doc = # Read the HTML here

# Parse the HTML
soup = BeautifulSoup(doc, 'html.parser')

# Select the first element you want to use as the reference
span = soup.select("span#target")[0]

# Find all elements after the `span` element that have the tag - p
print(span.find_all_next("p"))

上面的代码片段将导致

[<p>p4</p>, <p>p5</p>, <p>p6</p>, <p>p7</p>]

编辑:根据 OP- 比较以下位置的请求

如果要比较 2 个元素的位置,则必须依赖sourcelinesourcepos提供的html.parserhtml5lib解析选项。

首先,将参考元素的sourceline和/或存储在变量中。sourcepos

span_srcline = span.sourceline
span_srcpos = span.sourcepos

(你实际上不必存储它们,span.sourcepos只要你有存储就可以直接span存储)

现在遍历结果find_all_next并比较值-

for tag in span.find_all_next("p"):
    print(f'line diff: {tag.sourceline - span_srcline}, pos diff: {tag.sourcepos - span_srcpos}, tag: {tag}')

不过,您很可能对行号感兴趣,因为sourcepos表示line 上的位置。

但是,对于每个解析器来说sourcelinesourcepos它们的含义略有不同。检查文档以获取该信息


推荐阅读