【问题标题】:beautifulsoup table tree: find all tr between two objects?Beautifulsoup 表树:找到两个对象之间的所有 tr?
【发布时间】:2016-03-14 06:36:32
【问题描述】:

你好,我有这样的 HTML 表格(由代码中的注释自行解释):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<tbody>
    <!-- there is a box -->
    <tr>RED BOX</tr>

        <!-- containing the following balls, each <td> has a ball -->
        <!-- may be more than one <tr> -->
        <tr>
            <td>ball 1</td>
            <td>ball 2</td>
        </tr>

        <tr>
            <td>ball 3</td>
        </tr>

    <!-- another box -->
    <tr>GREEN BOX</tr>

        <!-- containing the following balls -->
        <tr>
            <td>ball 4</td>
        </tr>

</tbody>

</body>
</html>

如代码中注释所示:RED BOX是tr,球1、2、3在RED BOX中,从结构上可以看出,球1、2、3在tr&lt;tr&gt;RED BOX&lt;/tr&gt; 之后(球可能在一个或多个tr 中)。 GREEN BOX 是另一个tr,然后球4 在tr

我想找到每个盒子里的球。我可以通过

找到&lt;tr&gt;RED BOX&lt;/tr&gt;&lt;tr&gt;GREEN BOX&lt;/tr&gt;
tr_box = bs.findAll(text=[regex 'something BOX'])

我可以找到下一个 tr 使用

for t in tr_box:
    t[0].find_next('tr')

(可以找到第1、2、4号球,错过第3号球)

但是 (1) 有没有像 find_between_objects 这样的东西可以在 &lt;tr&gt;RED BOX&lt;/tr&gt;&lt;tr&gt;GREEN BOX&lt;/tr&gt; 之间找到所有 tr?或将所有tr 分割成多个部分的函数,除以&lt;tr&gt;RED BOX&lt;/tr&gt;&lt;tr&gt;GREEN BOX&lt;/tr&gt;

(2) 如何找到&lt;tr&gt;GREEN BOX&lt;/tr&gt;和表尾&lt;/tbody&gt;之间的所有tr

谢谢

【问题讨论】:

    标签: python html tree beautifulsoup html-parsing


    【解决方案1】:

    选项 1:find_next_siblings()break,当您遇到带有 GREEN BOX 的一行时。

    red_box = soup.find("tr", text="RED BOX")
    for row in red_box.find_next_siblings("tr"):
        if row.get_text(strip=True) == "GREEN BOX":
            break
    
        print([td.get_text(strip=True) for td in row.find_all("td")])
    

    或者itertools.takewhile(),如果你想更Pythonic的话。

    选项 2: a search function

    def filter_rows(tag):
        return tag.name == "tr" and \
               tag.find_previous_sibling("tr", text="RED BOX") and \
               tag.find_next_sibling("tr", text="GREEN BOX")
    
    for row in soup.find_all(filter_rows):
        print([td.get_text(strip=True) for td in row.find_all("td")])
    

    两个选项都会打印:

    ['ball 1', 'ball 2']
    ['ball 3']
    

    (2)如何找到GREEN BOX和表尾之间的所有tr?

    这只是:

    green_box = soup.find("tr", text="GREEN BOX")
    for row in green_box.find_next_siblings("tr"):
        print([td.get_text(strip=True) for td in row.find_all("td")])
    

    这里不需要打破循环,find_next_siblings() 会在没有更多匹配的兄弟姐妹时自然停止。


    仅供参考,complete gist 在这里。

    【讨论】:

      【解决方案2】:

      如果您只想从“盒子”中取出“球”,则使用此方法可能更简单。找到所有trs,然后在trs 中找到所有tds:

      for tr in soup.find_all('tr'):
          for td in tr.find_all('td'):
              print(td.text)
      

      打印:

      ball 1
      ball 2
      ball 3
      ball 4
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-12-08
        • 1970-01-01
        • 2011-06-25
        • 1970-01-01
        • 2011-06-28
        • 1970-01-01
        • 2018-03-17
        相关资源
        最近更新 更多