Как найти дочерних узлов с помощью BeautifulSoup - PullRequest
91 голосов
/ 09 июня 2011

Я хочу получить все теги <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>

Ответы [ 6 ]

104 голосов
/ 09 апреля 2013

В DOC есть очень маленький раздел, в котором показано, как найти / find_all direct children.

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

В вашем случае вам нужна ссылка1, которая является первым прямым потомком:

# 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)
91 голосов
/ 09 июня 2011

Попробуйте это

li = soup.find('li', {'class': 'text'})
children = li.findChildren("a" , recursive=False)
for child in children:
    print child
12 голосов
/ 18 августа 2014

попробуйте это:

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

другие напоминания:

Метод find получает только первый встречающийся дочерний элемент. Метод find_all получает все элементы-потомки и сохраняется в списке.

11 голосов
/ 09 июня 2011

Возможно, вы хотите сделать

soup.find("li", { "class" : "test" }).find('a')
6 голосов
/ 04 марта 2013

Еще один способ - создать функцию фильтра, которая возвращает 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
5 голосов
/ 22 апреля 2018

«Как найти всех 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>

Решение состоит в том, чтобы использовать дочерний комбинатор (>), который помещается между двумя селекторами CSS:

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

Если вы хотите найти только первого ребенка:

>>> soup.select_one('li.test > a')
<a>link1</a>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...