Как использовать BeautifulSoup для поиска элементов, которые встречаются перед другим элементом? - PullRequest
3 голосов
/ 07 июля 2019

Я использую BeautifulSoup 4 с Python 3.7.У меня есть следующий HTML ...

<tr>
    <td class="info"><div class="title">...</div></td>
</tr>
<tr class="ls">
    <td colspan="3">Less similar results</td>
</tr>
<tr>
    <td class="info"><div class="title">...</div></td>
</tr>

Я хотел бы извлечь DIVs с class = "title", однако я хочу найти только те, которые встречаются перед элементом в таблице, чей TDtext = "Менее похожие результаты".Прямо сейчас у меня есть это

elts = soup.find("td", class_="info").find_all("div", class_="title")

Но это возвращает все DIV с этим классом, даже те, которые произошли после элемента, для которого я хочу просмотреть.Как мне уточнить мой поиск, чтобы включить результаты только до этого конкретного TD?

Ответы [ 3 ]

5 голосов
/ 07 июля 2019

Вы можете использовать селектор CSS tr:not(tr:has(td:contains("Less similar results")) ~ *) div.title:

data = '''<tr>
    <td class="info"><div class="title">THIS YOU WANT ...</div></td>
</tr>
<tr class="ls">
    <td colspan="3">Less similar results</td>
</tr>
<tr>
    <td class="info"><div class="title">THIS YOU DON'T WANT ...</div></td>
</tr>'''

from bs4 import BeautifulSoup

soup = BeautifulSoup(data, 'lxml')

print(soup.select('tr:not(tr:has(td:contains("Less similar results")) ~ *) div.title'))

Печать:

[<div class="title">THIS YOU WANT ...</div>]

Что это значит?

tr:not(tr:has(td:contains("Less similar results")) ~ *) div.title

Выберите <div> с классом title, который находится под <tr>, что предшествует <tr>, который содержит <td> с "Less similar results".

Дополнительная информация:

Справочник по селектору CSS

2 голосов
/ 07 июля 2019

Мы можем пойти другим путем и сосредоточиться на первом <tr class="ls">:

from bs4.element import Tag

ls = soup.find('tr', class_='ls')
elts = [td for tr in <b>ls.previous_siblings</b>
           if isinstance(tr, Tag)
           for td in tr.find_all('td', class_='info')]

Это дает нам:

>>> elts
[<td class="info"><div class="title">...</div></td>]

Таким образом, сначала мы находим trс class="ls", а затем мы перебираем его предыдущих братьев и сестер и ищем <td class="info"> s.

0 голосов
/ 07 июля 2019

попробуйте это -

o = []
for td in soup.find("td", class_="info"):
    if td.get_text() == 'Less similar results':
        break
    for div in td.findChildren("div", class_='title'):
        o.append(div.get_text())

print(o)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...