如何使用Beautiful Soup找到节点的子节点

tej*_*tan 97 html python beautifulsoup

我想得到所有<a>孩子的标签<li>

<div>
<li class="test">
    <a>link1</a>
    <ul> 
       <li>  
          <a>link2</a> 
       </li>
    </ul>
</li>
</div>
Run Code Online (Sandbox Code Playgroud)

我知道如何找到像这样的特定类的元素

soup.find("li", { "class" : "test" }) 
Run Code Online (Sandbox Code Playgroud)

但我不知道如何找到所有<a>孩子<li class=test>而不是其他孩子

喜欢我想选择

<a>link1</a>
Run Code Online (Sandbox Code Playgroud)

bit*_*der 107

DOC中有一个超小部分,显示如何查找/ find_all 直接孩子.

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)
Run Code Online (Sandbox Code Playgroud)

如果你想要所有直接孩子:

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


cer*_*ros 101

试试这个

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

  • 来自 bs4 站点:“findChildren、findChild:这些方法是 Beautiful Soup 2 API 遗留下来的。它们自 2006 年以来已被弃用,根本不应该使用:” (17认同)
  • 或者,只提取描述我们想要的表达式:`soup.find('li',{'class':'text'}).findChildren()`. (3认同)
  • 但是如何在病房之后才获得frist <a>标签.类似于`find(li).find(a).firstChild()` (3认同)

Bem*_*mmu 11

也许你想做

soup.find("li", { "class" : "test" }).find('a')
Run Code Online (Sandbox Code Playgroud)

  • 我认为它也会找到`&lt;a&gt; link2 &lt;/a&gt;`,但我不想那样 (2认同)
  • 这回答了如何在问题中给出的 HTML 中选择 `&lt;a&gt;link1&lt;/a&gt;` 的问题,但是当第一个 `&lt;li class="test"&gt;` 不包含 `&lt;a&gt;` 时,这将失败元素,还有其他带有包含`&lt;a&gt;` 的`test` 类的`li` 元素。 (2认同)

小智 11

试试这个:

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

其他提醒:

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

  • 发问者希望以上两个选项都不是。他希望所有的链接都是直子。 (2认同)

小智 8

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

li = soup.find('li', {'class': 'text'})
for child in li.children:
    print(child)
Run Code Online (Sandbox Code Playgroud)

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


Ded*_*raz 6

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

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

然后find_all用参数调用:

for a in soup(my_filter): # or soup.find_all(my_filter)
    print a
Run Code Online (Sandbox Code Playgroud)


Jat*_*mir 6

“如何找到所有a是孩子的孩子,<li class=test>而不是其他孩子?”

给定下面的HTML(我添加了另一个<a>以显示select和之间的区别select_one):

<div>
  <li class="test">
    <a>link1</a>
    <ul>
      <li>
        <a>link2</a>
      </li>
    </ul>
    <a>link3</a>
  </li>
</div>
Run Code Online (Sandbox Code Playgroud)

解决方案是使用放置在两个CSS选择器之间的子组合器>):

>>> soup.select('li.test > a')
[<a>link1</a>, <a>link3</a>]
Run Code Online (Sandbox Code Playgroud)

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

>>> soup.select_one('li.test > a')
<a>link1</a>
Run Code Online (Sandbox Code Playgroud)