BeautifulSoup kullanarak düğümlerin alt öğelerini bulma


115

<a>Alt öğe olan tüm etiketleri almak istiyorum <li>:

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

Bunun gibi belirli bir sınıfa sahip öğeyi nasıl bulacağımı biliyorum:

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

Ama <a>çocukları olan <li class=test>ama başkalarının çocuklarını nasıl bulacağımı bilmiyorum .

Seçmek istediğim gibi:

<a>link1</a>

Yanıtlar:


124

Bunu dene

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

3
Ya da, sadece bizim istediğimiz açıklar ifadeyi ayıklamak için: soup.find('li', {'class': 'text'}).findChildren().
Karl Knechtel

3
ancak ilk <a> etiketini nasıl elde edeceğinizi sadece servislerden sonra değil. gibi bir şeyfind(li).find(a).firstChild()
tej.tan

"Yinelemeli" kwarg için teşekkürler :)
Swift

122

DOC'larda doğrudan çocukları nasıl bulacağınızı / bulacağınızı gösteren çok küçük bir bölüm var .

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

Sizin durumunuzda istediğiniz gibi ilk doğrudan çocuk olan link1:

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

Tüm doğrudan çocukları istiyorsanız:

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

12

Belki yapmak istersin

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

1
Ben de bulacağını düşünüyorum <a> link2 </a>ama bunu istemiyorum
tej.tan

1
Bu, soruda <a>link1</a>verilen HTML'de nasıl seçileceği sorusunu yanıtlar, ancak ilk öğe <li class="test">hiçbir <a>öğe içermediğinde ve sınıf içeren başka liöğeler olduğunda bu BAŞARISIZ olacaktır . test<a>
radzak

11

bunu dene:

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

diğer hatırlatıcılar:

Find yöntemi yalnızca ilk oluşan alt öğeyi alır. Find_all yöntemi tüm alt öğeleri alır ve bir listede saklanır.


2
Soru soran, yukarıdaki iki seçenekten hiçbirini istemiyor. Yalnızca doğrudan çocuk olan tüm bağlantıları istiyor.
Ahsan Roy

9

" aÇocukları olan her şeyi nasıl bulabilirim?<li class=test> ancak başkalarının olmadığı her ?"

Aşağıdaki HTML göz önüne alındığında ( ve <a>arasındaki farkı göstermek için bir tane daha ekledim ):selectselect_one

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

Çözüm, iki CSS seçici arasına yerleştirilen alt birleştirici ( >) kullanmaktır :

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

Sadece ilk çocuğu bulmak istemeniz durumunda:

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

Bu aradığım şey. Yanlış yöntemle sağlıyordum. Forgot> bir CSS seçicidir. Teşekkürler!
LFMekz

7

Yine başka bir yöntem - Trueistenen tüm etiketler için geri dönen bir filtre işlevi oluşturun :

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

Sonra find_allargümanla arayın :

for a in soup(my_filter): # or soup.find_all(my_filter)
    print a
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.