如何使用BeautifulSoup搜索出现在另一个元素之前的元素?

时间:2019-07-07 14:27:59

标签: django python-3.x beautifulsoup

我正在将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>

我想提取带有class =“ title”的DIV,但是,我只想查找表中TD文本=“缺少相似结果”的元素之前的DIV。现在我有这个

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

但是这将返回该类的所有DIV,即使是在我要筛选的元素之后发生的DIV。如何优化搜索以仅包含特定TD之前的结果?

3 个答案:

答案 0 :(得分:5)

您可以使用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>的{​​{1}},该类别位于title之前的<tr>之下,其中<tr>包含<td>"Less similar results"

进一步阅读:

CSS Selector Reference

答案 1 :(得分:2)

我们可以反过来,首先关注<tr class="ls">

from bs4.element import Tag

ls = soup.find('tr', class_='ls')
elts = [td for tr in ls.previous_siblings
           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">

答案 2 :(得分:0)

尝试-

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)