Files
hotels/CRAWLER_WORKFLOW.md
Фёдор 0cf3297290 Проект аудита отелей: основные скрипты и документация
- Краулеры: smart_crawler.py, regional_crawler.py
- Аудит: audit_orel_to_excel.py, audit_chukotka_to_excel.py
- РКН проверка: check_rkn_registry.py, recheck_unclear_rkn.py
- Отчёты: create_orel_horizontal_report.py
- Обработка: process_all_hotels_embeddings.py
- Документация: README.md, DB_SCHEMA_REFERENCE.md
2025-10-16 10:52:09 +03:00

7.5 KiB
Raw Blame History

🤖 Что делает краулер - пошаговый процесс

📋 КРАТКИЙ ОТВЕТ

Краулер делает ТОЛЬКО парсинг и сохранение в БД. Никаких эмбеддингов, векторизации или анализа!


🔄 ПОЛНЫЙ ПРОЦЕСС (шаг за шагом)

1 Получение списка отелей (get_unprocessed_hotels)

SELECT id, full_name, region_name, website_address
FROM hotel_main
WHERE website_address IS NOT NULL
  AND id NOT IN (SELECT hotel_id FROM hotel_website_processed)
ORDER BY id
LIMIT 50  -- пачками по 50

Что делает:

  • Берёт отели с сайтами
  • Исключает уже обработанные
  • Обрабатывает пачками по 50 штук

2 Краулинг сайта (crawl_hotel)

2.1. Запуск браузера Playwright

  • Открывает headless браузер
  • User-Agent: Mozilla/5.0 (Windows...)
  • Параллельно: 5 браузеров (MAX_CONCURRENT = 5)

2.2. Загрузка главной страницы

await page.goto(website, wait_until='domcontentloaded', timeout=20000)
  • Таймаут: 20 секунд
  • Ждёт загрузки DOM

2.3. Извлечение контента главной

html = await page.content()          # Сырой HTML
cleaned_text = TextCleaner.clean_html(html)  # Очищенный текст

TextCleaner.clean_html() делает:

  • Удаляет <script>, <style>, <meta>, <link>, <noscript>
  • Извлекает текст через BeautifulSoup
  • Убирает лишние пробелы/переносы
  • Возвращает чистый текст

2.4. Сбор внутренних ссылок

links = await page.evaluate('''() => {
    return Array.from(document.querySelectorAll('a[href]'))
        .map(a => a.href)
        .filter(href => href && !href.startsWith('mailto:') && !href.startsWith('tel:'))
}''')

Фильтрация:

  • Только внутренние ссылки (тот же домен)
  • Исключает mailto:, tel:
  • Убирает дубли
  • Лимит: 19 ссылок (+ главная = 20 страниц)

2.5. Обход внутренних страниц

for link in internal_links[:19]:  # Максимум 19 + главная = 20
    page2 = await context.new_page()
    await page2.goto(link, timeout=20000)
    html2 = await page2.content()
    text2 = TextCleaner.clean_html(html2)
    # Сохраняем в pages_data

Для каждой страницы:

  • Открывает новую вкладку
  • Загружает страницу (20 сек таймаут)
  • Извлекает HTML
  • Очищает текст
  • Добавляет в pages_data[]

3 Сохранение в БД (save_to_db)

3.1. Метаданные → hotel_website_meta

INSERT INTO hotel_website_meta 
(hotel_id, domain, main_url, pages_crawled, crawl_status, crawl_finished_at)
VALUES (...)
ON CONFLICT (hotel_id) DO UPDATE ...

Сохраняет:

  • hotel_id - UUID отеля
  • domain - Домен сайта
  • main_url - Главный URL
  • pages_crawled - Количество страниц
  • crawl_status - 'completed'
  • crawl_finished_at - Время завершения

3.2. Сырой HTML → hotel_website_raw

INSERT INTO hotel_website_raw 
(hotel_id, url, html, status_code, crawled_at)
VALUES (...)
ON CONFLICT (hotel_id, url) DO UPDATE ...

Для КАЖДОЙ страницы сохраняет:

  • hotel_id - UUID отеля
  • url - URL страницы
  • html - Полный сырой HTML
  • status_code - HTTP код (200, 404, etc)
  • crawled_at - Время краулинга

3.3. Очищенный текст → hotel_website_processed

INSERT INTO hotel_website_processed 
(hotel_id, url, cleaned_text, processed_at)
VALUES (...)
ON CONFLICT (hotel_id, url) DO UPDATE ...

Для КАЖДОЙ страницы сохраняет:

  • hotel_id - UUID отеля
  • url - URL страницы
  • cleaned_text - Очищенный текст (без HTML тегов)
  • processed_at - Время обработки

ПРОИЗВОДИТЕЛЬНОСТЬ

Настройки:

MAX_PAGES_PER_SITE = 20    # Максимум страниц с одного сайта
PAGE_TIMEOUT = 20000       # 20 секунд на загрузку страницы
MAX_CONCURRENT = 5         # 5 браузеров параллельно
BATCH_SIZE = 50            # Обрабатывать по 50 отелей

Время на 1 отель:

  • Быстрый сайт (1-5 страниц): ~10-30 секунд
  • Средний сайт (10-15 страниц): ~1-3 минуты
  • Большой сайт (20 страниц): ~3-5 минут
  • Недоступный сайт: ~20 секунд (таймаут)

Скорость обработки:

  • Текущая: ~50-100 отелей/день
  • Теоретическая: ~400-500 отелей/день (если все сайты быстрые)

ЧТО КРАУЛЕР НЕ ДЕЛАЕТ

  1. НЕ создаёт эмбеддинги (векторы для поиска)
  2. НЕ делает чанки (разбивку на части)
  3. НЕ анализирует контент (нет AI/NLP)
  4. НЕ извлекает структурированные данные (телефоны, email, etc)
  5. НЕ проверяет критерии аудита
  6. НЕ делает скриншоты
  7. НЕ проверяет SSL/сертификаты

📊 ЧТО В ИТОГЕ В БД

После краулинга 1 отеля с 15 страницами:

hotel_website_meta: 1 запись

  • Метаданные: домен, количество страниц, статус

hotel_website_raw: 15 записей

  • 15 × полный HTML (может быть 100-500 KB каждый)
  • Всего: ~1-7 MB сырых данных

hotel_website_processed: 15 записей

  • 15 × очищенный текст (обычно 1-10 KB каждый)
  • Всего: ~15-150 KB текста

🚀 СЛЕДУЮЩИЕ ЭТАПЫ (отдельно от краулера)

После того как краулер заполнит БД, ОТДЕЛЬНО нужно будет:

  1. Создать эмбеддинги (process_all_hotels_embeddings.py)

    • Разбить текст на чанки
    • Создать векторы через BGE-M3
    • Сохранить в hotel_website_chunks
  2. Запустить аудит (hybrid_audit_chukotka.py)

    • Семантический поиск
    • Регулярные выражения
    • Natasha NER
    • Сохранить в hotel_audit_results
  3. Интеграция с n8n

    • AI Agent для анализа
    • Автоматизация проверок

💡 ВЫВОД

Краулер = простой парсер:

  • Открывает сайты
  • Скачивает HTML
  • Чистит текст
  • Кладёт в БД

Всё остальное (AI, векторы, аудит) - это отдельные процессы!


Дата: 2025-10-14
Автор: Фёдор + AI Assistant