JavaRush /Курси /Python SELF UA /Пошук елементів за допомогою методів find і find_all для ...

Пошук елементів за допомогою методів find і find_all для цілеспрямованого скрейпінгу

Python SELF UA
Рівень 32 , Лекція 1
Відкрита

1. Навіщо використовувати find та find_all?

Сьогодні ми поговоримо про два основних методи, які дозволять нам ефективно і цілеспрямовано видобувати елементи з HTML-документів: find та find_all.

Перш ніж занурюватись у код, давайте обговоримо, навіщо взагалі потрібні ці методи. Уявіть веб-сторінку як величезну бібліотеку, де кожне слово і речення — це елементи HTML. Здається, що знайти потрібну інформацію — це як спроба вгадати смак морозива, не знаючи його кольору. Методи find та find_all — це ваші «детектори смаку», які допоможуть вам точно налаштуватись на потрібну інформацію.

  • find: Цей метод схожий на звичку програмістів зранку шукати першу чашку кави — він швидко знаходить і повертає перший елемент, який відповідає заданим критеріям.
  • find_all: Це більш терплячий і ґрунтовний підхід, він повертає список усіх елементів, що відповідають критеріям пошуку. Підходить для тих ситуацій, коли вам потрібно більше інформації (наприклад, кілька чашок кави протягом дня).

2. Використання find

Отже, метод find можна використовувати, коли вам потрібно швидко отримати перший відповідний елемент. Він приймає різні параметри, такі як ім'я тега, атрибути і навіть функції.

Сигнатура методу find


find(name=None, attrs={}, recursive=True, string=None, **kwargs)

Параметри методу find

  • name: Ім'я тега, який ви хочете знайти. Це може бути будь-який HTML-тег, наприклад, div, p, h1, a тощо.
  • attrs: Словник атрибутів тега. Наприклад, {'class': 'example'} або {'id': 'main'}. Цей параметр дозволяє звузити пошук.
  • recursive: Булевий параметр, який визначає, чи буде метод шукати тег на всіх рівнях вкладеності. За замовчуванням True, що означає, що пошук буде виконаний на всіх рівнях.
  • string: Пошук елементів з певним текстом. Це корисно для фільтрації елементів за вмістом тексту.
  • kwargs: Додаткові аргументи для пошуку за атрибутами. Якщо вказані аргументи, такі як class_, вони будуть інтерпретуватись як attrs={'class': 'value'}.

Приклад

Python

from bs4 import BeautifulSoup

html_doc = """
<html>
    <head><title>The Dormouse's story</title></head>
    <body>
        <p class="title"><b>The Dormouse's story</b></p>
        <p class="story">Once upon a time there were three little sisters; and their names were
        <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
        <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
        <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
        and they lived at the bottom of a well.</p>
    </body>
</html>
"""

soup = BeautifulSoup(html_doc, 'html.parser')
first_link = soup.find('a')  # Знаходимо перший <a> тег

print(first_link)  # Виводить: <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>

Як бачите, метод find знайшов перший тег <a> у документі, і ми спокійно продовжуємо свої пошуки, знаючи, що потрібна інформація знайдена.

3. Використання find_all

Метод find_all повертає список усіх елементів, які відповідають заданим критеріям. Це особливо корисно, коли потрібно отримати всі теги певного типу або всі елементи з певним класом.

Сигнатура методу find_all


find_all(name=None, attrs={}, recursive=True, string=None, limit=None, **kwargs)

Параметри метода find_all

  • name: Ім'я тега, який ви хочете знайти. Це може бути рядок з ім'ям тега (div, a, p і т.д.) або список тегів, наприклад, ["div", "p"].
  • attrs: Словник атрибутів для фільтрації тегів, наприклад, {'class': 'example'}.
  • recursive: Визначає, чи буде пошук виконуватись рекурсивно, включаючи вкладені теги. Значення True за замовчуванням.
  • string: Шукає теги, що містять вказаний текст.
  • limit: Встановлює максимальну кількість результатів, що повертаються. Якщо задано, метод поверне не більше limit елементів.
  • kwargs: Додаткові параметри для фільтрації атрибутів тега.

Приклад використання find_all

Якщо find — це як швидкий пошук потрібної книги на полиці, то find_all — це більш детальний підхід, як якщо б ви перечитували кожен заголовок розділу, щоб розібратися.

