【问题标题】:How do I use BeautifulSoup to search for elements that occur before another element?如何使用 BeautifulSoup 搜索出现在另一个元素之前的元素?
【发布时间】:2019-07-07 14:27:59
【问题描述】:

我在 Python 3.7 中使用 BeautifulSoup 4。我有以下 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 文本 =“不太相似的结果”的元素之前的那些。现在我有这个

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

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

【问题讨论】:

  • 是否总是在&lt;tr class="ls"&gt; 中定义“不太相似的结果”?

标签: django python-3.x beautifulsoup


【解决方案1】:

你可以使用 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

选择&lt;div&gt;title 类,即在&lt;tr&gt; 之下,在&lt;tr&gt; 之前,包含&lt;td&gt;"Less similar results"

进一步阅读:

CSS Selector Reference

【讨论】:

    【解决方案2】:

    我们可以反过来,先关注&lt;tr class="ls"&gt;

    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>]
    

    因此,我们首先使用class="ls" 定位tr,然后遍历其先前的兄弟姐妹并寻找&lt;td class="info"&gt;s。

    【讨论】:

      【解决方案3】:

      试试这个 -

      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)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-06-30
        • 1970-01-01
        • 2015-06-02
        • 1970-01-01
        • 2010-10-04
        • 2011-06-05
        • 2014-03-18
        • 2019-10-25
        相关资源
        最近更新 更多