Введение в BeautifulSoup и атрибуты тегов
Что такое BeautifulSoup и зачем он нужен?
BeautifulSoup – это мощная Python-библиотека, предназначенная для парсинга HTML и XML документов. Она предоставляет удобные инструменты для навигации по структуре документа, поиска и извлечения данных, что делает её незаменимой при web scraping’е.
Вместо того, чтобы бороться со сложными регулярными выражениями для разбора HTML, BeautifulSoup позволяет работать с документом как с древовидной структурой, где каждый тег является узлом. Это существенно упрощает процесс извлечения информации, например, цен товаров, описаний, ссылок и многого другого, с веб-страниц.
Основы HTML и атрибутов тегов
HTML (HyperText Markup Language) – это язык разметки, используемый для создания веб-страниц. HTML документ состоит из набора тегов, которые определяют структуру и содержание страницы. Теги обычно состоят из открывающего и закрывающего тега (например, <p>
и </p>
), между которыми располагается контент.
Атрибуты тегов – это дополнительные параметры, которые предоставляют дополнительную информацию о теге. Например, тег <a>
(ссылка) имеет атрибут href
, который указывает на URL, на который ведет ссылка. Атрибуты обычно указываются внутри открывающего тега в формате имя_атрибута="значение_атрибута"
.
Пример:
<a href="https://www.example.com" class="external-link">Ссылка на Example.com</a>
В этом примере, href
и class
являются атрибутами тега <a>
.
Установка и импорт библиотеки BeautifulSoup
Установить BeautifulSoup можно с помощью pip:
pip install beautifulsoup4
Для работы с BeautifulSoup также потребуется установить парсер, например, lxml
или html.parser
(входит в стандартную библиотеку Python). lxml
обычно быстрее.
pip install lxml
После установки, импортируйте BeautifulSoup в ваш Python-скрипт:
from bs4 import BeautifulSoup
# Пример использования с lxml парсером
html_doc: str = """
<html><head><title>Пример страницы</title></head>
<body>
<p class="title"><b>Заголовок</b></p>
<a href="https://www.example.com/1" class="link">Ссылка 1</a>,
<a href="https://www.example.com/2" class="link">Ссылка 2</a>
</body>
</html>
"""
soup: BeautifulSoup = BeautifulSoup(html_doc, 'lxml')
print(soup.prettify())
Поиск атрибутов тегов с помощью BeautifulSoup
Метод get()
для извлечения атрибутов
Метод get()
позволяет получить значение атрибута тега. Если атрибут не существует, метод вернет None
(или значение, указанное в качестве второго аргумента).
from bs4 import BeautifulSoup
html_doc: str = '<a href="https://www.example.com" class="external-link">Ссылка</a>'
soup: BeautifulSoup = BeautifulSoup(html_doc, 'lxml')
link: bs4.element.Tag = soup.a
href_value: str | None = link.get('href')
class_value: str | None = link.get('class')
print(f"URL: {href_value}") # Output: URL: https://www.example.com
print(f"Class: {class_value}") # Output: Class: ['external-link']
non_existent_attr: str | None = link.get('nonexistent')
print(f"Non-existent attribute: {non_existent_attr}") # Output: Non-existent attribute: None
default_value: str = link.get('nonexistent', 'default')
print(f"Non-existent attribute with default: {default_value}") # Output: Non-existent attribute with default: default
Использование синтаксиса словаря для доступа к атрибутам
К атрибутам тега можно обращаться как к элементам словаря:
from bs4 import BeautifulSoup
html_doc: str = '<a href="https://www.example.com" class="external-link">Ссылка</a>'
soup: BeautifulSoup = BeautifulSoup(html_doc, 'lxml')
link: bs4.element.Tag = soup.a
href_value: str = link['href']
print(f"URL: {href_value}") # Output: URL: https://www.example.com
# Попытка доступа к несуществующему атрибуту вызовет KeyError
# try:
# non_existent_attr: str = link['nonexistent']
# except KeyError:
# print("Атрибут не найден")
Проверка существования атрибута
Чтобы избежать KeyError
, можно проверить наличие атрибута перед обращением к нему:
from bs4 import BeautifulSoup
html_doc: str = '<a href="https://www.example.com" class="external-link">Ссылка</a>'
soup: BeautifulSoup = BeautifulSoup(html_doc, 'lxml')
link: bs4.element.Tag = soup.a
if 'href' in link.attrs:
href_value: str = link['href']
print(f"URL: {href_value}")
if 'nonexistent' in link.attrs:
print(link['nonexistent'])
else:
print("Атрибут 'nonexistent' не найден.")
Поиск тегов по атрибутам
Метод find()
и find_all()
для поиска по атрибутам
Методы find()
и find_all()
позволяют искать теги, соответствующие определенным критериям, включая значения атрибутов.
from bs4 import BeautifulSoup
html_doc: str = """
<div class="product" data-product-id="123">
<h2 class="product-name">Товар 1</h2>
<span class="price">1000 руб.</span>
</div>
<div class="product" data-product-id="456">
<h2 class="product-name">Товар 2</h2>
<span class="price">2000 руб.</span>
</div>
"""
soup: BeautifulSoup = BeautifulSoup(html_doc, 'lxml')
# Найти первый тег div с классом "product"
product: bs4.element.Tag | None = soup.find('div', class_='product')
if product:
print(product)
# Найти все теги div с классом "product"
products: list[bs4.element.Tag] = soup.find_all('div', class_='product')
for prod in products:
print(prod)
Использование словаря attrs
для более сложного поиска
Для более сложных запросов, можно использовать словарь attrs
:
from bs4 import BeautifulSoup
html_doc: str = """
<div class="product" data-product-id="123" data-discount="10%">
<h2 class="product-name">Товар 1</h2>
</div>
<div class="product" data-product-id="456">
<h2 class="product-name">Товар 2</h2>
</div>
"""
soup: BeautifulSoup = BeautifulSoup(html_doc, 'lxml')
# Найти тег div с классом "product" и атрибутом data-product-id равным "123"
product: bs4.element.Tag | None = soup.find('div', attrs={'class': 'product', 'data-product-id': '123'})
if product:
print(product)
Поиск по частичному совпадению значений атрибутов
BeautifulSoup позволяет искать теги, у которых значение атрибута частично совпадает с заданным значением. Для этого используются регулярные выражения.
import re
from bs4 import BeautifulSoup
html_doc: str = """
<a href="/products/phone-123">Phone 123</a>
<a href="/products/tablet-456">Tablet 456</a>
<a href="/about">About Us</a>
"""
soup: BeautifulSoup = BeautifulSoup(html_doc, 'lxml')
# Найти все ссылки, у которых href содержит '/products/'
products_links: list[bs4.element.Tag] = soup.find_all('a', href=re.compile(r'/products/'))
for link in products_links:
print(link)
Работа с множественными атрибутами и их значениями
Получение списка всех атрибутов тега
Атрибуты тега хранятся в словаре attrs
:
from bs4 import BeautifulSoup
html_doc: str = '<a href="https://www.example.com" class="external-link" data-id="1">Ссылка</a>'
soup: BeautifulSoup = BeautifulSoup(html_doc, 'lxml')
link: bs4.element.Tag = soup.a
all_attributes: dict[str, str] = link.attrs
print(all_attributes) # Output: {'href': 'https://www.example.com', 'class': ['external-link'], 'data-id': '1'}
Изменение значений атрибутов
Значения атрибутов можно изменять напрямую через словарь attrs
:
«`python
from bs4 import BeautifulSoup
html_doc: str = ‘Ссылка‘
soup: BeautifulSoup = BeautifulSoup(html_doc, ‘lxml’)
link: bs4.element.Tag = soup.a
link[‘href’] = ‘https://www.new-example.com’
link[‘class’] = ‘internal-link’
print(link) # Output: <a class=