Python

all_links = soup.find_all('a')  # Знаходимо всі <a> теги

for link in all_links:
    print(link.get('href'))  # Виводить посилання: http://example.com/elsie, http://example.com/lacie, http://example.com/tillie

У цьому прикладі ми знаходимо всі теги <a> і потім отримуємо посилання з кожного з них. Корисно, якщо вам потрібно зібрати всі посилання на сторінці.

Важливо! Методи find() та find_all() можна викликати не лише у об'єкта soup, але й у будь-якого дочірнього елемента, який повертався функціями find(), select() і т.п.

4. Використання атрибутів для фільтрації елементів

Тепер, коли ми контролюємо свою пристрасть до даних, настав час стати більш конкретними. Методи find і find_all дозволяють фільтрувати елементи за атрибутами. Це як налаштувати фільтр у кавовій машині, щоб отримати саме той напій, який тобі до душі.

Python

link_with_id = soup.find('a', id='link2')  # Знаходимо <a> з id='link2'

print(link_with_id.text)  # Виводить: Lacie

Використовуючи параметр id, ми швидко знайшли потрібний елемент. Аналогічно, можна використовувати інші атрибути, наприклад class.

Python

links_with_class = soup.find_all('a', class_='sister')  # Знаходимо всі <a> з class='sister'

for link in links_with_class:
    print(link.get('id'))  # Виводить: link1, link2, link3

5. Порівняння find та find_all: коли використовувати що?

Знаючи обидва методи, ти, можливо, задаєшся питанням: «Коли ж використовувати find, а коли find_all?» Все просто. Якщо ти впевнений, що на сторінці лише один елемент, який тобі потрібен, або тебе цікавить лише перший знайдений елемент, обирай find. Якщо ж потрібно зібрати всі елементи, які відповідають критеріям і їх може бути багато, краще використовувати find_all.

Параметр find find_all
Повертає значення Перший знайдений елемент (або None, якщо не знайдено) Список знайдених елементів (або пустий список)
Призначення Коли потрібен лише один елемент Коли потрібно отримати всі підходящі елементи
Параметр limit Не застосовується Підтримується: задає максимальну кількість

Приклад порівняння: Якщо потрібно отримати всі заголовки h2 на сторінці, використовуй find_all. Але якщо тобі потрібен лише перший заголовок h2, достатньо find.

Python

# Отримати всі заголовки h2 на сторінці
all_h2_tags = soup.find_all("h2")

# Отримати лише перший заголовок h2
first_h2_tag = soup.find("h2")

6. Практичне завдання

Тепер, коли ви знаєте теорію, давайте застосуємо її на практиці. Розробимо невеликий скрипт, який буде вилучати заголовки та посилання статей з блогу. Для цього будемо використовувати find_all для пошуку всіх заголовків і посилань, припустивши, що вони знаходяться в тегу <h2> з класом post-title.

Python

blog_html = """
<html>
  <body>
    <h2 class="post-title"><a href="http://example.com/post1">Перша Стаття</a></h2>
    <h2 class="post-title"><a href="http://example.com/post2">Друга Стаття</a></h2>
    <h2 class="post-title"><a href="http://example.com/post3">Третя Стаття</a></h2>
  </body>
</html>
"""

blog_soup = BeautifulSoup(blog_html, 'html.parser')
post_titles = blog_soup.find_all('h2', class_='post-title')

for post in post_titles:
    title = post.text
    link = post.find('a')['href']
    print(f"Title: {title}, Link: {link}")

Якщо все зроблено правильно, ви побачите:

Title: Перша Стаття, Link: http://example.com/post1
Title: Друга Стаття, Link: http://example.com/post2
Title: Третя Стаття, Link: http://example.com/post3

Зверніть увагу, що метод find() у прикладі вище викликається у об'єкта post. Таким чином можна шукати дочірній елемент(и) у вже знайденого елемента.

7. Типові помилки

Коли доводиться мати справу з find і find_all, часто виникають помилки. Наприклад, метод find поверне None, якщо елемент не знайдено, що може призвести до AttributeError. Тому завжди варто перевіряти результат перед використанням.

Також часто трапляються проблеми з неправильними атрибутами. Наприклад, якщо атрибут записаний з помилкою, метод нічого не знайде. Тому рекомендую завжди перевіряти правильність написання атрибутів у HTML-коді.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