Одна из ключевых особенностей библиотеки BeautifulSoup — возможность использования пользовательских функций для фильтрации результатов поиска. Это расширяет возможности стандартных методов поиска, таких как find_all()
, позволяя реализовывать сложные условия выборки.
Метод find_all()
в BeautifulSoup ищет все теги и строки, которые соответствуют указанным критериям. Он может принимать различные аргументы, включая строки, регулярные выражения, списки и функции.
Функция, передаваемая в 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 не просто инструментом для парсинга, но и мощным решением для сложных задач извлечения данных.
Содержание: