auction-scrapper/README.md
Vakula Uladimir 12f005e335 init
2025-10-17 11:27:52 +03:00

549 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

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.

# Parser Zakupok (Парсер Закупок)
AdonisJS 6 приложение для автоматического парсинга аукционов с сайта icetrade.by. Система автоматически собирает данные каждые 6 часов, сохраняет в PostgreSQL и отправляет Telegram уведомления по ключевым словам.
## Возможности
- 🔄 Автоматический парсинг аукционов каждые 6 часов
- 🔍 Поиск по ключевым словам (заголовок, описание, организация)
- 📱 Telegram уведомления пользователям
- 📊 Логирование всех операций парсинга
- 🗄️ PostgreSQL база данных с полной историей
- ⚡ Пагинация и rate limiting для стабильности
- 🔧 REST API для управления
## Технологический стек
- **Framework**: AdonisJS 6 (TypeScript)
- **Database**: PostgreSQL + Lucid ORM
- **Scheduler**: adonisjs-scheduler
- **HTML Parser**: Cheerio
- **Validation**: Zod
- **Telegram Bot**: Grammy
- **Testing**: Japa
## Установка
### Требования
- Node.js >= 20.6
- PostgreSQL >= 14
- npm >= 9
### Шаги установки
```bash
# 1. Клонировать репозиторий
git clone <repository-url>
cd parser-zakupok
# 2. Установить зависимости
npm install
# 3. Скопировать .env файл
cp .env.example .env
# 4. Настроить переменные окружения
nano .env # или любой редактор
# 5. Запустить миграции
node ace migration:run
# 6. Запустить приложение
npm run dev
```
### Настройка .env
```env
# Сервер
PORT=3333
HOST=localhost
NODE_ENV=development
APP_KEY=<generate-with-node-ace-generate:key>
# База данных PostgreSQL
DB_HOST=127.0.0.1
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=your_password
DB_DATABASE=parser_zakupok
# Telegram Bot
TELEGRAM_BOT_TOKEN=your_bot_token_from_@BotFather
# Опционально
LOG_LEVEL=info
```
## Команды запуска
### Режим разработки
```bash
# Запуск с hot reload (рекомендуется)
npm run dev
# Альтернативный вариант
node ace serve --hmr
# С watch режимом
node ace serve --watch
```
### Production режим
```bash
# 1. Собрать проект
npm run build
# 2. Запустить миграции
node ace migration:run --force
# 3. Запустить сервер
npm start
# или
node build/bin/server.js
```
## Команды базы данных
### Миграции
```bash
# Выполнить все pending миграции
node ace migration:run
# Откатить последний batch
node ace migration:rollback
# Откатить все миграции
node ace migration:rollback --batch=0
# Пересоздать базу (drop + migrate)
node ace migration:fresh
# Fresh + seed данные
node ace migration:fresh --seed
```
### Создание новых сущностей
```bash
# Создать миграцию
node ace make:migration create_table_name
node ace make:migration add_column_to_table
# Создать модель
node ace make:model ModelName
# Создать модель + миграцию
node ace make:model ModelName -m
# Создать контроллер
node ace make:controller ControllerName
```
### Database утилиты
```bash
# Открыть REPL с доступом к моделям
node ace repl
# Примеры в REPL:
# > await loadModels()
# > const Auction = await import('#models/auction')
# > await Auction.default.all()
```
## Команды парсинга
### Основная команда parse:auctions
```bash
# Парсинг с дефолтными настройками (до 10 страниц)
node ace parse:auctions
# Парсинг конкретного количества страниц
node ace parse:auctions --pages=5
# Парсинг без отправки уведомлений (только сохранение)
node ace parse:auctions --skip-notifications
# Парсинг 1 страницы без уведомлений (для тестирования)
node ace parse:auctions --pages=1 --skip-notifications
# Комбинация опций
node ace parse:auctions --pages=20 --skip-notifications
```
**Что делает команда:**
1. Создает запись в `parse_logs` (статус: running)
2. Парсит страницы с icetrade.by с rate limiting (1 сек между запросами)
3. Валидирует данные через Zod схемы
4. Upsert аукционов по `auction_num` (обновляет существующие, создает новые)
5. Ищет совпадения по ключевым словам
6. Создает записи уведомлений для пользователей
7. Обновляет parse_log (статус: completed/failed, статистика)
**Выводит:**
- Количество найденных аукционов
- Количество новых аукционов
- Количество обновленных аукционов
- Количество созданных уведомлений
- Время выполнения
- Ошибки (если есть)
## Команды Scheduler
### Управление планировщиком
```bash
# Запустить scheduler (production)
node ace scheduler:work
# Запустить с watch режимом (development)
node ace scheduler:work --watch
# Показать список всех запланированных задач
node ace scheduler:list
# Вывод scheduler:list:
# ┌────────────────┬──────────────────┬─────────────────┐
# │ Name │ Cron Expression │ Next Run │
# ├────────────────┼──────────────────┼─────────────────┤
# │ parse:auctions │ 0 0 */6 * * * │ 2024-01-15 18:00│
# └────────────────┴──────────────────┴─────────────────┘
```
### Настройка расписания
Расписание настроено в `start/scheduler.ts`:
```typescript
// Текущее: каждые 6 часов (00:00, 06:00, 12:00, 18:00)
scheduler.call(async () => {
await ace.exec('parse:auctions', [])
}).cron('0 0 */6 * * *')
// Другие варианты расписания:
// .cron('0 0 * * * *') // Каждый час
// .cron('0 */30 * * * *') // Каждые 30 минут
// .everyFourHours() // Каждые 4 часа
// .dailyAt('09:00') // Ежедневно в 9:00
// .twiceDaily(9, 18) // Дважды в день (9:00, 18:00)
```
### Production deployment scheduler
```bash
# Вариант 1: Использовать встроенный scheduler
npm start & # Запустить сервер
node ace scheduler:work # Запустить scheduler в отдельном процессе
# Вариант 2: Использовать PM2 (рекомендуется)
pm2 start ecosystem.config.js
# Вариант 3: Systemd services
# Создать два сервиса: parser-app.service и parser-scheduler.service
```
## Команды тестирования
```bash
# Запустить все тесты
npm test
# или
node ace test
# Запустить конкретный файл теста
node ace test --files=tests/unit/models/auction.spec.ts
# Запустить тесты по паттерну (grep)
node ace test --grep="keyword matching"
node ace test --grep="scraper"
# Запустить только unit тесты
node ace test tests/unit
# Запустить только functional тесты
node ace test tests/functional
```
## Code Quality команды
```bash
# Проверка типов TypeScript
npm run typecheck
# Линтинг (ESLint)
npm run lint
# Автофикс линтинга
npm run lint -- --fix
# Форматирование (Prettier)
npm run format
# Проверить форматирование без изменений
npm run format -- --check
```
## Telegram Bot команды
```bash
# Запустить Telegram бота (когда будет реализовано в Phase 5)
node ace telegram:start
# С watch режимом
node ace telegram:start --watch
```
### Команды бота для пользователей
После запуска бота, пользователи могут использовать:
- `/start` - Регистрация в системе
- `/addkeyword <слово>` - Добавить ключевое слово
- `/keywords` или `/listkeywords` - Список ваших ключевых слов
- `/deletekeyword <id>` - Удалить ключевое слово
- `/help` - Справка по командам
## Структура проекта
```
parser-zakupok/
├── app/
│ ├── controllers/ # HTTP контроллеры
│ ├── models/ # Lucid ORM модели
│ │ ├── auction.ts
│ │ ├── keyword.ts
│ │ ├── user.ts
│ │ ├── notification.ts
│ │ └── parse_log.ts
│ ├── services/ # Бизнес-логика
│ │ ├── scraper_service.ts # Парсинг icetrade.by
│ │ └── notification_service.ts # Обработка уведомлений
│ ├── middleware/ # HTTP middleware
│ └── validators/ # VineJS валидаторы
├── commands/ # Ace CLI команды
│ └── parse_auctions.ts # Команда парсинга
├── config/ # Конфигурация приложения
│ ├── app.ts
│ ├── database.ts
│ └── logger.ts
├── database/
│ └── migrations/ # Database миграции
├── start/
│ ├── routes.ts # Маршруты
│ ├── kernel.ts # Middleware регистрация
│ ├── scheduler.ts # Настройка scheduler
│ └── env.ts # Env validation
├── tests/ # Тесты (Japa)
│ ├── unit/
│ └── functional/
├── docs/ # Документация
├── .env # Environment переменные
├── adonisrc.ts # AdonisJS конфигурация
└── package.json
```
## Import Aliases
В проекте настроены удобные алиасы для импортов:
```typescript
#controllers/* ./app/controllers/*.js
#models/* ./app/models/*.js
#services/* ./app/services/*.js
#validators/* ./app/validators/*.js
#middleware/* ./app/middleware/*.js
#config/* ./config/*.js
#database/* ./database/*.js
#start/* ./start/*.js
// Пример использования:
import Auction from '#models/auction'
import ScraperService from '#services/scraper_service'
import { DatabaseConfig } from '#config/database'
```
## Логирование
Все операции логируются через Pino logger:
```typescript
import logger from '@adonisjs/core/services/logger'
// В коде:
logger.info('Scraping started')
logger.error({ err }, 'Failed to parse page')
logger.debug({ count: auctions.length }, 'Auctions scraped')
```
Логи сохраняются в:
- `tmp/logs/app.log` (production)
- Console output (development)
## Parse Logs в БД
Каждый запуск парсинга создает запись в таблице `parse_logs`:
```sql
SELECT * FROM parse_logs ORDER BY started_at DESC LIMIT 5;
-- Поля:
-- id, parse_type, status, started_at, completed_at,
-- items_found, items_new, items_updated, items_failed,
-- error_message, error_details
```
Полезные запросы:
```sql
-- Последние успешные парсинги
SELECT * FROM parse_logs
WHERE status = 'completed'
ORDER BY started_at DESC;
-- Статистика по парсингам
SELECT
COUNT(*) as total_runs,
AVG(items_found) as avg_found,
AVG(items_new) as avg_new,
SUM(items_failed) as total_failed
FROM parse_logs
WHERE parse_type = 'auction';
-- Неудачные парсинги с ошибками
SELECT started_at, error_message
FROM parse_logs
WHERE status = 'failed'
ORDER BY started_at DESC;
```
## Troubleshooting
### База данных не подключается
```bash
# Проверить что PostgreSQL запущен
# Linux/Mac:
sudo systemctl status postgresql
# Windows:
# Проверить через Services (services.msc)
# Проверить подключение
psql -U postgres -h localhost
# Создать базу вручную
psql -U postgres
CREATE DATABASE parser_zakupok;
\q
```
### Ошибки при парсинге
```bash
# Проверить логи
tail -f tmp/logs/app.log
# Проверить parse_logs в БД
node ace repl
> await loadModels()
> const ParseLog = await import('#models/parse_log')
> await ParseLog.default.query().orderBy('started_at', 'desc').first()
# Запустить парсинг одной страницы для отладки
node ace parse:auctions --pages=1 --skip-notifications
```
### Scheduler не запускается
```bash
# Проверить что scheduler провайдер добавлен в adonisrc.ts
cat adonisrc.ts | grep scheduler
# Проверить список задач
node ace scheduler:list
# Запустить вручную для проверки
node ace parse:auctions
```
### TypeScript ошибки
```bash
# Очистить build и пересобрать
rm -rf build/
npm run build
# Проверить типы
npm run typecheck
# Обновить зависимости
npm update
```
## API Endpoints (будут реализованы в Phase 7)
```
GET /api/auctions # Список аукционов (пагинация, фильтры)
GET /api/auctions/:id # Детали аукциона
GET /api/keywords # Ключевые слова пользователя
POST /api/keywords # Добавить ключевое слово
DELETE /api/keywords/:id # Удалить ключевое слово
GET /api/notifications # История уведомлений
```
## Docker (будет реализовано в Phase 8)
```bash
# Сборка и запуск
docker-compose up -d
# Просмотр логов
docker-compose logs -f app
# Остановка
docker-compose down
```
## Roadmap
- [x] Phase 1: Project Setup
- [x] Phase 2: Database Models & Migrations
- [x] Phase 3: ScraperService Implementation
- [x] Phase 4: Scheduler Command
- [ ] Phase 5: Telegram Bot Integration
- [ ] Phase 6: NotificationService Enhancement
- [ ] Phase 7: REST API Endpoints
- [ ] Phase 8: Docker Deployment
## Contributing
1. Fork репозиторий
2. Создать feature branch (`git checkout -b feature/AmazingFeature`)
3. Commit изменения (`git commit -m 'Add some AmazingFeature'`)
4. Push в branch (`git push origin feature/AmazingFeature`)
5. Открыть Pull Request
## License
[MIT License](LICENSE)
## Поддержка
При возникновении проблем:
1. Проверьте [документацию](docs/)
2. Создайте [Issue](../../issues)
3. Проверьте существующие Issues
## Полезные ссылки
- [AdonisJS Documentation](https://docs.adonisjs.com/)
- [Lucid ORM](https://lucid.adonisjs.com/)
- [Grammy Telegram Bot](https://grammy.dev/)
- [PostgreSQL Documentation](https://www.postgresql.org/docs/)