【问题标题】:How to find children of nodes using BeautifulSoup如何使用 BeautifulSoup 查找节点的子节点
【发布时间】:2011-09-11 08:46:46
【问题描述】:

我想获取所有<a> 标签,它们是<li> 的子标签:

<div>
<li class="test">
    <a>link1</a>
    <ul> 
       <li>  
          <a>link2</a> 
       </li>
    </ul>
</li>
</div>

我知道如何找到具有特定类的元素,如下所示:

soup.find("li", { "class" : "test" }) 

但我不知道如何找到所有 &lt;a&gt; 的孩子 &lt;li class=test&gt; 但不是任何其他人。

我想选择:

<a>link1</a>

【问题讨论】:

    标签: python html beautifulsoup


    【解决方案1】:

    试试这个

    li = soup.find('li', {'class': 'text'})
    children = li.findChildren("a" , recursive=False)
    for child in children:
        print(child)
    

    【讨论】:

    • 或者,只提取描述我们想要的表达式:soup.find('li', {'class': 'text'}).findChildren()
    • 感谢“递归”kwarg :)
    • 来自 bs4 站点:“findChildren, findChild:这些方法是从 Beautiful Soup 2 API 遗留下来的。它们自 2006 年以来已被弃用,根本不应该使用:“
    【解决方案2】:

    DOC 中有一个超小的部分展示了如何查找/查找所有 直接 孩子。

    https://www.crummy.com/software/BeautifulSoup/bs4/doc/#the-recursive-argument

    在您的情况下,您希望 link1 是第一个直接子项:

    # for only first direct child
    soup.find("li", { "class" : "test" }).find("a", recursive=False)
    

    如果您想要所有直系子代:

    # for all direct children
    soup.find("li", { "class" : "test" }).findAll("a", recursive=False)
    

    【讨论】:

      【解决方案3】:

      也许你想做

      soup.find("li", { "class" : "test" }).find('a')
      

      【讨论】:

      • 我认为它也会找到&lt;a&gt; link2 &lt;/a&gt;,但我不希望这样
      • 这回答了如何在问题中给出的 HTML 中选择 &lt;a&gt;link1&lt;/a&gt; 的问题,但是当第一个 &lt;li class="test"&gt; 不包含 &lt;a&gt; 元素并且还有其他 li 时,这将失败包含&lt;a&gt;test 类的元素。
      • 这不能回答问题,但它正是我要找的。​​span>
      【解决方案4】:

      试试这个:

      li = soup.find("li", { "class" : "test" })
      children = li.find_all("a") # returns a list of all <a> children of li
      

      其他提醒:

      find 方法只获取第一个出现的子元素。 find_all 方法获取所有后代元素并存储在列表中。

      【讨论】:

      • 提问者不希望上述两个选项中的任何一个。他想要所有只是直接子级的链接。
      【解决方案5】:

      “如何找到所有a&lt;li class=test&gt; 的孩子但不是其他任何人?”

      鉴于下面的 HTML(我添加了另一个 &lt;a&gt; 以显示 selectselect_one 之间的区别):

      <div>
        <li class="test">
          <a>link1</a>
          <ul>
            <li>
              <a>link2</a>
            </li>
          </ul>
          <a>link3</a>
        </li>
      </div>
      

      解决方案是使用放在两个 CSS 选择器之间的child combinator (&gt;):

      >>> soup.select('li.test > a')
      [<a>link1</a>, <a>link3</a>]
      

      如果您只想找到第一个孩子:

      >>> soup.select_one('li.test > a')
      <a>link1</a>
      

      【讨论】:

      • 这是我要找的那个。我将它提供给错误的方法。 Forgot > 是一个 CSS 选择器。谢谢!
      【解决方案6】:

      另一种方法 - 创建一个过滤函数,为所有需要的标签返回True

      def my_filter(tag):
          return (tag.name == 'a' and
              tag.parent.name == 'li' and
              'test' in tag.parent['class'])
      

      然后只需使用参数调用find_all

      for a in soup(my_filter): # or soup.find_all(my_filter)
          print a
      

      【讨论】:

        【解决方案7】:

        刚刚遇到这个答案并检查了文档以查看 soup.findChildren 已被弃用(BS 4.9)。您可以改用soup.children,它只考虑元素的直接子元素,而不考虑其后代。

        li = soup.find('li', {'class': 'text'})
        for child in li.children:
            print(child)
        

        文档:https://www.crummy.com/software/BeautifulSoup/bs4/doc/#contents-and-children

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-07-16
          • 2014-08-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-02-04
          • 2011-07-24
          相关资源
          最近更新 更多