Come trovare i figli dei nodi usando BeautifulSoup


115

Voglio ottenere tutti i <a>tag che sono figli di <li>:

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

So come trovare elementi con una classe particolare come questa:

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

Ma non so come trovare tutti quelli <a>che sono figli di <li class=test>ma non di altri.

Come voglio selezionare:

<a>link1</a>

Risposte:


124

Prova questo

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

3
Oppure, per estrarre solo l'espressione che descrive ciò che vogliamo: soup.find('li', {'class': 'text'}).findChildren().
Karl Knechtel

3
ma come ottenere il tag <a> frist solo non dopo i reparti. qualcosa comefind(li).find(a).firstChild()
tej.tan

Grazie per il kwarg "ricorsivo" :)
Swift

122

C'è una sezione piccolissima nei DOC che mostra come trovare / trovare_tutti i figli diretti .

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

Nel tuo caso come vuoi link1 che è il primo figlio diretto:

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

Se vuoi che tutti i figli diretti:

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

12

Forse vuoi farlo

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

1
penso che lo troverà <a> link2 </a>anche ma non lo voglio
tej.tan

1
Questo risponde alla domanda su come selezionare <a>link1</a>nell'HTML data nella domanda, ma questo FAIL quando il primo <li class="test">non conterrà <a>elementi e ci sono altri lielementi con la testclasse che lo contiene <a>.
radzak

11

prova questo:

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

altri promemoria:

Il metodo find ottiene solo il primo elemento figlio che si verifica. Il metodo find_all ottiene tutti gli elementi discendenti e vengono memorizzati in un elenco.


2
L'interrogante non vuole nessuna delle due opzioni sopra. Vuole tutti i collegamenti che sono solo figli diretti.
Ahsan Roy

9

"Come trovare tutti coloro ache sono figli di<li class=test> ma non di altri?"

Dato l'HTML di seguito (ne ho aggiunto un altro <a>per mostrare la differenza tra selecte select_one):

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

La soluzione è usare il combinatore figlio ( >) che si trova tra due selettori CSS:

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

Nel caso in cui desideri trovare solo il primo figlio:

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

Questo è quello che stavo cercando. Lo stavo fornendo al metodo sbagliato. Forgot> è un selettore CSS. Grazie!
LFMekz

7

Ancora un altro metodo: crea una funzione di filtro che restituisca Truetutti i tag desiderati:

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

Quindi chiama find_allcon l'argomento:

for a in soup(my_filter): # or soup.find_all(my_filter)
    print a
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.