Фильтрация с помощью функций в BeautifulSoup

Применение функций для фильтрации результатов в BeautifulSoup

Одна из ключевых особенностей библиотеки BeautifulSoup — возможность использования пользовательских функций для фильтрации результатов поиска. Это расширяет возможности стандартных методов поиска, таких как find_all(), позволяя реализовывать сложные условия выборки.

Метод find_all() в BeautifulSoup ищет все теги и строки, которые соответствуют указанным критериям. Он может принимать различные аргументы, включая строки, регулярные выражения, списки и функции.

Использование функций в find_all()

Функция, передаваемая в find_all(), должна принимать один аргумент (тег) и возвращать True, если этот тег соответствует критериям поиска.

Пример:

def has_class_but_no_id(tag):
    return tag.has_attr('class') and not tag.has_attr('id')

soup.find_all(has_class_but_no_id)

Эта функция найдет все теги, у которых есть атрибут класса, но нет ID.

Поиск элементов с определенными атрибутами

Задача: Найти все теги <a>, содержащие атрибут href, но не содержащие класса.

Функция:

def a_with_href_not_class(tag):
    return tag.name == 'a' and tag.has_attr('href') and not tag.has_attr('class')

links = soup.find_all(a_with_href_not_class)

Фильтрация по содержимому тегов

Задача: Найти все теги <p>, содержащие определенное слово.

Функция:

def p_contains_word(tag):
    return tag.name == 'p' and 'слово' in tag.text

paragraphs = soup.find_all(p_contains_word)

Комбинированная фильтрация

Задача: Выбрать все теги, которые имеют ID и содержат определенное количество элементов внутри.

Функция:

def tag_with_id_and_children(tag):
    return tag.has_attr('id') and len(tag.contents) > 3

tags = soup.find_all(tag_with_id_and_children)

Лямбда-функции для простых фильтров

Лямбда-функции - это компактный способ применения простых фильтров. Они особенно полезны для однострочных условий.

soup.find_all(lambda tag: tag.name == 'div' and 'header' in tag.get('class', []))

Это найдет все <div>, которые имеют класс header.

Практические примеры

Давайте рассмотрим пример использования функциональной фильтрации на странице Википедии для извлечения всех заголовков статей с определенной длиной.

from bs4 import BeautifulSoup
import requests

# Загрузим страницу Википедии
url = 'https://ru.wikipedia.org/wiki/Python'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')

# Определим функцию для фильтрации по длине заголовка
def title_length_filter(tag):
    return tag.name == 'h2' and len(tag.text) > 20

# Применим функциональную фильтрацию
filtered_titles = soup.find_all(title_length_filter)

# Выведем результат
for title in filtered_titles:
    print(title.text)

В данном примере мы создали функцию title_length_filter(), которая возвращает True для тегов h2 с текстом заголовка длиннее 20 символов. Затем мы использовали эту функцию в методе find_all(), чтобы получить все подходящие заголовки.

Заключение

Использование пользовательских функций в методе find_all() позволяет проводить более глубокий и точный парсинг, адаптируя процесс к конкретным требованиям задачи. Это делает BeautifulSoup не просто инструментом для парсинга, но и мощным решением для сложных задач извлечения данных.

Содержание: