Создание новых парсеров 🕷️
В системе Gifty сбор данных автоматизирован с помощью Scrapy. Эта станица описывает, как правильно создавать, тестировать и масштабировать пауков.
🚀 Основные концепции
1. Как работает Паук (Yield и Генераторы)
В Scrapy методы парсинга — это генераторы. Вместо того чтобы собирать все товары в огромный список и возвращать его в конце (return list), мы используем ключевое слово yield.
Почему это важно?
- Экономия памяти: Scrapy обрабатывает объекты по одному, как только они "вылетают" из генератора. Это позволяет парсить миллионы товаров, не забивая RAM воркера.
- Потоковость: Pipeline (цепочка обработки) начинает валидировать и отправлять первый товар, пока паук еще парсит второй.
def parse_catalog(self, response):
for card in response.css('.card'):
# Мы "выбрасываем" товар в систему сразу
yield self.create_product(...)
2. Стратегии: Discovery vs Deep
Система различает две фазы жизни источника:
- Discovery (
strategy="discovery"): Используется для Хабов (главных страниц разделов). Паук ищет ссылки на конечные категории. Результат — объектыCategoryItem. - Deep (
strategy="deep"): Используется для Списков товаров (Листингов). Паук собирает товары и идет по пагинации. Результат — объектыProductItem.
🛠️ Реализация Паука
Используйте GiftyBaseSpider в качестве основы. Он берет на себя рутину: инициализацию URL, проброс source_id и выбор нужного метода парсинга в зависимости от стратегии.
Пример реализации
from gifty_scraper.base_spider import GiftyBaseSpider
from gifty_scraper.items import CategoryItem
class MyShopSpider(GiftyBaseSpider):
name = "myshop"
site_key = "myshop"
def parse_discovery(self, response):
"""Фаза 1: Собираем ссылки на подкатегории"""
for link in response.css('a.category-link'):
yield CategoryItem(
name=link.css('::text').get().strip(),
url=response.urljoin(link.attrib['href']),
site_key=self.site_key
)
def parse_catalog(self, response):
"""Фаза 2: Собираем товары из конкретной категории"""
for card in response.css('.product-card'):
yield self.create_product(
title=card.css('.name::text').get(),
price=card.css('.price::text').re_first(r'\d+'),
product_url=response.urljoin(card.css('a::attr(href)').get()),
image_url=response.urljoin(card.css('img::attr(src)').get()),
merchant="My Shop"
)
# Пагинация
if self.strategy == "deep":
next_page = response.css('a.next::attr(href)').get()
if next_page:
yield response.follow(next_page, self.parse_catalog)
🏗️ Обработка сложных случаев
Случай: Разная верстка для разных категорий
Иногда внутри одного сайта категории "Одежда" и "Электроника" имеют абсолютно разные селекторы.
Вариант А: Проверка через URL (в коде)
def parse_catalog(self, response):
if "/electronics/" in response.url:
return self.parse_electronics(response)
return self.parse_generic(response)
Вариант Б: Использование Config (через базу)
Если вы хотите менять логику без пересборки кода, используйте поле config в таблице parsing_sources. Все данные из него доступны пауку в self.config.
def parse_catalog(self, response):
title_css = self.config.get('custom_title_css', '.default-title')
yield self.create_product(
title=response.css(title_css).get(),
# ...
)
🛠️ Тестирование и отладка
Для проверки логики без запуска всей инфраструктуры (Docker/API) используйте специальный скрипт:
--limit: Ограничит сбор (например, первые 10 товаров).--output: Имя файла с результатами (по умолчаниюtest_results.json).--strategy: discovery или deep (по умолчанию deep).
⛓️ Регистрация в системе
В новой архитектуре Gifty регистрация пауков происходит автоматически. Вам не нужно вручную править базу данных или словари в коде.
1. Создание паука
Просто создайте новый файл паука в директории services/gifty_scraper/spiders/. Убедитесь, что у паука задано уникальное имя (name и site_key).
2. Автоматическое обнаружение
Как только вы добавите файл и перезапустите сервис scraper, воркер при старте выполнит команду scrapy list и отправит список всех доступных пауков в Core API.
3. Настройка через Dashboard
После обнаружения новый паук появится в Dashboard (в Telegram боте) со статусом disabled.
Чтобы запустить его:
- Откройте Dashboard через бота.
- Найдите вашего нового паука в списке.
- Нажмите кнопку редактирования и укажите:
- URL: Входная точка (например, ссылка на Sitemap или Hub-страницу).
- Type: Тип источника (
hub,list,sitemap). - Strategy: Стратегия (
discoveryилиdeep). - Interval: Желаемый интервал обновления.
- Переведите переключатель в положение Active.
Система сама добавит задачу в очередь при наступлении времени следующей синхронизации.
🚦 Мониторинг и управление (Dashboard)
Для оперативного управления системой парсинга используется Gifty Scraping Dashboard, интегрированный прямо в Telegram Бота (Mini App).
Основные возможности дашборда:
- Spider List: Список всех зарегистрированных источников, их текущий статус (
waiting,running,error,broken) и время последнего запуска. - Health Check: Визуализация активных воркеров и их "пульса" (heartbeat) из Redis.
- Config Editor: Возможность редактирования настроек паука (URL, интервал, глубина парсинга) без изменения кода.
- Stats: Агрегированная статистика по количеству спаршенных и новых товаров за последние 24 часа.
Как открыть дашборд:
В главном меню Telegram бота нажмите кнопку "🕷 Парсинг".
Tip
Если дашборд не открывается (белый экран), проверьте, запущен ли сервис dashboard и доступен ли он по HTTPS (требование Telegram).
💡 Рекомендации
- Throttling: По умолчанию стоит задержка 1с между запросами. Если сайт блокирует — увеличьте
DOWNLOAD_DELAYвsettings.py. - CSS vs XPath: Используйте CSS селекторы везде, где это возможно — они проще читаются.
- Images: Всегда проверяйте, что
image_url— это полная ссылка (используйтеresponse.urljoin). - Batching: Наш Pipeline автоматически группирует товары в пачки перед отправкой в API для экономии ресурсов.