web-dev-qa-db-fra.com

Comment trouver les enfants de noeuds à l'aide de BeautifulSoup

Je veux avoir tous les <a> tags qui sont les enfants de <li>:

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

Je sais comment trouver un élément avec une classe particulière comme ceci:

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

Mais je ne sais pas comment trouver tous les <a> qui sont des enfants de <li class=test> mais pas les autres.

Comme je veux sélectionner:

<a>link1</a>
91
tej.tan

Essaye ça

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

Il y a une très petite section dans les DOC qui montre comment trouver/find_all des enfants directs .

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

Dans votre cas, vous voulez link1 qui est le premier enfant direct:

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

Si vous voulez tous les enfants directs:

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

essaye ça:

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

autres rappels:

La méthode find ne récupère que le premier élément enfant existant. La méthode find_all récupère tous les éléments descendants et est stockée dans une liste.

12
kiiru

Peut-être que vous voulez faire

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

Encore une autre méthode - créez une fonction de filtre qui retourne True pour toutes les balises désirées:

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

Ensuite, appelez simplement find_all avec l'argument:

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

"Comment trouver tous les a qui sont des enfants de <li class=test> mais pas d'autres? "

Étant donné le code HTML ci-dessous (j'ai ajouté un autre <a> pour montrer la différence entre select et select_one):

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

La solution consiste à utiliser combinateur enfant (>) placé entre deux sélecteurs CSS:

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

Si vous voulez ne trouver que le premier enfant:

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