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

227 lines
7.5 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 🤖 Что делает краулер - пошаговый процесс
## 📋 КРАТКИЙ ОТВЕТ
Краулер делает **ТОЛЬКО парсинг и сохранение в БД**. Никаких эмбеддингов, векторизации или анализа!
---
## 🔄 ПОЛНЫЙ ПРОЦЕСС (шаг за шагом)
### 1⃣ **Получение списка отелей** (`get_unprocessed_hotels`)
```sql
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. Загрузка главной страницы
```python
await page.goto(website, wait_until='domcontentloaded', timeout=20000)
```
- Таймаут: 20 секунд
- Ждёт загрузки DOM
#### 2.3. Извлечение контента главной
```python
html = await page.content() # Сырой HTML
cleaned_text = TextCleaner.clean_html(html) # Очищенный текст
```
**`TextCleaner.clean_html()` делает:**
- Удаляет `<script>`, `<style>`, `<meta>`, `<link>`, `<noscript>`
- Извлекает текст через BeautifulSoup
- Убирает лишние пробелы/переносы
- Возвращает чистый текст
#### 2.4. Сбор внутренних ссылок
```python
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. Обход внутренних страниц
```python
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`
```sql
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`
```sql
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`
```sql
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` - Время обработки
---
## ⚡ ПРОИЗВОДИТЕЛЬНОСТЬ
### Настройки:
```python
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