Красивый суп - игнорировать дочерние элементы с тем же именем, что и родительский элемент - PullRequest
0 голосов
/ 26 сентября 2019

html структурирован следующим образом:

  <div class="my_class">
       <div>important text</div>
       <div class="my_class">
            <div>not important</div>
       </div>
   </div>
   <div class="my_class">
       <div>important text</div>
       <div class="my_class">
            <div>not important</div>
       </div>
   </div>
   ...

В основном, есть много div с тем же именем, что и их дочерние div, и, в конечном счете, я хочу найти «важный текст», который находится втолько div div.

Когда я пытаюсь найти все div с помощью class = "my_class", я, очевидно, получаю как родителей, так и детей.Как я могу получить только родительские элементы div?

Вот мой код для получения всех элементов div с помощью class = "my_class" и поиска важного текста:

my_div_list = soup.find_all('div', attrs={'class': 'my_class'})
for my_div in my_div_list:
    text_item = my_div.find('div') # to get to the div that contains the important text
    print(text_item.getText())

Очевидно, что вывод такой:

important text
not important
important text
not important
...

Когда я хочу:

 important text
 important text
 ...

Ответы [ 3 ]

1 голос
/ 26 сентября 2019

Из документации findall():

рекурсивный является логическим аргументом (по умолчанию True), который сообщает Beautiful Soup, идти ли до конца по дереву разбора или смотреть только нанепосредственные потомки тега или объекта парсера.

Итак, если первый уровень div находится, например, под тегами <head> и <body>, вы можете установить

soup.html.body.find_all('div', attrs={'class': 'my_class'}, 
recursive=False)

Вывод:

 ['important text', 'important text']
1 голос
/ 26 сентября 2019

с bs4 4.7.1 вы можете использовать: имеет и: первый ребенок

from bs4 import BeautifulSoup as bs

html = '''<div class="my_class">
       <div>important text</div>
       <div class="my_class">
            <div>not important</div>
       </div>
   </div>
   <div class="my_class">
       <div>important text</div>
       <div class="my_class">
            <div>not important</div>
       </div>
   </div>'''

soup = bs(html, 'lxml')
print([i.text for i in soup.select('.my_class:has(>.my_class) > div:first-child')])
1 голос
/ 26 сентября 2019

Вы можете перебрать soup.contents:

from bs4 import BeautifulSoup as soup
r = [i.div.text for i in soup(html, 'html.parser').contents if i != '\n']

Вывод:

['important text', 'important text']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...