วิธีค้นหาลูกของโหนดโดยใช้ BeautifulSoup


118

ฉันต้องการรับ<a>แท็กทั้งหมดที่เป็นลูกของ<li>:

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

ฉันรู้วิธีค้นหาองค์ประกอบที่มีคลาสเฉพาะเช่นนี้:

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

แต่ฉันไม่รู้ว่าจะหาทั้งหมด<a>ที่เป็นลูกของ<li class=test>คนอื่นได้อย่างไร

เช่นฉันต้องการเลือก:

<a>link1</a>

คำตอบ:


125

ลองทำตามนี้

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

3
soup.find('li', {'class': 'text'}).findChildren()หรือจะเพียงแค่ดึงการแสดงออกที่อธิบายในสิ่งที่เราต้องการ:
Karl Knechtel

3
แต่จะรับแท็ก <a> ได้อย่างไรไม่ใช่หลังจากวอร์ด บางอย่างเช่นfind(li).find(a).firstChild()
tej.tan

ขอบคุณสำหรับ kwarg "เรียกซ้ำ" :)
Swift

124

DOCs มีส่วนเล็ก ๆ ที่แสดงวิธีค้นหา / find_all direct children

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)

13

บางทีคุณอาจต้องการทำ

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

1
ฉันคิดว่ามันจะเจอ<a> link2 </a>เช่นกัน แต่ฉันไม่ต้องการแบบนั้น
tej.tan

1
นี้จะตอบคำถามวิธีการเลือก<a>link1</a>ใน HTML ที่กำหนดในคำถาม แต่นี้จะล้มเหลวเมื่อครั้งแรกที่<li class="test">จะมีไม่มี<a>องค์ประกอบและมีอื่น ๆliองค์ประกอบที่มีชั้นเรียนที่มีtest <a>
radzak

11

ลองสิ่งนี้:

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

การแจ้งเตือนอื่น ๆ :

วิธีการค้นหาจะได้รับองค์ประกอบลูกแรกที่เกิดขึ้นเท่านั้น เมธอด find_all ได้รับองค์ประกอบที่สืบทอดมาทั้งหมดและถูกเก็บไว้ในรายการ


2
ผู้ถามไม่ต้องการตัวเลือกสองข้อข้างต้น เขาต้องการการเชื่อมโยงทั้งหมดที่เป็นลูกโดยตรงเท่านั้น
Ahsan Roy

9

"จะหา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>

วิธีแก้ปัญหาคือใช้child combinator ( >) ที่วางไว้ระหว่างตัวเลือก CSS สองตัว:

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

ในกรณีที่คุณต้องการค้นหาลูกคนแรกเท่านั้น:

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

นี่คือสิ่งที่ฉันกำลังมองหา ฉันส่งมันไปผิดวิธี ลืม> เป็นตัวเลือก CSS ขอบคุณ!
LFMekz

7

อีกวิธีหนึ่ง - สร้างฟังก์ชันตัวกรองที่ส่งกลับ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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.