Содержание
Что такое парсинг?
Парсинг (англ. parsing) — это процесс анализа и разбора структурированных данных, чаще всего в текстовом формате, с целью извлечения нужной информации или преобразования данных в более удобный для работы формат.Парсинг широко используется в информационных технологиях и программировании для работы с различными типами данных, такими как текстовые документы, HTML-страницы, XML-файлы, JSON-данные и другие. Примеры сфер, где применяется парсинг:
- Веб-скрапинг: Извлечение информации с веб-сайтов, такой как заголовки новостей, цены товаров, рейтинги и многое другое.
- Обработка HTML и XML: Анализ и извлечение данных из HTML-страниц и XML-документов.
- Обработка текстов: Разбор и анализ текстовых документов, таких как логи, журналы и др.
- Работа с данными форматов обмена: Парсинг и создание данных в форматах, таких как JSON, CSV, XML, YAML и другие.
- Анализ и обработка данных: Извлечение, преобразование и агрегирование данных для последующего анализа.
Beautiful Soup
Beautiful Soup — это библиотека программирования на языке Python, которая помогает анализировать и извлекать данные из HTML и XML документов.Она используется для «парсинга» веб-страниц и других текстовых документов, чтобы найти и извлечь нужную информацию. Простыми словами, Beautiful Soup делает следующее:
- Скачивает веб-страницу: Она позволяет вам получить веб-страницу с интернета или загрузить уже существующий HTML-файл.
- Разбирает HTML или XML: Beautiful Soup анализирует структуру страницы, как если бы это было деревом с разными элементами, такими как заголовки, ссылки, текст и так далее.
- Извлекает данные: С помощью Beautiful Soup, вы можете легко найти и извлечь конкретные части информации с этой страницы. Например, заголовки новостей, цены товаров или ссылки на изображения.
- Облегчает работу с данными: Благодаря этой библиотеке, вы можете преобразовать сложный HTML-код в удобный для работы формат, что позволяет вам анализировать и использовать данные в своих программных проектах.
Начало работы с Beautiful Soup
Прежде чем мы начнем парсить веб-страницы, нам нужно установить необходимые инструменты и настроить рабочее окружение. В этом разделе мы рассмотрим, как установить BeautifulSoup и библиотеку Requests, а также как правильно их импортировать и использовать. Для парсинга веб-страниц с помощью Python нам понадобятся две библиотеки: BeautifulSoup и Requests. Requests позволяет нам легко загружать веб-страницы, отправляя HTTP-запросы. Это как если бы вы вручную открыли браузер и перешли по адресу сайта, но всё происходит программно. BeautifulSoup помогает нам анализировать HTML и извлекать нужные данные из полученного кода. Для установки этих библиотек нам нужно использовать командуpip – это менеджер пакетов для Python, который позволяет легко устанавливать и управлять библиотеками.
Как установить Beautiful Soup
Сначала вам нужно установить Beautiful Soup с помощью pip (установщика пакетов Python). Откройте командную строку (терминал) и выполните следующую команду:pip install beautifulsoup4
pip install requests
Эта команда загрузит и установит Beautiful Soup и его зависимости.
Подключаем Beautiful Soup к своему проекту
После установки библиотек мы можем импортировать их в наш Python-скрипт. Это позволит нам использовать их функции и методы. Создайте новый файл с расширением.py, например parsing_example.py, и напишите в нем следующие строки:
# Задаем URL-адрес сайта, который хотим загрузить
url = 'https://example.com'
# Отправляем HTTP-запрос и получаем ответ
response = requests.get(url)
# Извлекаем HTML-код страницы
html_content = response.text
# Создаем объект BeautifulSoup для анализа HTML-кода
soup = BeautifulSoup(html_content, 'html.parser')
# Выводим HTML-код страницы
print(soup.prettify())
Что происходит в этом коде:
- URL-адрес: Мы указываем URL-адрес страницы, которую хотим загрузить (вместо example.com подставьте адрес существующей веб страницы).
- Запрос: Отправляем HTTP-запрос к этому URL с помощью Requests и получаем ответ.
- HTML-код: Извлекаем HTML-код из ответа.
- BeautifulSoup: Создаем объект BeautifulSoup, который поможет нам анализировать HTML-код.
- Вывод: Выводим HTML-код страницы в отформатированном виде.
Основные понятия и создание объекта BeautifulSoup
Чтобы начать парсить веб-страницы, важно понять основные элементы HTML и как использовать BeautifulSoup для работы с ними. В этом разделе мы рассмотрим, что такое HTML, теги и атрибуты, а также как создать объект BeautifulSoup для анализа HTML-кода.Основные понятия HTML
HTML (HyperText Markup Language) – это язык разметки, используемый для создания веб-страниц. HTML состоит из различных элементов, которые описывают структуру и содержание страницы. Основные понятия, которые вам нужно знать:- Теги: Теги обрамляют элементы HTML и указывают, как они должны отображаться в браузере. Примеры тегов:
<html>,<head>,<title>,<body>,<h1>,<p>,<a>. - Атрибуты: Атрибуты содержат дополнительную информацию о элементах HTML. Пример:
<a href="https://example.com">Example</a>– здесьhrefявляется атрибутом тега<a>. - Текст: Текст – это содержимое между открывающим и закрывающим тегами, которое отображается на странице.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Scraping Demo</title>
</head>
<body>
<h1>Добро пожаловать на тренировочную страницу по парсингу</h1>
<p>Эта страница создана для демонстрации возможностей библиотеки BeautifulSoup.</p>
<h2>Заголовки</h2>
<p>Это пример параграфа с <a href="https://example.com/link1">ссылкой 1</a> и <a href="https://example.com/link2">ссылкой 2</a>.</p>
<h2>Список статей</h2>
<ul>
<li><a href="https://example.com/article1">Статья 1</a></li>
<li><a href="https://example.com/article2">Статья 2</a></li>
<li><a href="https://example.com/article3">Статья 3</a></li>
</ul>
<h2>Изображения</h2>
<img src="https://example.com/image1.jpg" alt="Изображение 1">
<img src="https://example.com/image2.jpg" alt="Изображение 2">
</body>
</html>
Создание объекта BeautifulSoup
Теперь, когда у нас есть базовое понимание HTML, давайте научимся создавать объект BeautifulSoup для работы с HTML-кодом.Шаг 1: Получение HTML кода страницы
Мы будем использовать библиотеку Requests для загрузки страницыhttps://victor-komlev.ru/scraping_demo.
import requests
# Задаем URL-адрес тренировочной страницы
url = 'https://victor-komlev.ru/scraping_demo'
# Отправляем HTTP-запрос и получаем ответ
response = requests.get(url)
# Извлекаем HTML-код страницы
html_content = response.text
Шаг 2: Создание объекта BeautifulSoup
После получения HTML-кода мы создаем объект BeautifulSoup для анализа HTML-кода.from bs4 import BeautifulSoup
# Создаем объект BeautifulSoup для анализа HTML-кода
soup = BeautifulSoup(html_content, 'html.parser')
Здесь мы используем два параметра:
- html_content: HTML-код, который мы получили от Requests.
- ‘html.parser’: Встроенный парсер Python для анализа HTML-кода. Это простой и эффективный способ обработки HTML.
Изучение структуры HTML документа
Теперь давайте рассмотрим, как использовать BeautifulSoup для извлечения данных из нашей тренировочной страницы. 1. Заголовок страницы Мы можем получить заголовок страницы, находящийся в теге<title>.
title = soup.title
print(title) # <title>Scraping Demo</title>
print(title.name) # title
print(title.string) # Scraping Demo
2. Поиск всех ссылок
Мы можем найти все теги <a> на странице, которые представляют собой ссылки.
links = soup.find_all('a')
for link in links:
print(link.get('href'))
Этот код найдет все теги <a> и выведет значения атрибута href для каждой ссылки.
3. Извлечение текста
Мы можем извлечь текстовое содержимое всей страницы или отдельных элементов.
page_text = soup.get_text()
print(page_text)
Этот метод извлекает весь текст с HTML-страницы, удаляя теги.
Полный код для примера
Полный код для получения и анализа HTML-кода нашей тренировочной страницы:import requests
from bs4 import BeautifulSoup
# Задаем URL-адрес тренировочной страницы
url = 'https://victor-komlev.ru/scraping_demo'
# Отправляем HTTP-запрос и получаем ответ
response = requests.get(url)
# Извлекаем HTML-код страницы
html_content = response.text
# Создаем объект BeautifulSoup для анализа HTML-кода
soup = BeautifulSoup(html_content, 'html.parser')
# Пример 1: Получение заголовка страницы
title = soup.title
print(title) # <title>Scraping Demo</title>
print(title.name) # title
print(title.string) # Scraping Demo
# Пример 2: Поиск всех ссылок
links = soup.find_all('a')
for link in links:
print(link.get('href'))
# Пример 3: Извлечение текста страницы
page_text = soup.get_text()
print(page_text)
Задания для закрепления пройденного материала
Задание 1
Описание: Извлечь текст всех заголовков (теги <h2>) со страницы и вывести их на экран.
Задание 2 Описание: Извлечь данные из таблицы, расположенной на странице, и вывести их в виде списка словарей.
Решения
import requests
from bs4 import BeautifulSoup
# Задаем URL-адрес тренировочной страницы
url = 'https://victor-komlev.ru/scraping_demo'
# Отправляем HTTP-запрос и получаем ответ
response = requests.get(url)
# Извлекаем HTML-код страницы
html_content = response.text
# Создаем объект BeautifulSoup для анализа HTML-кода
soup = BeautifulSoup(html_content, 'html.parser')
# Задание 1: Извлечь текст всех заголовков <h2> и вывести их на экран
h2_tags = soup.find_all('h2')
for tag in h2_tags:
print(tag.get_text())
print("\n" + "="*20 + "\n") # Разделитель между заданиями
# Задание 2: Извлечь данные из таблицы и вывести их в виде списка словарей
table = soup.find('table')
rows = table.find_all('tr')
table_data = []
# Извлекаем заголовки таблицы
headers = [header.get_text() for header in rows[0].find_all('th')]
# Извлекаем строки данных
for row in rows[1:]:
cells = row.find_all('td')
cell_data = [cell.get_text() for cell in cells]
row_dict = dict(zip(headers, cell_data))
table_data.append(row_dict)
# Выводим данные таблицы в виде списка словарей
for item in table_data:
print(item)
Из чего состоит веб-страница. HTML теги
Любая страница сайта представляет собой HTML документ.HTML (Hypertext Markup Language) — это стандартный язык разметки, используемый для создания веб-страниц и определения их структуры и содержания. HTML-документ представляет собой текстовый файл, который браузер интерпретирует и отображает веб-страницу для пользователя.HTML состоит из множества элементов, которые называются тегами. Теги — это основные строительные блоки HTML-документа и выделяются угловыми скобками
< >. Они имеют открывающий и закрывающий теги, которые обрамляют содержимое элемента. Например, <p> — это открывающий тег для абзаца, а </p> — закрывающий тег. Теги определяют тип и структуру элемента на странице.
Предназначение тегов зависит от их названия и роли. Например:
<html>— определяет начало и конец HTML-документа.<head>— содержит метаданные и информацию о документе, такие как заголовок страницы, ссылки на стили и другие настройки.<body>— содержит основное содержание страницы, такие как текст, изображения, ссылки и другие элементы, видимые для пользователя.<p>— используется для создания абзацев текста.<a>— создает гиперссылки на другие страницы или ресурсы.
Атрибуты HTML тегов
Атрибуты тегов (HTML attributes) — это дополнительные сведения или параметры, которые могут быть добавлены к HTML-элементам для определения их характеристик, поведения или внешнего вида. Атрибуты помогают уточнить, как должен вести себя или отображаться элемент на веб-странице. Атрибуты всегда указываются внутри открывающего тега элемента и обычно имеют видимя="значение".
Вот несколько примеров атрибутов и их предназначения:
- Атрибут
src(source):- Используется в теге
<img>для указания пути к изображению, которое должно быть отображено на странице. - Пример:
<img src="image.jpg" alt="Описание изображения">.
- Используется в теге
- Атрибут
href(hypertext reference):- Используется в теге
<a>для создания гиперссылок и указания URL-адреса, на который следует перейти при клике на ссылку. - Пример:
<a href="https://www.example.com">Ссылка на пример</a>.
- Используется в теге
- Атрибут
class:- Используется для присвоения одному или нескольким элементам одного класса, который может быть использован для применения стилей из таблицы стилей (CSS) или для выборки элементов с помощью JavaScript.
- Пример:
<div class="highlighted">Выделенный текст</div>.
- Атрибут
id:- Используется для уникальной идентификации элемента на странице. Каждый
idдолжен быть уникальным в рамках всего документа. - Пример:
<p id="unique-paragraph">Уникальный абзац</p>.
- Используется для уникальной идентификации элемента на странице. Каждый
- Атрибут
alt(alternative text):- Используется в теге
<img>для предоставления текстовой альтернативы изображению, которая будет отображаться в случае, если изображение не может быть загружено или доступно для некоторых пользователей (например, для пользователей с ограниченным зрением). - Пример:
<img src="image.jpg" alt="Описание изображения">.
- Используется в теге
Атрибуты class и id
class и id — это атрибуты, которые могут быть присвоены HTML-элементам для определения их стиля и идентификации с помощью CSS (каскадных таблиц стилей) и JavaScript. Вот их более подробное описание:
class(класс):class— это атрибут, который присваивается одному или нескольким HTML-элементам с одним и тем же именем класса.- Он используется для применения одинакового стиля или форматирования к нескольким элементам.
- Несколько элементов могут иметь одинаковый
class, что позволяет им совместно использовать общие стили. - В CSS вы можете выбрать элементы с определенным классом, используя селектор
.classname.
class:
<p class="highlight">Этот текст будет выделен</p>
<p class="highlight">Этот текст также будет выделен</p>
id(идентификатор):id— это атрибут, который присваивается уникальному HTML-элементу на странице.- Каждый
idдолжен быть уникальным на всей веб-странице; в противном случае это будет недопустимо. idобычно используется для идентификации конкретного элемента и применения к нему уникальных стилей или для взаимодействия с элементом с помощью JavaScript.- В CSS вы можете выбрать элемент с определенным
id, используя селектор#idname.
id:
<div id="unique-element">Этот элемент уникален и его можно идентифицировать по id</div>
Использование class и id позволяет разработчикам более точно управлять структурой и стилями веб-страницы, а также обеспечивает уникальную идентификацию элементов для взаимодействия с ними через скрипты.
Получение и поиск необходимых элементов. Навигация по HTML
Когда мы работаем с HTML-документом, важно уметь находить нужные элементы и перемещаться по его структуре. В этом разделе мы рассмотрим, как использовать методы поиска и навигацию по дереву элементов с помощью BeautifulSoup.Шаг 1: Методы поиска
BeautifulSoup предоставляет несколько методов для поиска элементов в HTML-документе. Основные из них:find: Находит первый элемент, соответствующий заданным критериям.first_h1 = soup.find('h1') print(first_h1.text) # Выводит текст первого элемента <h1>find_all: Находит все элементы, соответствующие заданным критериям.all_h2 = soup.find_all('h2') for h2 in all_h2: print(h2.text) # Выводит текст всех элементов <h2>findс атрибутами: Мы можем искать элементы по тегам и атрибутам.first_link = soup.find('a', href='https://example.com/link1') print(first_link.text) # Выводит текст ссылки с заданным href- Поиск по классу и id: Мы можем искать элементы по классу или id.
element_by_class = soup.find(class_='example-class') element_by_id = soup.find(id='example-id') print(element_by_class.text) print(element_by_id.text)
Шаг 2: Навигация по дереву
HTML-документ имеет древовидную структуру, где элементы могут быть вложены друг в друга. BeautifulSoup предоставляет методы для перемещения по этому дереву.- Родительские элементы: Мы можем получить родительский элемент текущего элемента с помощью свойства
parent.child_element = soup.find('h2') parent_element = child_element.parent print(parent_element.name) # Выводит имя родительского тега
Свойствоtag.parentsparentsвозвращает генератор, который позволяет итерироваться по всем родительским элементам данного тега, вплоть до корневого элемента. Пример использования:# Находим элемент <a> с определенным href link = soup.find('a', href='https://example.com/link1') # Получаем всех родительских элементов этого <a> for parent in link.parents: print(parent.name) # Выводим имя каждого родительского элементаtag.parentvstag.parentstag.parent: Возвращает непосредственный родительский элемент данного тега.tag.parents: Возвращает генератор, который позволяет итерироваться по всем родительским элементам данного тега.
- Дочерние элементы: Мы можем получить все дочерние элементы текущего элемента с помощью свойства
childrenилиcontents.parent_element = soup.find('div') for child in parent_element.children: print(child) # Выводит всех непосредственных дочерних элементов
Свойствоtag.contentscontentsвозвращает список всех дочерних элементов тега. Оно включает в себя как теги, так и текстовые узлы. Пример использования:
Сравните это с методом# Находим элемент <div> с id 'content' content_div = soup.find('div', id='content') # Получаем все дочерние элементы этого <div> children = content_div.contents for child in children: print(child) # Выводим каждый дочерний элемент (включая текстовые узлы)children, который возвращает генератор, позволяющий итерироваться по дочерним элементам. Основное отличие в том, чтоcontentsвозвращает все дочерние элементы сразу в виде списка, аchildrenвозвращает генератор, что может быть полезно при работе с большими документами. - Соседние элементы: Мы можем получить следующий и предыдущий элементы на том же уровне дерева с помощью свойств
next_siblingиprevious_sibling.first_h2 = soup.find('h2') next_element = first_h2.next_sibling prev_element = first_h2.previous_sibling print(next_element) # Выводит следующий элемент print(prev_element) # Выводит предыдущий элемент - Десценденты (потомки): Мы можем получить всех потомков текущего элемента с помощью свойства
descendants.parent_element = soup.find('div') for descendant in parent_element.descendants: print(descendant) # Выводит всех потомков элемента
scraping_demo с древовидной структурой
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Scraping Demo</title>
</head>
<body>
<h1>Добро пожаловать на тренировочную страницу по парсингу</h1>
<p>Эта страница создана для демонстрации возможностей библиотеки BeautifulSoup.</p>
<div id="content">
<h2>Заголовки</h2>
<p>Это пример параграфа с <a href="https://example.com/link1">ссылкой 1</a> и <a href="https://example.com/link2">ссылкой 2</a>.</p>
<div class="nested">
<h3>Вложенный заголовок</h3>
<p>Вложенный параграф.</p>
</div>
<h2>Список статей</h2>
<ul>
<li><a href="https://example.com/article1">Статья 1</a></li>
<li><a href="https://example.com/article2">Статья 2</a></li>
<li><a href="https://example.com/article3">Статья 3</a></li>
</ul>
<h2>Изображения</h2>
<img src="https://example.com/image1.jpg" alt="Изображение 1">
<img src="https://example.com/image2.jpg" alt="Изображение 2">
<h2>Таблица данных</h2>
<table>
<tr>
<th>Имя</th>
<th>Возраст</th>
<th>Город</th>
</tr>
<tr>
<td>Алексей</td>
<td>29</td>
<td>Москва</td>
</tr>
<tr>
<td>Мария</td>
<td>24</td>
<td>Санкт-Петербург</td>
</tr>
<tr>
<td>Иван</td>
<td>31</td>
<td>Новосибирск</td>
</tr>
</table>
</div>
</body>
</html>
Примеры поиска и навигации с использованием обновленной страницы
import requests
from bs4 import BeautifulSoup
# Задаем URL-адрес тренировочной страницы
url = 'https://victor-komlev.ru/scraping_demo'
# Отправляем HTTP-запрос и получаем ответ
response = requests.get(url)
# Извлекаем HTML-код страницы
html_content = response.text
# Создаем объект BeautifulSoup для анализа HTML-кода
soup = BeautifulSoup(html_content, 'html.parser')
# Поиск элементов
# Находим первый <h2> элемент
first_h2 = soup.find('h2')
print("Первый <h2> элемент:", first_h2.text) # Выводит текст первого <h2> элемента
# Находим все <h2> элементы
all_h2 = soup.find_all('h2')
print("Все <h2> элементы:")
for h2 in all_h2:
print(h2.text) # Выводит текст всех <h2> элементов
# Находим элемент <a> с определенным href
first_link = soup.find('a', href='https://example.com/link1')
print("Ссылка с href='https://example.com/link1':", first_link.text)
# Находим элемент по классу
nested_div = soup.find('div', class_='nested')
print("Текст внутри <div class='nested'>:", nested_div.text.strip()) # strip() убирает лишние пробелы
# Находим элемент по id
content_div = soup.find('div', id='content')
print("Текст внутри <div id='content'>:", content_div.text.strip())
# Навигация по дереву
# Родительские элементы
parent_element = first_h2.parent
print("Родительский элемент для первого <h2>:", parent_element.name) # Выводит имя родительского тега
# Дочерние элементы
print("Дочерние элементы <div id='content'>:")
for child in content_div.children:
if child.name: # Выводим только теги (не текст)
print(child.name)
# Соседние элементы
next_sibling = first_h2.find_next_sibling()
prev_sibling = first_h2.find_previous_sibling()
print("Следующий соседний элемент для первого <h2>:", next_sibling.name) # Выводит следующий соседний элемент
print("Предыдущий соседний элемент для первого <h2>:", prev_sibling.name) # Выводит предыдущий соседний элемент
# Десценденты
print("Все потомки <div id='content'>:")
for descendant in content_div.descendants:
if descendant.name: # Выводим только теги (не текст)
print(descendant.name)
Объяснение кода
- Импорт библиотек и получение HTML-кода страницы: Мы импортируем библиотеки BeautifulSoup и Requests, а затем загружаем HTML-код тренировочной страницы.
- Создание объекта BeautifulSoup: Мы создаем объект BeautifulSoup, который поможет нам анализировать HTML-код.
- Поиск элементов:
find: Находит первый элемент<h2>и выводит его текст.find_all: Находит все элементы<h2>и выводит их текст.findс атрибутами: Находит первый элемент<a>с атрибутомhref='https://example.com/link1'и выводит его текст.findпо классу: Находит элемент<div>с классомnestedи выводит его текст.findпо id: Находит элемент<div>с idcontentи выводит его текст.
- Навигация по дереву:
- Родительские элементы: Используем
parent, чтобы получить родительский элемент для первого<h2>. - Дочерние элементы: Используем
children, чтобы получить всех непосредственных дочерних элементов внутри<div id='content'>. - Соседние элементы: Используем
next_siblingиprevious_sibling, чтобы получить следующий и предыдущий элементы на том же уровне. - Десценденты: Используем
descendants, чтобы получить всех потомков внутри<div id='content'>.
- Родительские элементы: Используем
Задания для тренировки
Задание 3: Извлечь текст всех элементов<h2>и их последующих элементов<p>На страницеhttps://victor-komlev.ru/scraping_demoнайдите все элементы<h2>и извлеките текст этих элементов, а также текст первого последующего за ними параграфа<p>.
Задание 4: Найти все ссылки в списке статей и вывести их текст и атрибутhrefИзвлеките все ссылки (<a>) внутри списка статей (тег<ul>) и выведите их текст и значения атрибутовhref.
Задание 5: Извлечь данные из таблицы Найдите таблицу на странице и извлеките данные из всех строк таблицы. Сохраните данные в виде списка словарей, где ключами будут заголовки столбцов.
Решения заданий
import requests
from bs4 import BeautifulSoup
# Задаем URL-адрес тренировочной страницы
url = 'https://victor-komlev.ru/scraping_demo'
# Отправляем HTTP-запрос и получаем ответ
response = requests.get(url)
# Извлекаем HTML-код страницы
html_content = response.text
# Создаем объект BeautifulSoup для анализа HTML-кода
soup = BeautifulSoup(html_content, 'html.parser')
# Задание 3: Извлечь текст всех элементов <h2> и их последующих элементов <p>
print("Задание 3:")
h2_elements = soup.find_all('h2')
for h2 in h2_elements:
print("Заголовок <h2>:", h2.text)
next_p = h2.find_next_sibling('p')
if next_p:
print("Параграф:", next_p.text)
# Задание 4: Найти все ссылки в списке статей и вывести их текст и атрибут href
print("\nЗадание 4:")
article_list = soup.find('ul')
article_links = article_list.find_all('a')
for link in article_links:
print("Текст ссылки:", link.text)
print("URL ссылки:", link['href'])
# Задание 5: Извлечь данные из таблицы
print("\nЗадание 5:")
table = soup.find('table')
headers = [header.text for header in table.find_all('th')]
rows = table.find_all('tr')[1:] # Пропускаем заголовок таблицы
data = []
for row in rows:
cells = row.find_all('td')
row_data = {headers[i]: cells[i].text for i in range(len(cells))}
data.append(row_data)
print("Данные таблицы:")
for row_data in data:
print(row_data)
Объяснение кода
Задание 3
- Используем
find_allдля нахождения всех элементов<h2>. - Для каждого элемента
<h2>используем методfind_next_sibling('p'), чтобы найти первый последующий элемент<p>. - Выводим текст каждого элемента
<h2>и соответствующего элемента<p>.
- Находим элемент
<ul>, содержащий список статей. - Используем
find_all('a')внутри списка, чтобы найти все ссылки. - Для каждой ссылки выводим текст ссылки и значение атрибута
href.
- Находим элемент
<table>. - Извлекаем заголовки столбцов из элементов
<th>. - Пропускаем первую строку таблицы (она содержит заголовки) и обрабатываем остальные строки.
- Извлекаем данные из ячеек каждой строки
<td>и сохраняем их в виде списка словарей.
Извлечение данных
Извлечение данных из HTML-документа — это один из ключевых навыков при работе с BeautifulSoup. Давайте рассмотрим, как получать текст и атрибуты из HTML-элементов.Шаг 1: Получение текста
Когда вы ищете элементы на веб-странице, часто вам нужно будет получить текст, который содержится внутри этих элементов. BeautifulSoup предоставляет несколько способов для извлечения текста. Примеры кодаimport requests
from bs4 import BeautifulSoup
# Задаем URL-адрес тренировочной страницы
url = 'https://victor-komlev.ru/scraping_demo'
# Отправляем HTTP-запрос и получаем ответ
response = requests.get(url)
# Извлекаем HTML-код страницы
html_content = response.text
# Создаем объект BeautifulSoup для анализа HTML-кода
soup = BeautifulSoup(html_content, 'html.parser')
# Извлечение текста из заголовка <h1>
h1 = soup.find('h1')
h1_text = h1.text
print("Текст заголовка <h1>:", h1_text)
# Извлечение текста из первого параграфа <p>
p = soup.find('p')
p_text = p.text
print("Текст первого параграфа <p>:", p_text)
# Извлечение текста всех заголовков <h2>
all_h2 = soup.find_all('h2')
for h2 in all_h2:
print("Текст заголовка <h2>:", h2.text)
Объяснение кода
- Извлечение текста из заголовка
<h1>:- Находим элемент
<h1>с помощью методаfind. - Извлекаем текст этого элемента с помощью свойства
text. - Выводим текст заголовка
<h1>.
- Находим элемент
- Извлечение текста из первого параграфа
<p>:- Находим элемент
<p>с помощью методаfind. - Извлекаем текст этого элемента с помощью свойства
text. - Выводим текст первого параграфа
<p>.
- Находим элемент
- Извлечение текста всех заголовков
<h2>:- Находим все элементы
<h2>с помощью методаfind_all. - Итерируемся по каждому элементу
<h2>. - Извлекаем и выводим текст каждого заголовка
<h2>.
- Находим все элементы
Шаг 2: Извлечение атрибутов
HTML-элементы могут содержать различные атрибуты, такие какhref у ссылок <a> или src у изображений <img>. BeautifulSoup позволяет легко извлекать эти атрибуты.
Примеры кода
# Извлечение атрибута href из первой ссылки <a>
first_link = soup.find('a')
link_href = first_link['href']
print("URL первой ссылки <a>:", link_href)
# Извлечение атрибута src из первого изображения <img>
first_image = soup.find('img')
image_src = first_image['src']
print("URL первого изображения <img>:", image_src)
# Извлечение всех атрибутов ссылки <a>
link_attrs = first_link.attrs
print("Все атрибуты первой ссылки <a>:", link_attrs)
Объяснение кода
- Извлечение атрибута
hrefиз первой ссылки<a>:- Находим первый элемент
<a>с помощью методаfind. - Извлекаем значение атрибута
hrefэтого элемента. - Выводим URL первой ссылки
<a>.
- Находим первый элемент
- Извлечение атрибута
srcиз первого изображения<img>:- Находим первый элемент
<img>с помощью методаfind. - Извлекаем значение атрибута
srcэтого элемента. - Выводим URL первого изображения
<img>.
- Находим первый элемент
- Извлечение всех атрибутов ссылки
<a>:- Находим первый элемент
<a>с помощью методаfind. - Извлекаем все атрибуты этого элемента в виде словаря.
- Выводим все атрибуты первой ссылки
<a>.
- Находим первый элемент
Практическое применение Beautiful Soup
Задача. Дана статья https://habr.com/ru/articles/764440/. Получить все заголовки статьи h1-h4. И на основании нее вывести многоуровневый список со структурой данной статьи.import requests
from bs4 import BeautifulSoup
# URL веб-страницы для парсинга
url = 'https://habr.com/ru/articles/764440/'
# Отправка GET-запроса к веб-странице и получение HTML-кода
response = requests.get(url)
# Проверка успешности запроса
if response.status_code == 200:
# Создание объекта Beautiful Soup для анализа HTML
soup = BeautifulSoup(response.text, 'html.parser')
# Находим все заголовки h1-h4 на странице
headers = soup.find_all(['h1', 'h2', 'h3', 'h4'])
# Инициализируем многоуровневый список
nested_list = []
# Проходимся по найденным заголовкам
for header in headers:
# Получаем текст заголовка
header_text = header.text.strip()
# Определяем уровень заголовка
header_level = int(header.name[1]) # Получаем цифру из имени тега (например, 1 из "h1")
# Создаем элемент списка для текущего заголовка
current_item = {'text': header_text, 'children': []}
# Добавляем элемент в нужный уровень списка
parent = nested_list
for _ in range(header_level - 1):
parent = parent[-1]['children']
parent.append(current_item)
# Функция для рекурсивного построения HTML-списка
def build_html_list(items):
result = "<ul>"
for item in items:
result += f"<li>{item['text']}"
if item['children']:
result += build_html_list(item['children'])
result += "</li>"
result += "</ul>"
return result
# Строим HTML-список на основе структуры
html_list = build_html_list(nested_list)
# Выводим HTML-список
print(html_list)
else:
print("Не удалось получить страницу. Код ответа:", response.status_code)
Этот код отправляет GET-запрос к указанной странице, а затем, если запрос прошел успешно (код ответа 200), использует Beautiful Soup для поиска всех заголовков h1-h4 на странице. Затем код строит многоуровневый список на основе структуры заголовков и преобразует его в HTML-список с вложенными элементами <ul> и <li>. Рекурсивная функция build_html_list используется для построения HTML-списка.
После выполнения этого кода, вы получите многоуровневый список, отражающий структуру заголовков h1-h4 на странице.
Усовершенствуем пример. Добавим в результат не только заголовки, но и контент в тегах <p> после заголовков.
import requests
from bs4 import BeautifulSoup
# URL веб-страницы для парсинга
url = 'https://habr.com/ru/articles/764440/'
# Отправка GET-запроса к веб-странице и получение HTML-кода
response = requests.get(url)
# Проверка успешности запроса
if response.status_code == 200:
# Создание объекта Beautiful Soup для анализа HTML
soup = BeautifulSoup(response.text, 'html.parser')
# Находим div с id="post-content-body"
content_div = soup.find('div', {'id': 'post-content-body'})
if content_div:
# Инициализируем многоуровневый список
nested_list = []
# Находим все элементы внутри div с id="post-content-body"
elements = content_div.find_all()
current_item = None
# Проходимся по найденным элементам
for element in elements:
# Если элемент - заголовок h1-h4
if element.name and element.name.startswith('h') and element.name!='hr':
# Получаем текст заголовка
header_text = element.text.strip()
print (element.name)
# Определяем уровень заголовка
header_level = int(element.name[1]) # Получаем цифру из имени тега (например, 1 из "h1")
# Находим все теги <p> после заголовка и объединяем их в контент
content_paragraphs = []
next_sibling = element.find_next_sibling()
while next_sibling and next_sibling.name == 'p':
content_paragraphs.append(next_sibling.text.strip())
next_sibling = next_sibling.find_next_sibling()
# Создаем элемент списка для текущего заголовка
current_item = {'text': header_text, 'content': ' '.join(content_paragraphs), 'children': []}
# Добавляем элемент в нужный уровень списка
parent = nested_list
for _ in range(header_level - 1):
if parent:
parent = parent[-1]['children']
parent.append(current_item)
elif current_item is not None:
# Если текущий элемент - не заголовок, добавляем его в "content" предыдущего элемента
current_item['content'] += str(element)
# Функция для рекурсивного построения HTML-списка
def build_html_list(items):
result = "<ul>"
for item in items:
result += f"<li>{item['text']} <p>{item['content']}</p>"
if item['children']:
result += build_html_list(item['children'])
result += "</li>"
result += "</ul>"
return result
# Строим HTML-список на основе структуры
html_list = build_html_list(nested_list)
# Выводим HTML-список
print(html_list)
else:
print("Не удалось найти div с id='post-content-body' на странице.")
else:
print("Не удалось получить страницу. Код ответа:", response.status_code)
Обработка ошибок и исключений
Работа с веб-страницами и их содержимым может быть непредсказуемой. Серверы могут не отвечать, страницы могут не содержать нужных элементов, и многое другое может пойти не так. Поэтому очень важно уметь обрабатывать ошибки и исключения, чтобы ваш код не ломался и был устойчив к различным проблемам.Шаг 1: Обработка ошибок запросов
Первый шаг в работе с веб-страницей — это отправка HTTP-запроса. Этот процесс может завершиться с ошибками, например, если сервер не отвечает, если URL некорректен, или если у вас нет доступа к ресурсу. Для обработки этих ошибок в Python мы можем использовать библиотекуrequests вместе с конструкцией try-except.
Пример кода
import requests
# Задаем URL-адрес тренировочной страницы
url = 'https://victor-komlev.ru/scraping_demo'
try:
# Отправляем HTTP-запрос и получаем ответ
response = requests.get(url)
response.raise_for_status() # Проверяем, был ли запрос успешным (статус-код 200)
html_content = response.text
print("HTML-код страницы успешно загружен")
except requests.exceptions.HTTPError as http_err:
print(f"HTTP ошибка: {http_err}")
except requests.exceptions.ConnectionError as conn_err:
print(f"Ошибка соединения: {conn_err}")
except requests.exceptions.Timeout as timeout_err:
print(f"Превышено время ожидания: {timeout_err}")
except requests.exceptions.RequestException as req_err:
print(f"Ошибка запроса: {req_err}")
Объяснение кода
- Импортируем библиотеку
requests. - Устанавливаем URL страницы.
- Используем конструкцию
try-exceptдля отправки запроса и обработки возможных ошибок:requests.get(url): Отправляем HTTP-запрос.response.raise_for_status(): Если статус-код ответа не 200, вызывается исключениеHTTPError.- Обрабатываем различные исключения:
HTTPError: Ошибка, связанная с HTTP-запросом (например, 404 Not Found).ConnectionError: Ошибка соединения (например, сервер недоступен).Timeout: Ошибка, связанная с превышением времени ожидания ответа от сервера.RequestException: Общее исключение для всех ошибок, связанных с запросами.
Шаг 2: Проверка наличия тегов
После успешной загрузки HTML-кода, важно убедиться, что нужные вам элементы присутствуют на странице. Если элементы отсутствуют, ваш код может выдать ошибку при попытке доступа к ним. Для обработки таких ситуаций можно использовать проверки наличия тегов и конструкциюtry-except.
Пример кода
from bs4 import BeautifulSoup
# Загрузка HTML-кода (как результат успешного запроса)
html_content = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Scraping Demo</title>
</head>
<body>
<h1>Добро пожаловать на тренировочную страницу по парсингу</h1>
<div id="content">
<h2>Заголовки</h2>
<p>Это пример параграфа.</p>
</div>
</body>
</html>
"""
# Создаем объект BeautifulSoup для анализа HTML-кода
soup = BeautifulSoup(html_content, 'html.parser')
try:
# Пытаемся найти элемент <h1>
h1 = soup.find('h1')
if h1 is not None:
print("Текст заголовка <h1>:", h1.text)
else:
print("Элемент <h1> не найден")
except Exception as e:
print(f"Ошибка при поиске <h1>: {e}")
try:
# Пытаемся найти элемент <p> внутри <div id='content'>
content_div = soup.find('div', id='content')
if content_div is not None:
p = content_div.find('p')
if p is not None:
print("Текст параграфа <p> внутри <div>:", p.text)
else:
print("Элемент <p> не найден внутри <div id='content'>")
else:
print("Элемент <div id='content'> не найден")
except Exception as e:
print(f"Ошибка при поиске <p> внутри <div>: {e}")
Объяснение кода
- Создаем объект
BeautifulSoupдля анализа HTML-кода. - Проверяем наличие элементов и обрабатываем возможные исключения:
- Проверка наличия элемента
<h1>:- Используем метод
findдля поиска элемента<h1>. - Проверяем, найден ли элемент (
if h1 is not None). - Если элемент найден, выводим его текст, иначе выводим сообщение, что элемент не найден.
- Используем метод
- Проверка наличия элемента
<p>внутри элемента<div id='content'>:- Находим элемент
<div>с idcontent. - Проверяем, найден ли элемент
<div>. - Если элемент
<div>найден, ищем элемент<p>внутри него. - Проверяем, найден ли элемент
<p>. - Если элемент найден, выводим его текст, иначе выводим сообщение, что элемент не найден внутри
<div>.
- Находим элемент
- Проверка наличия элемента
Дополнительные возможности BeautifulSoup
BeautifulSoup — это мощная библиотека для парсинга HTML и XML документов. Помимо базовых возможностей, таких как поиск и извлечение данных из HTML, BeautifulSoup предлагает и дополнительные функции, которые делают его использование еще более гибким и удобным. Давайте рассмотрим две из них: парсинг XML и использование CSS селекторов.Шаг 1: Парсинг XML
XML (eXtensible Markup Language) — это язык разметки, используемый для хранения и передачи данных. Он похож на HTML, но с более строгими правилами синтаксиса. BeautifulSoup позволяет парсить XML так же просто, как и HTML. Пример кодаfrom bs4 import BeautifulSoup
# Пример XML-документа
xml_content = """
<catalog>
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
</book>
<book id="bk102">
<author>Ralls, Kim</author>
<title>Midnight Rain</title>
<genre>Fantasy</genre>
<price>5.95</price>
<publish_date>2000-12-16</publish_date>
</book>
</catalog>
"""
# Создаем объект BeautifulSoup для анализа XML-кода
soup = BeautifulSoup(xml_content, 'xml')
# Извлекаем все книги
books = soup.find_all('book')
for book in books:
# Извлекаем информацию о каждой книге
book_id = book['id']
author = book.find('author').text
title = book.find('title').text
genre = book.find('genre').text
price = book.find('price').text
publish_date = book.find('publish_date').text
print(f"ID книги: {book_id}")
print(f"Автор: {author}")
print(f"Название: {title}")
print(f"Жанр: {genre}")
print(f"Цена: {price}")
print(f"Дата публикации: {publish_date}")
print("---------")
Объяснение кода
- Создаем объект
BeautifulSoupдля анализа XML-кода:- Передаем XML-контент и указываем парсер
'xml'.
- Передаем XML-контент и указываем парсер
- Извлекаем все элементы
<book>:- Используем метод
find_all, чтобы найти все элементы<book>.
- Используем метод
- Извлекаем информацию о каждой книге:
- Итерируемся по всем найденным книгам.
- Для каждой книги извлекаем значения атрибутов и текстовое содержимое дочерних элементов.
Шаг 2: Использование CSS селекторов
CSS селекторы — это мощный инструмент, который позволяет выбирать элементы на основе их классов, идентификаторов и других атрибутов. BeautifulSoup поддерживает использование CSS селекторов через методselect.
Пример кода
from bs4 import BeautifulSoup
# Пример HTML-документа
html_content = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Scraping Demo</title>
</head>
<body>
<div id="content">
<h1 class="header">Добро пожаловать на тренировочную страницу по парсингу</h1>
<p class="description">Это пример параграфа.</p>
<a href="https://example.com/link1" class="external">Ссылка 1</a>
<a href="https://example.com/link2" class="external">Ссылка 2</a>
<div class="nested">
<span class="highlight">Вложенный элемент</span>
</div>
</div>
</body>
</html>
"""
# Создаем объект BeautifulSoup для анализа HTML-кода
soup = BeautifulSoup(html_content, 'html.parser')
# Используем CSS селектор для извлечения заголовка <h1> с классом 'header'
header = soup.select_one('h1.header')
print("Текст заголовка <h1> с классом 'header':", header.text)
# Используем CSS селектор для извлечения всех ссылок с классом 'external'
external_links = soup.select('a.external')
for link in external_links:
print("Ссылка с классом 'external':", link['href'])
# Используем CSS селектор для извлечения вложенного элемента <span> с классом 'highlight'
highlight = soup.select_one('div.nested span.highlight')
print("Текст вложенного элемента <span> с классом 'highlight':", highlight.text)
Объяснение кода
- Создаем объект
BeautifulSoupдля анализа HTML-кода:- Передаем HTML-контент и указываем парсер
'html.parser'.
- Передаем HTML-контент и указываем парсер
- Используем CSS селектор для извлечения заголовка
<h1>с классом'header':- Используем метод
select_oneс CSS селектором'h1.header'. - Извлекаем и выводим текст заголовка.
- Используем метод
- Используем CSS селектор для извлечения всех ссылок с классом
'external':- Используем метод
selectс CSS селектором'a.external'. - Итерируемся по найденным ссылкам и выводим значения их атрибутов
href.
- Используем метод
- Используем CSS селектор для извлечения вложенного элемента
<span>с классом'highlight':- Используем метод
select_oneс CSS селектором'div.nested span.highlight'. - Извлекаем и выводим текст вложенного элемента.
- Используем метод
id). В HTML каждый id должен быть уникальным в пределах документа, поэтому селекторы ID позволяют точно указывать на конкретные элементы. В BeautifulSoup для этого используются CSS селекторы.
Давайте рассмотрим, как использовать селекторы ID для поиска элементов в BeautifulSoup.
from bs4 import BeautifulSoup
# Пример HTML-документа
html_content = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Demo Page</title>
</head>
<body>
<div id="header">
<h1>Welcome to My Website</h1>
</div>
<div id="content">
<p id="intro">This is the introduction paragraph.</p>
<p id="main">This is the main content paragraph.</p>
<a id="contact-link" href="https://example.com/contact">Contact Us</a>
</div>
<div id="footer">
<p>Footer information</p>
</div>
</body>
</html>
"""
# Создаем объект BeautifulSoup для анализа HTML-кода
soup = BeautifulSoup(html_content, 'html.parser')
# Используем CSS селектор для извлечения элемента с id='header'
header_div = soup.select_one('#header')
print("Содержимое div с id='header':", header_div.text.strip())
# Используем CSS селектор для извлечения элемента с id='intro'
intro_paragraph = soup.select_one('#intro')
print("Текст параграфа с id='intro':", intro_paragraph.text.strip())
# Используем CSS селектор для извлечения ссылки с id='contact-link'
contact_link = soup.select_one('#contact-link')
print("Ссылка с id='contact-link':", contact_link['href'])
print("Текст ссылки с id='contact-link':", contact_link.text.strip())
Объяснение кода
- Импортируем библиотеку BeautifulSoup.
- Создаем объект
BeautifulSoupдля анализа HTML-кода:- Передаем HTML-контент и указываем парсер
'html.parser'.
- Передаем HTML-контент и указываем парсер
- Извлечение элементов с использованием селекторов ID:
header_div = soup.select_one('#header'):- Используем метод
select_oneс CSS селектором'#header'для поиска элемента<div>сid='header'. - Выводим текстовое содержимое этого элемента.
- Используем метод
intro_paragraph = soup.select_one('#intro'):- Используем метод
select_oneс CSS селектором'#intro'для поиска элемента<p>сid='intro'. - Выводим текстовое содержимое этого параграфа.
- Используем метод
contact_link = soup.select_one('#contact-link'):- Используем метод
select_oneс CSS селектором'#contact-link'для поиска элемента<a>сid='contact-link'. - Выводим значение атрибута
hrefи текст ссылки.
- Используем метод
Законно ли это: что важно знать
Сам по себе парсинг открытых страниц в России не запрещён. Проблемы начинаются с того, что и как вы собираете. Перед запуском парсера проверьте несколько вещей.- Правила сайта. Прочитайте пользовательское соглашение и файл
robots.txt(он лежит по адресусайт/robots.txt). Если владелец прямо запрещает автоматический сбор, лучше спросить разрешения или поискать официальный API. - Нагрузка. Делайте паузы между запросами (например,
time.sleep(1)) и не запускайте сотни потоков. Парсер, который положил чужой сайт, — уже повод для претензий. - Персональные данные. Имена, телефоны, почта людей защищены законом № 152-ФЗ «О персональных данных». Собирать их без согласия людей рискованно, даже если они открыто лежат на странице.
- Базы данных. Если сайт — по сути большая база (каталог, справочник), её создателя защищает статья 1334 Гражданского кодекса. Копировать её целиком или значительную часть без разрешения нельзя.
- Обход защиты. Подбор паролей, взлом капчи, доступ к закрытым разделам могут попасть под статью 272 Уголовного кодекса (неправомерный доступ к компьютерной информации).
Итоговые задания для закрепления
Задание 1: Парсинг новостных заголовков
Цель: Извлечь заголовки новостей и их ссылки с новостного сайта. Описание: Выберите новостной сайт (например, BBC News или CNN) и напишите скрипт, который парсит главную страницу. Ваш скрипт должен извлекать заголовки новостей и соответствующие ссылки. Шаги:- Откройте сайт и найдите HTML-структуру, содержащую заголовки новостей и ссылки.
- Напишите скрипт, который использует BeautifulSoup для извлечения заголовков и ссылок.
- Выведите заголовки и их ссылки в удобочитаемом формате.
Задание 2: Сбор данных о товарах из интернет-магазина
Цель: Собрать данные о товарах, включая названия, цены и ссылки на изображение, с сайта интернет-магазина. Описание: Выберите интернет-магазин (например, Amazon или eBay) и напишите скрипт, который извлекает названия товаров, их цены и ссылки на изображения. Шаги:- Изучите HTML-структуру страницы товара, чтобы найти нужные элементы.
- Напишите скрипт для извлечения названий, цен и ссылок на изображения.
- Выведите данные в формате, удобном для анализа (например, CSV).
Задание 3: Извлечение событий из календаря
Цель: Извлечь данные о предстоящих событиях с веб-страницы календаря, включая название события, дату и ссылку на подробности. Описание: Выберите сайт с календарем событий (например, Eventbrite или Meetup) и напишите скрипт, который извлекает информацию о предстоящих событиях. Шаги:- Изучите HTML-структуру страницы календаря, чтобы найти нужные элементы.
- Напишите скрипт для извлечения названий событий, дат и ссылок.
- Выведите данные в удобном формате.
