Поиск тегов: find(), find_all()

Поиск тегов: find(), find_all() Парсинг (BeautifulSoup, Selenium)

Важное предупреждение !!!

Данная статья носит исключительно информационный и образовательный характер. Она не является юридической консультацией и не может использоваться как руководство к действию в вопросах, связанных с парсингом, сбором данных и соблюдением законодательства.

Все примеры и рекомендации приведены для ознакомления с технической стороной процесса. Решение о законности парсинга в каждом конкретном случае зависит от множества факторов: юрисдикции, содержания сайта, способа сбора данных и целей использования информации. Для получения юридически обоснованного ответа обращайтесь к квалифицированным специалистам.

Перед началом прочтения статьи, ОБЯЗАТЕЛЬНО ознакомтесь со статьей «Что такое парсинг сайтов: законно ли это?«

Автор и администрация сайта не несут ответственности за использование материалов данной статьи в коммерческих или иных целях, а также за любые последствия, связанные с применением описанных методов.

Привет! В прошлой статье мы установили BeautifulSoup и написали первый парсер. Теперь пришло время научиться искать элементы на веб-странице. Это самое важное в парсинге — умение находить нужные теги.

В этой статье мы разберём:

  • find() — поиск первого элемента
  • find_all() — поиск всех элементов
  • Поиск по классам, id, атрибутам
  • CSS-селекторы через select()

Что нужно знать перед началом

Для этого урока тебе понадобится:

  • Установленный BeautifulSoup (статья 2 в этом подменю)
  • Базовое понимание HTML-тегов

Совет: Умение искать элементы — это 80% всей работы парсера.

Основная часть

Метод find()

find() возвращает первый элемент, соответствующий критериям.

from bs4 import BeautifulSoup

html = """
<div class="content">
    <h1>Заголовок</h1>
    <p>Первый параграф</p>
    <p>Второй параграф</p>
</div>
"""

soup = BeautifulSoup(html, "html.parser")

first_p = soup.find("p")
print(first_p.text)   # Первый параграф

Синтаксис:

soup.find(name, attrs, recursive, string, **kwargs)

Основные параметры:

ПараметрЧто делает
nameИмя тега ("p""div""a")
attrsАтрибуты тега (class_id)
stringПоиск по тексту

Метод find_all()

find_all() возвращает список всех элементов, соответствующих критериям.

soup = BeautifulSoup(html, "html.parser")

paragraphs = soup.find_all("p")
for p in paragraphs:
    print(p.text)

# Выведет:
# Первый параграф
# Второй параграф

Важно: Если элементов нет, find_all() возвращает пустой список, а не None.

items = soup.find_all("div")
print(items)   # [] (пустой список)

Поиск по классу

html = """
<div class="article">
    <p class="title">Заголовок</p>
    <p class="content">Текст статьи</p>
</div>
"""

soup = BeautifulSoup(html, "html.parser")

title = soup.find("p", class_="title")
print(title.text)   # Заголовок

content = soup.find("p", class_="content")
print(content.text)   # Текст статьи

Совет: Используй class_ с подчёркиванием, чтобы не конфликтовать с ключевым словом class в Python.

Поиск по id

html = """
<div id="main">
    <p>Главный текст</p>
</div>
<div id="footer">
    <p>Подвал</p>
</div>
"""

soup = BeautifulSoup(html, "html.parser")

main = soup.find(id="main")
print(main.p.text)   # Главный текст

footer = soup.find(id="footer")
print(footer.p.text) # Подвал

Поиск по атрибутам

html = """
<a href="https://example.com">Ссылка</a>
<a href="https://google.com">Google</a>
"""

soup = BeautifulSoup(html, "html.parser")

# Поиск по атрибуту href
example_link = soup.find("a", href="https://example.com")
print(example_link.text)   # Ссылка

# Поиск по атрибуту с помощью словаря
google_link = soup.find("a", attrs={"href": "https://google.com"})
print(google_link.text)   # Google

Поиск по тексту

html = """
<p>Привет, мир!</p>
<p>Hello, world!</p>
"""

soup = BeautifulSoup(html, "html.parser")

