Если вы используете BeautifulSoup 4.7+, в нем улучшена поддержка CSS-селекторов.Он обрабатывает множество селекторов до уровня CSS 4 и несколько пользовательских, таких как :contains()
.В дополнение ко всему этому, он обрабатывает сложные селекторы в псевдоклассах, таких как :not()
, который должен обрабатывать уровень 4, но недавно они выдвинули эту поддержку в поддержку селектора уровня 5 CSS.
в этом примере мы будем использовать пользовательский селектор :contains
для поиска диапазонов, которые содержат текст Review
.Кроме того, мы скажем, что не хотим, чтобы оно совпадало с div.class span
.
from bs4 import BeautifulSoup
html = """
<div>
<p><span>Review: Let's find this</span></p>
</div>
<div class="child">
<p><span>Review: Do not want this</span></p>
</div>
"""
soup = BeautifulSoup(html, features="html.parser")
spans = soup.select('span:contains(Review):not(div.child span)')
print(spans)
Выход
[<span>Review: Let's find this</span>]
В зависимости от вашего случая, возможно :contains
isnнедостаточно крепкийВ этом случае вы все еще можете сделать что-то подобное.Soup Sieve - это базовая библиотека, включенная в Beautiful Soup 4.7+, и вы можете импортировать ее напрямую, чтобы отфильтровать возвраты регулярного выражения:
from bs4 import BeautifulSoup
import soupsieve as sv
import re
html = """
<div>
<p><span>Review: Let's find this</span></p>
</div>
<div class="child">
<p><span>Review: Do not want this</span></p>
</div>
"""
soup = BeautifulSoup(html, features="html.parser")
spans = soup.find_all("span", text=re.compile("Review"))
spans = sv.filter(':not(div.child span)', spans)
print(spans)
Вывод
[<span>Review: Let's find this</span>]