Практическое занятие 6: Первый веб-скрапер
Цель занятия
Заголовок раздела «Цель занятия»Создать первый веб-скрапер для сбора данных с веб-страниц и сохранения их в формате JSON.
Виртуальное окружение
Заголовок раздела «Виртуальное окружение»Создание виртуального окружения
Заголовок раздела «Создание виртуального окружения»Виртуальное окружение позволяет изолировать зависимости проекта от системных зависимостей Python.
# Создание виртуального окруженияpython -m venv venv
# илиpython3 -m venv venvАктивация виртуального окружения
Заголовок раздела «Активация виртуального окружения»Windows:
venv\Scripts\activatemacOS/Linux:
source venv/bin/activateПосле активации в начале командной строки появится (venv).
Деактивация
Заголовок раздела «Деактивация»deactivateУстановка библиотек
Заголовок раздела «Установка библиотек»Библиотека requests
Заголовок раздела «Библиотека requests»Библиотека requests используется для выполнения HTTP-запросов.
pip install requestsБиблиотека BeautifulSoup
Заголовок раздела «Библиотека BeautifulSoup»Библиотека BeautifulSoup (из пакета beautifulsoup4) используется для парсинга HTML.
pip install beautifulsoup4Сохранение зависимостей
Заголовок раздела «Сохранение зависимостей»Сохраните список установленных библиотек в файл requirements.txt:
pip freeze > requirements.txtУстановка зависимостей из файла:
pip install -r requirements.txtПервый скрапер
Заголовок раздела «Первый скрапер»Базовый пример
Заголовок раздела «Базовый пример»Создайте файл scraper.py:
import requestsfrom bs4 import BeautifulSoup
# URL для скрапингаurl = "https://example.com"
# Выполнение GET-запросаresponse = requests.get(url)
# Проверка успешности запросаif response.status_code == 200: print("Успешно подключились к странице") print(f"Код ответа: {response.status_code}")else: print("Ошибка при подключении") print(f"Код ответа: {response.status_code}")Получение и парсинг HTML
Заголовок раздела «Получение и парсинг HTML»import requestsfrom bs4 import BeautifulSoup
url = "https://example.com"response = requests.get(url)
# Парсинг HTMLsoup = BeautifulSoup(response.text, "html.parser")
# Вывод заголовка страницыtitle = soup.titleprint(f"Заголовок страницы: {title.text}")
# Вывод всех ссылокlinks = soup.find_all("a")print(f"\nНайдено ссылок: {len(links)}")
for link in links[:5]: # Первые 5 ссылок href = link.get("href") text = link.text.strip() print(f"{text}: {href}")Извлечение данных
Заголовок раздела «Извлечение данных»import requestsfrom bs4 import BeautifulSoup
url = "https://example.com"response = requests.get(url)
soup = BeautifulSoup(response.text, "html.parser")
# Поиск элемента по тегуh1 = soup.find("h1")if h1: print(f"H1: {h1.text}")
# Поиск по idelement = soup.find(id="content")if element: print("Элемент с id='content' найден")
# Поиск по классуelements = soup.find_all(class_="example")for elem in elements: print(f"Элемент с классом 'example': {elem.text}")
# Комбинированный поискdivs = soup.find_all("div", class_="container")for div in divs[:3]: print(f"Div с классом 'container': {div.text.strip()}")Работа с атрибутами
Заголовок раздела «Работа с атрибутами»import requestsfrom bs4 import BeautifulSoup
url = "https://example.com"response = requests.get(url)
soup = BeautifulSoup(response.text, "html.parser")
# Получение всех ссылокlinks = soup.find_all("a")
data = []
for link in links: href = link.get("href") text = link.text.strip() title = link.get("title", "")
data.append({ "текст": text, "ссылка": href, "заголовок": title })
print(f"Собрано {len(data)} ссылок")Сохранение данных в JSON
Заголовок раздела «Сохранение данных в JSON»Базовое сохранение
Заголовок раздела «Базовое сохранение»import json
data = { "имя": "Анна", "возраст": 25, "город": "Москва"}
# Сохранение в JSON файлwith open("data.json", "w", encoding="utf-8") as file: json.dump(data, file, ensure_ascii=False, indent=4)
print("Данные сохранены в data.json")Чтение из JSON
Заголовок раздела «Чтение из JSON»import json
# Чтение из JSON файлаwith open("data.json", "r", encoding="utf-8") as file: data = json.load(file)
print(data)Полный пример скрапера с сохранением
Заголовок раздела «Полный пример скрапера с сохранением»Создайте файл advanced_scraper.py:
import requestsfrom bs4 import BeautifulSoupimport json
def scrape_website(url): """Собирает данные с веб-сайта""" response = requests.get(url)
if response.status_code != 200: print(f"Ошибка: код ответа {response.status_code}") return None
soup = BeautifulSoup(response.text, "html.parser")
# Сбор заголовка title = soup.title.text.strip() if soup.title else "Без заголовка"
# Сбор ссылок links = [] for link in soup.find_all("a"): href = link.get("href") text = link.text.strip() if href and text: links.append({ "текст": text, "ссылка": href })
# Сбор изображений images = [] for img in soup.find_all("img"): src = img.get("src") alt = img.get("alt", "") if src: images.append({ "источник": src, "описание": alt })
return { "url": url, "заголовок": title, "ссылок": len(links), "ссылки": links[:10], # Первые 10 ссылок "изображений": len(images), "изображения": images[:5] # Первые 5 изображений }
def save_to_json(data, filename): """Сохраняет данные в JSON файл""" with open(filename, "w", encoding="utf-8") as file: json.dump(data, file, ensure_ascii=False, indent=4) print(f"Данные сохранены в {filename}")
# Основной кодif __name__ == "__main__": url = "https://example.com" print(f"Скрапинг: {url}")
data = scrape_website(url)
if data: print(f"Заголовок: {data['заголовок']}") print(f"Найдено ссылок: {data['ссылок']}") print(f"Найдено изображений: {data['изображений']}")
save_to_json(data, "scraped_data.json")Обработка ошибок
Заголовок раздела «Обработка ошибок»import requestsfrom requests.exceptions import RequestException
url = "https://example.com"
try: response = requests.get(url, timeout=10) response.raise_for_status() # Проверка на ошибки HTTP
print("Успешный запрос") print(f"Размер страницы: {len(response.text)} байт")
except RequestException as e: print(f"Ошибка запроса: {e}")except Exception as e: print(f"Неожиданная ошибка: {e}")Добавление заголовков
Заголовок раздела «Добавление заголовков»import requests
url = "https://example.com"
# Заголовки для имитации браузераheaders = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7"}
response = requests.get(url, headers=headers)
print(f"Статус: {response.status_code}")Задания для самостоятельной работы
Заголовок раздела «Задания для самостоятельной работы»-
Создайте скрапер, который собирает заголовки (
h1,h2,h3) с выбранной вами веб-страницы. -
Напишите скрапер, который собирает все таблицы с веб-страницы и сохраняет их данные в JSON.
-
Создайте функцию для сохранения результатов скрапинга с автоматическим именованием файла (например,
data_2024-03-07.json). -
Реализуйте обработку ошибок для всех возможных ситуаций (ошибка сети, ошибка парсинга, ошибка записи файла).
-
Добавьте логирование для отслеживания процесса скрапинга.
Пример решения задания 1
Заголовок раздела «Пример решения задания 1»import requestsfrom bs4 import BeautifulSoupimport json
def scrape_headers(url): response = requests.get(url) soup = BeautifulSoup(response.text, "html.parser")
headers = []
for level in ["h1", "h2", "h3"]: for header in soup.find_all(level): headers.append({ "уровень": level, "текст": header.text.strip() })
return headers
url = "https://example.com"headers = scrape_headers(url)
for header in headers: print(f"{header['уровень']}: {header['текст']}")
# Сохранениеwith open("headers.json", "w", encoding="utf-8") as file: json.dump(headers, file, ensure_ascii=False, indent=4)Полезные ресурсы
Заголовок раздела «Полезные ресурсы»Следующий шаг
Заголовок раздела «Следующий шаг»На следующем занятии мы изучим работу с базами данных SQLite и сохранение данных в таблицы.