# Поиск по тексту
element = soup.find(string="Привет, мир!")
print(element)   # Привет, мир!

# Поиск с частичным совпадением
import re
elements = soup.find_all(string=re.compile("мир"))
for el in elements:
    print(el)   # Привет, мир!

Совет: Для частичного поиска используй модуль re (регулярные выражения).

Поиск с рекурсивным обходом

По умолчанию find() и find_all() ищут по всему дереву HTML. Можно ограничить поиск:

html = """
<div>
    <p>Параграф в div</p>
    <span>
        <p>Вложенный параграф</p>
    </span>
</div>
"""

soup = BeautifulSoup(html, "html.parser")

# Поиск только внутри div
div = soup.find("div")
paragraphs = div.find_all("p", recursive=False)
print(len(paragraphs))   # 1 (только прямой потомок)

CSS-селекторы через select()

BeautifulSoup поддерживает CSS-селекторы через метод select().

html = """
<div class="container">
    <p id="first">Первый</p>
    <p class="second">Второй</p>
    <p>Третий</p>
</div>
"""

soup = BeautifulSoup(html, "html.parser")

# Поиск по id
element = soup.select("#first")
print(element[0].text)   # Первый

# Поиск по классу
elements = soup.select(".second")
print(elements[0].text)   # Второй

# Поиск по тегу внутри класса
elements = soup.select(".container p")
for el in elements:
    print(el.text)
# Первый
# Второй
# Третий

Основные CSS-селекторы:

СелекторЧто ищет
#idПо id
.classПо классу
tagПо тегу
tag.classТег с классом
tag#idТег с id
parent childВложенные элементы

Пример из реальной жизни

Парсинг заголовков новостей с сайта:

import requests
from bs4 import BeautifulSoup

url = "https://news.ycombinator.com/"
response = requests.get(url)
soup = BeautifulSoup(response.text, "html.parser")

# Ищем все заголовки новостей (обычно внутри тега a с классом storylink)
titles = soup.find_all("a", class_="storylink")

for title in titles:
    print(title.text)
    print(title.get("href"))
    print("-" * 40)

Задачи для закрепления

Задача 1. Найди первый параграф на странице с помощью find().

Задача 2. Найди все ссылки на странице с помощью find_all().

Задача 3. Найди элемент с классом «highlight».

Задача 4. Найди элемент с id «main-content».

Задача 5. В чём разница между find() и find_all()?

Ответы:

Задача 1.

soup.find("p")

Задача 2.

soup.find_all("a")

Задача 3.

soup.find(class_="highlight")

Задача 4.

soup.find(id="main-content")

Задача 5.

# find() возвращает первый элемент или None
# find_all() возвращает список всех элементов или пустой список

Нюансы и подводные камни

class_ с подчёркиванием

В Python class — зарезервированное слово, поэтому используется class_.

# Правильно
soup.find("p", class_="title")

# Неправильно
soup.find("p", class="title")   # SyntaxError

find_all() возвращает список

items = soup.find_all("p")
if items:
    print(len(items))
else:
    print("Элементов нет")

Поиск по нескольким классам

soup.find("div", class_="content main")

Частые ошибки и как их избежать

Ошибка 1: Забыл подчёркивание в class_

Всегда используй class_, а не class.

Ошибка 2: Неправильное имя тега

Проверь регистр: "div" ≠ "DIV".

Ошибка 3: Ожидание списка от find()

find() возвращает один элемент или None, а не список.

Шпаргалка

Что нужноКак пишется
Найти первый элементsoup.find("tag")
Найти все элементыsoup.find_all("tag")
Поиск по классуsoup.find("tag", class_="name")
Поиск по idsoup.find(id="name")
Поиск по атрибутуsoup.find("tag", attrs={"key": "value"})
CSS-селекторsoup.select(".class")

7. Заключение / Выводы

Сегодня мы:

  • Научились искать элементы с помощью find() и find_all()
  • Искали по тегам, классам, id и атрибутам
  • Познакомились с CSS-селекторами
  • Разобрали частые ошибки

КВИЗ

Что дальше?

Оцените статью
IMI-DS - PYTHON LERNEN
Содержание
Оглавление ×