Красивый суп - выберите все элементы, которые имеют класс, но также разделите их или игнорируйте элементы, если у них есть и другие предложения - PullRequest
1 голос
/ 22 января 2020

У меня следующая структура:

<div class="alpha">
<div class="alpha">
<div class="alpha">
<div class="alpha betha">
<div class="alpha gama">
<div class="alpha">

Мне нужно

  1. получить все элементы, которые имеют только «альфа» в качестве класса в списке.
  2. получить все элементы, которые имеют 'alpha' и 'betha' в другом списке.
  3. Игнорировать другие комбинации, такие как "alpha gama".

Я знаю, что могу получить все элементы которые имеют класс

container.findAll('div', {'class': 'alpha'})

но как разделить / игнорировать на 2 и 3.

Ответы [ 2 ]

3 голосов
/ 22 января 2020

Вы можете использовать CSS селекторы с методом .select():

txt = '''<div class="alpha">1</div>
<div class="alpha">2</div>
<div class="alpha">3</div>
<div class="alpha betha">4</div>
<div class="betha alpha">5</div>
<div class="alpha betha gama">6</div>
<div class="alpha gama">7</div>
<div class="alpha">8</div>'''

from bs4 import BeautifulSoup

soup = BeautifulSoup(txt, 'html.parser')

only_alpha = soup.select('[class="alpha"]')
only_alpha_betha = soup.select('.alpha.betha:not(.gama)')

print('Only alpha:', only_alpha)
print('Only alpha and betha:', only_alpha_betha)

Отпечатки:

Only alpha: [<div class="alpha">1</div>, <div class="alpha">2</div>, <div class="alpha">3</div>, <div class="alpha">8</div>]
Only alpha and betha: [<div class="alpha betha">4</div>, <div class="betha alpha">5</div>]
2 голосов
/ 23 января 2020

Почему бы не создать вспомогательную функцию?

bs4 позволяет указать a function as filter при поиске дерева с помощью find_all () .

Из документов:

Если ни одно из других совпадений не работает для вас, определите функцию, которая принимает элемент в качестве единственного аргумента. Функция должна возвращать True, если аргумент совпадает, и False в противном случае.

Проблема в том, что мы не можем передавать другие аргументы (список допустимых классов в этом случае). Мы можем преодолеть это, используя функцию-обертку для динамического создания фильтров.

def create_filter(tag_name, class_list):
    def class_filter(tag):
        return (
            tag.name == tag_name and
            set(tag.get('class', [])) == set(class_list)
        )
    return class_filter

Давайте посмотрим, как это работает на примере @AndrejKesely html.

Only alpha

print(soup.find_all(create_filter('div', ['alpha'])))

Выход

[<div class="alpha">1</div>, <div class="alpha">2</div>, <div class="alpha">3</div>, <div class="alpha">8</div>]

Только alpha и betha

print(soup.find_all(create_filter('div', ['alpha', 'betha'])))

Выход

[<div class="alpha betha">4</div>, <div class="betha alpha">5</div>]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...