Теги и текст
Веб-страница — это текст на языке HTML: содержимое размечено тегами. <h1> — заголовок, <p> — абзац, <a> — ссылка, <li> — пункт списка. Теги вкладываются друг в друга и образуют дерево:
<html>
<head><title>Магазин</title></head>
<body>
<h1>Товары</h1>
<ul>
<li>Чай <b>250</b></li>
<li>Кофе <b>400</b></li>
</ul>
</body>
</html>
Достать из такой страницы нужные данные — цены, заголовки, ссылки — задача парсинга (разбора). Регулярными выражениями это делать неудобно и ненадёжно. Библиотека BeautifulSoup строит дерево тегов и даёт удобно по нему ходить.
Как начать
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, "html.parser")
- первый аргумент — текст страницы (строка);
- второй — какой разборщик использовать.
"html.parser"встроен в Python и всегда доступен.
Обычно HTML получают по сети (библиотекой requests), но в задачах этого курса страница приходит во входных данных — целиком её читают так: sys.stdin.read().
BeautifulSoup терпим к ошибкам: незакрытые теги и лишние пробелы его не пугают. Имена тегов он приводит к нижнему регистру, так что <H2> найдётся как "h2".
Поиск тегов
soup.find("li") # первый <li> или None, если его нет
soup.find_all("li") # список всех <li>
soup.find_all(["h1", "h2"]) # теги нескольких видов
soup.title # короткая запись для soup.find("title")
Искать можно не только во всём документе, но и внутри найденного тега — у него те же методы:
ul = soup.find("ul")
for li in ul.find_all("li"):
price = li.find("b") # <b> внутри этого <li>
Текст тега
li = soup.find("li")
print(li) # <li>Чай <b>250</b></li> — тег целиком
print(li.get_text()) # Чай 250 — весь текст, включая вложенные теги
print(li.find("b").get_text()) # 250
print(li.get_text().strip()) # без пробелов по краям
get_text()(или свойство.text) собирает текст тега и всех вложенных;.strip()у полученной строки убирает пробелы и переводы строк по краям:li.get_text().strip();- параметр
strip=Trueдействует иначе: он обрезает каждый кусочек текста и склеивает их без пробелов — для<p>Привет, <b>мир</b></p>получитсяПривет,мир. Он удобен, когда в теге одно число или одно слово.
Есть ещё свойство .string — оно работает, только если внутри тега ровно один кусок текста без вложенных тегов, иначе возвращает None. Поэтому для текста надёжнее get_text().
Помните, что текст — это строка. Число из него получают через int(...) или float(...).
Итог
BeautifulSoup(html, "html.parser")— дерево тегов;find(тег)— первый илиNone;find_all(тег)— список всех;- поиск работает и внутри найденного тега;
get_text().strip()— текст без разметки и пробелов по краям.