Актуализирован README и очищены служебные артефакты
- Полностью обновлена документация проекта под текущую архитектуру - Добавлены исчерпывающие инструкции локального запуска: Docker и без Docker - Уточнены реальные API эндпоинты, задачи Celery, переменные окружения и prod/dev сценарии - Удалены вспомогательные временные файлы: concatenate_files.py и один_файл.docx
This commit is contained in:
528
README.md
528
README.md
@@ -1,349 +1,277 @@
|
|||||||
# Django ETL Boilerplate
|
# Mostovik Backend
|
||||||
|
|
||||||
Шаблон Django приложения для ETL (Extract, Transform, Load) операций с функциями веб-скрапинга.
|
Backend-сервис на Django/DRF для сбора, хранения и выдачи данных из государственных источников (Минпромторг, ЕРП, ЕИС закупок, ФНС), с асинхронной обработкой через Celery.
|
||||||
|
|
||||||
## Технологический стек
|
## Что умеет проект
|
||||||
|
|
||||||
- **Python**: 3.11.2
|
- JWT-аутентификация и профиль пользователя.
|
||||||
- **Django**: 3.2.25
|
- Swagger UI документация API.
|
||||||
- **Django REST Framework**: 3.14.0
|
- Health/Liveness/Readiness эндпоинты.
|
||||||
- **PostgreSQL**: 15.10
|
- Фоновые задачи с трекингом статуса (`BackgroundJob`).
|
||||||
- **Redis**: 7.x
|
- Парсеры источников:
|
||||||
- **Celery**: 5.3.6
|
- Минпромторг: сертификаты и реестр производителей.
|
||||||
- **Playwright**: 1.52+ (browser automation)
|
- Единый реестр проверок (`proverki.gov.ru`, включая 248-ФЗ/294-ФЗ).
|
||||||
- **Gunicorn**: 21.2.0
|
- Закупки (`zakupki.gov.ru`, SOAP API с токеном).
|
||||||
- **Apache**: 2.4.57
|
- ФНС: загрузка и обработка Excel-отчётности (`fin_{id}_{ogrn}.xlsx`).
|
||||||
|
- Админ-панель на Jazzmin для мониторинга данных и логов загрузок.
|
||||||
|
|
||||||
## Парсеры данных
|
## Технологии
|
||||||
|
|
||||||
Проект включает парсеры для загрузки данных из государственных источников:
|
- Python 3.11
|
||||||
|
- Django 3.2
|
||||||
### Минпромторг (minpromtorg.gov.ru)
|
- Django REST Framework
|
||||||
- **Сертификаты промышленного производства** - `parse_industrial_production`
|
- PostgreSQL 15
|
||||||
- **Реестр производителей** - `parse_manufactures`
|
- Redis 7
|
||||||
|
- Celery + django-celery-beat + django-celery-results
|
||||||
### Единый реестр проверок (proverki.gov.ru)
|
- drf-yasg (Swagger/OpenAPI)
|
||||||
- **Проверки по ФЗ-294** - традиционные проверки
|
- uv (управление зависимостями)
|
||||||
- **Проверки по ФЗ-248** - новые проверки с 2021 года
|
- Docker / Docker Compose
|
||||||
- **Автоматическая синхронизация** - `sync_inspections`
|
|
||||||
|
|
||||||
### Запуск парсеров
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Через Celery
|
|
||||||
from apps.parsers.tasks import (
|
|
||||||
parse_industrial_production,
|
|
||||||
parse_manufactures,
|
|
||||||
parse_inspections,
|
|
||||||
sync_inspections,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Парсинг сертификатов
|
|
||||||
parse_industrial_production.delay()
|
|
||||||
|
|
||||||
# Парсинг производителей
|
|
||||||
parse_manufactures.delay()
|
|
||||||
|
|
||||||
# Парсинг проверок за конкретный месяц
|
|
||||||
parse_inspections.delay(year=2025, month=10, is_federal_law_248=False)
|
|
||||||
|
|
||||||
# Автоматическая синхронизация (с 01.01.2025 до текущего месяца)
|
|
||||||
sync_inspections.delay()
|
|
||||||
```
|
|
||||||
|
|
||||||
### Особенности парсера proverki.gov.ru
|
|
||||||
- Использует **Playwright** для JS-рендеринга
|
|
||||||
- Поддержка **потокового парсинга** для больших файлов (>50 МБ)
|
|
||||||
- Автоматическое определение последнего загруженного периода
|
|
||||||
- Раздельная загрузка ФЗ-294 и ФЗ-248
|
|
||||||
|
|
||||||
## Структура проекта
|
## Структура проекта
|
||||||
|
|
||||||
```
|
```text
|
||||||
mostovik-backend/
|
.
|
||||||
├── src/ # Исходный код Django
|
├── src/
|
||||||
│ ├── apps/ # Django приложения
|
│ ├── apps/
|
||||||
│ │ └── user/ # Приложение пользователей
|
│ │ ├── core/ # health, background jobs, openapi, startup checks
|
||||||
│ ├── core/ # Runtime-конфигурация проекта (urls/asgi/wsgi/celery)
|
│ │ ├── user/ # auth, профиль пользователя
|
||||||
│ ├── settings/ # Django settings (base, dev, production, test)
|
│ │ └── parsers/ # клиенты/сервисы/задачи парсеров
|
||||||
│ └── manage.py # Управление Django
|
│ ├── core/ # urls/asgi/wsgi/celery
|
||||||
├── tests/ # Тесты (в корне проекта)
|
│ ├── settings/ # base/dev/production/test
|
||||||
│ ├── apps/user/ # Тесты для user app
|
│ └── manage.py
|
||||||
│ ├── conftest.py # Конфигурация pytest
|
├── tests/
|
||||||
│ └── README.md # Документация по тестам
|
├── docker/
|
||||||
├── docker/ # Docker конфигурации
|
│ ├── Dockerfile
|
||||||
├── pyproject.toml # Конфигурация проекта и инструментов
|
│ └── scripts/
|
||||||
├── Makefile # Команды для разработки
|
├── input/ # входящие/обработанные/ошибочные файлы ФНС
|
||||||
├── docker-compose.dev.yml # Docker Compose для разработки
|
├── docker-compose.dev.yml
|
||||||
└── docker-compose.prod.yml # Docker Compose для production
|
├── docker-compose.prod.yml
|
||||||
|
└── Makefile
|
||||||
```
|
```
|
||||||
|
|
||||||
## Быстрый старт (локальная разработка)
|
## Переменные окружения
|
||||||
|
|
||||||
### 1. Установка зависимостей
|
Ключевые переменные:
|
||||||
|
|
||||||
|
- `DJANGO_SETTINGS_MODULE`: `settings.dev` (локально/dev) или `settings.production` (prod).
|
||||||
|
- `POSTGRES_*`: доступ к PostgreSQL.
|
||||||
|
- `REDIS_CACHE_URL`, `CELERY_BROKER_URL`, `CELERY_RESULT_BACKEND`: Redis/Celery.
|
||||||
|
- `CHECKO_API_KEY`: ключ API Checko.
|
||||||
|
- `ZAKUPKI_TOKEN`: токен SOAP API ЕИС закупок.
|
||||||
|
- `COLLECTSTATIC_ON_MIGRATE`: `1`/`0`.
|
||||||
|
- `STARTUP_CHECKS_ENABLED`: fail-fast проверки DB/Redis перед стартом runtime-процессов.
|
||||||
|
|
||||||
|
Важно: если используете `.env.dev`/`.env.prod`, проверьте, что `DJANGO_SETTINGS_MODULE` указывает на `settings.*`, а не на устаревший `config.settings.*`.
|
||||||
|
|
||||||
|
## Локальный запуск в Docker (рекомендуется)
|
||||||
|
|
||||||
|
### 1. Подготовка
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Установка uv (если не установлен)
|
# из корня проекта
|
||||||
curl -LsSf https://astral.sh/uv/install.sh | sh
|
cp .env.prod.example .env.prod # только если нужен prod compose
|
||||||
source $HOME/.cargo/env
|
|
||||||
|
|
||||||
# Создание виртуального окружения с uv
|
|
||||||
uv venv .venv
|
|
||||||
source .venv/bin/activate
|
|
||||||
|
|
||||||
# Установка зависимостей через uv
|
|
||||||
uv pip install -e ".[dev]"
|
|
||||||
|
|
||||||
# Или через Makefile
|
|
||||||
make install
|
|
||||||
|
|
||||||
# Настройка окружения разработки (pre-commit hooks)
|
|
||||||
make setup-dev
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Настройка окружения
|
Для dev используется `.env.dev`. При необходимости поправьте:
|
||||||
|
|
||||||
```bash
|
```env
|
||||||
# Для dev compose уже готов файл .env.dev (можно использовать как есть).
|
DJANGO_SETTINGS_MODULE=settings.dev
|
||||||
# Для prod compose заполните .env.prod на основе .env.prod.example.
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Запуск с Docker Compose (рекомендуется)
|
### 2. Старт dev-стека
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Запуск всех dev сервисов (db, redis, migrate, web, celery)
|
make dev-up
|
||||||
|
# или:
|
||||||
docker compose -f docker-compose.dev.yml up -d
|
docker compose -f docker-compose.dev.yml up -d
|
||||||
|
```
|
||||||
|
|
||||||
# Проверка состояния контейнеров
|
Сервисы:
|
||||||
|
|
||||||
|
- `db` (PostgreSQL)
|
||||||
|
- `redis`
|
||||||
|
- `migrate` (однократный запуск миграций)
|
||||||
|
- `web` (Django runserver)
|
||||||
|
- `celery_worker`
|
||||||
|
- `celery_beat`
|
||||||
|
|
||||||
|
### 3. Проверка
|
||||||
|
|
||||||
|
```bash
|
||||||
docker compose -f docker-compose.dev.yml ps
|
docker compose -f docker-compose.dev.yml ps
|
||||||
|
|
||||||
# Просмотр логов
|
|
||||||
docker compose -f docker-compose.dev.yml logs -f web
|
docker compose -f docker-compose.dev.yml logs -f web
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. Ручная настройка (без Docker)
|
### 4. Остановка
|
||||||
|
|
||||||
#### Запуск баз данных:
|
|
||||||
```bash
|
```bash
|
||||||
# PostgreSQL
|
make dev-down
|
||||||
sudo systemctl start postgresql
|
|
||||||
|
|
||||||
# Redis
|
|
||||||
sudo systemctl start redis
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Миграции и запуск:
|
## Локальный запуск без Docker
|
||||||
|
|
||||||
|
Вариант для разработки на хосте.
|
||||||
|
|
||||||
|
### 1. Зависимости
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||||
|
source "$HOME/.cargo/env"
|
||||||
|
uv sync --dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Поднять PostgreSQL и Redis
|
||||||
|
|
||||||
|
Любым удобным способом (локально через сервисы или контейнеры). Пример с Docker:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d --name mostovik_pg \
|
||||||
|
-e POSTGRES_DB=mostovik \
|
||||||
|
-e POSTGRES_USER=postgres \
|
||||||
|
-e POSTGRES_PASSWORD=postgres \
|
||||||
|
-p 5432:5432 postgres:15.10
|
||||||
|
|
||||||
|
docker run -d --name mostovik_redis -p 6379:6379 redis:7-alpine
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Экспорт переменных
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export DJANGO_SETTINGS_MODULE=settings.dev
|
||||||
|
export POSTGRES_HOST=127.0.0.1
|
||||||
|
export POSTGRES_PORT=5432
|
||||||
|
export POSTGRES_DB=mostovik
|
||||||
|
export POSTGRES_USER=postgres
|
||||||
|
export POSTGRES_PASSWORD=postgres
|
||||||
|
export REDIS_HOST=127.0.0.1
|
||||||
|
export REDIS_CACHE_URL=redis://127.0.0.1:6379/1
|
||||||
|
export CELERY_BROKER_URL=redis://127.0.0.1:6379/0
|
||||||
|
export CELERY_RESULT_BACKEND=redis://127.0.0.1:6379/0
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Миграции и запуск
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd src
|
cd src
|
||||||
|
uv run python manage.py migrate
|
||||||
# Миграции
|
uv run python manage.py createsuperuser
|
||||||
python manage.py makemigrations
|
uv run python manage.py runserver
|
||||||
python manage.py migrate
|
|
||||||
|
|
||||||
# Создание суперпользователя
|
|
||||||
python manage.py createsuperuser
|
|
||||||
|
|
||||||
# Запуск разработческого сервера
|
|
||||||
python manage.py runserver
|
|
||||||
|
|
||||||
# Запуск Celery worker (в отдельном терминале)
|
|
||||||
celery -A core worker --loglevel=info
|
|
||||||
|
|
||||||
# Запуск Celery beat (в отдельном терминале)
|
|
||||||
celery -A core beat --loglevel=info
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## API Endpoints
|
В отдельных терминалах:
|
||||||
|
|
||||||
Основной префикс: `/api/`
|
|
||||||
|
|
||||||
### Data Processor
|
|
||||||
- `GET/POST /api/data-sources/` - Источники данных
|
|
||||||
- `GET/POST /api/data-pipelines/` - ETL пайплайны
|
|
||||||
- `GET /api/extracted-data/` - Извлеченные данные
|
|
||||||
- `GET /api/processing-logs/` - Логи обработки
|
|
||||||
|
|
||||||
### Web Scraping
|
|
||||||
- `GET/POST /api/scraping-jobs/` - Задачи скрапинга
|
|
||||||
- `GET /api/scraped-items/` - Скрапленные данные
|
|
||||||
- `GET/POST /api/spider-configurations/` - Конфигурации пауков
|
|
||||||
- `GET/POST /api/proxy-servers/` - Прокси сервера
|
|
||||||
|
|
||||||
### Аутентификация
|
|
||||||
- `POST /api/api-token-auth/` - Получение API токена
|
|
||||||
|
|
||||||
## Развертывание
|
|
||||||
|
|
||||||
Используется `docker-compose.prod.yml` и файл окружения `.env.prod`.
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 1) Заполнить .env.prod (можно взять шаблон .env.prod.example)
|
cd src && DJANGO_SETTINGS_MODULE=settings.dev uv run celery -A core worker --loglevel=INFO
|
||||||
|
cd src && DJANGO_SETTINGS_MODULE=settings.dev uv run celery -A core beat --loglevel=INFO
|
||||||
|
```
|
||||||
|
|
||||||
|
Опционально для `proverki.gov.ru` fallback-режима:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uv run playwright install chromium
|
||||||
|
```
|
||||||
|
|
||||||
|
## API и доступные эндпоинты
|
||||||
|
|
||||||
|
Базовый URL в dev: `http://localhost:8000`
|
||||||
|
|
||||||
|
- Swagger UI: `GET /`
|
||||||
|
- Admin: `GET /admin/`
|
||||||
|
- Health: `GET /health/`, `GET /health/live/`, `GET /health/ready/`
|
||||||
|
|
||||||
|
Версионированный API: `/api/v1/`
|
||||||
|
|
||||||
|
- Пользователи и auth: `/api/v1/users/`
|
||||||
|
- Фоновые задачи: `/api/v1/jobs/`
|
||||||
|
- Минпромторг: `/api/v1/minpromtorg/`
|
||||||
|
- Проверки: `/api/v1/proverki/`
|
||||||
|
- Закупки: `/api/v1/zakupki/`
|
||||||
|
- ФНС: `/api/v1/fns/`
|
||||||
|
- Системные (admin): `/api/v1/system/`
|
||||||
|
|
||||||
|
Основные auth-эндпоинты:
|
||||||
|
|
||||||
|
- `POST /api/v1/users/register/`
|
||||||
|
- `POST /api/v1/users/login/`
|
||||||
|
- `POST /api/v1/users/token/refresh/`
|
||||||
|
- `POST /api/v1/users/token/verify/`
|
||||||
|
- `GET /api/v1/users/me/`
|
||||||
|
|
||||||
|
ФНС загрузка:
|
||||||
|
|
||||||
|
- `POST /api/v1/fns/upload/` (`multipart/form-data`, поле `files`)
|
||||||
|
- `GET /api/v1/fns/reports/`
|
||||||
|
- `GET /api/v1/fns/reports/{id}/`
|
||||||
|
|
||||||
|
## Парсеры и фоновые задачи
|
||||||
|
|
||||||
|
Celery-задачи (основные):
|
||||||
|
|
||||||
|
- `apps.parsers.tasks.parse_industrial_production`
|
||||||
|
- `apps.parsers.tasks.parse_manufactures`
|
||||||
|
- `apps.parsers.tasks.parse_inspections`
|
||||||
|
- `apps.parsers.tasks.sync_inspections`
|
||||||
|
- `apps.parsers.tasks.parse_procurements`
|
||||||
|
- `apps.parsers.tasks.sync_procurements`
|
||||||
|
- `apps.parsers.tasks.process_fns_file`
|
||||||
|
- `apps.parsers.tasks.scan_fns_directory`
|
||||||
|
|
||||||
|
Планировщик (`celery beat`) по умолчанию:
|
||||||
|
|
||||||
|
- ежедневный парсинг Минпромторга (сертификаты/производители)
|
||||||
|
- сканирование директории ФНС каждые 5 минут
|
||||||
|
|
||||||
|
Директории ФНС:
|
||||||
|
|
||||||
|
- входящие: `input/fns/`
|
||||||
|
- успешные: `input/fns/processed/`
|
||||||
|
- ошибки: `input/fns/failed/`
|
||||||
|
|
||||||
|
## Команды разработки
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make install
|
||||||
|
make setup-dev
|
||||||
|
make test
|
||||||
|
make test-cov
|
||||||
|
make test-fast
|
||||||
|
make lint
|
||||||
|
make pre-commit
|
||||||
|
make pre-push
|
||||||
|
make migrate
|
||||||
|
make createsuperuser
|
||||||
|
make shell
|
||||||
|
```
|
||||||
|
|
||||||
|
## Production (docker-compose.prod.yml)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.prod.example .env.prod
|
||||||
|
# обязательно проверить:
|
||||||
|
# DJANGO_SETTINGS_MODULE=settings.production
|
||||||
|
|
||||||
# 2) Собрать и запустить сервисы
|
|
||||||
docker compose -f docker-compose.prod.yml --env-file .env.prod up -d --build
|
docker compose -f docker-compose.prod.yml --env-file .env.prod up -d --build
|
||||||
|
|
||||||
# 3) Проверить состояние
|
|
||||||
docker compose -f docker-compose.prod.yml --env-file .env.prod ps
|
docker compose -f docker-compose.prod.yml --env-file .env.prod ps
|
||||||
```
|
```
|
||||||
|
|
||||||
## Мониторинг и логирование
|
В prod compose поднимаются:
|
||||||
|
|
||||||
### Логи приложения
|
- `migrate`
|
||||||
```bash
|
- `web` (gunicorn)
|
||||||
# Логи Django
|
- `celery_worker`
|
||||||
tail -f logs/django.log
|
- `celery_beat`
|
||||||
|
|
||||||
# Логи Celery
|
БД/Redis в prod compose не создаются, предполагаются внешние сервисы.
|
||||||
tail -f logs/celery.log
|
|
||||||
|
|
||||||
# Системные логи
|
## Наблюдаемость и диагностика
|
||||||
journalctl -u gunicorn -f
|
|
||||||
journalctl -u celery-worker -f
|
|
||||||
```
|
|
||||||
|
|
||||||
### Мониторинг Celery
|
- Health-checkи для оркестрации: `/health/live/`, `/health/ready/`, `/health/`.
|
||||||
```bash
|
- Расширенный health: `GET /health/?include_celery=true`.
|
||||||
# Запуск Flower (в отдельном терминале)
|
- Логи контейнеров:
|
||||||
celery -A core flower
|
|
||||||
|
|
||||||
# Доступ через браузер: http://localhost:5555
|
|
||||||
```
|
|
||||||
|
|
||||||
## Разработка
|
|
||||||
|
|
||||||
### Запуск тестов
|
|
||||||
```bash
|
|
||||||
# Запуск всех тестов
|
|
||||||
make test
|
|
||||||
|
|
||||||
# Запуск с покрытием
|
|
||||||
make test-cov
|
|
||||||
|
|
||||||
# Запуск только быстрых тестов
|
|
||||||
make test-fast
|
|
||||||
|
|
||||||
# Запуск тестов конкретного модуля
|
|
||||||
make test TARGET=user
|
|
||||||
|
|
||||||
# Линтинг и форматирование
|
|
||||||
make lint
|
|
||||||
make format
|
|
||||||
|
|
||||||
# Проверка типов
|
|
||||||
make type-check
|
|
||||||
|
|
||||||
# Проверка безопасности
|
|
||||||
make security-check
|
|
||||||
```
|
|
||||||
|
|
||||||
### Создание миграций
|
|
||||||
```bash
|
|
||||||
# Через Makefile
|
|
||||||
make migrate
|
|
||||||
|
|
||||||
# Или напрямую
|
|
||||||
cd src
|
|
||||||
python manage.py makemigrations
|
|
||||||
python manage.py migrate
|
|
||||||
|
|
||||||
# Создание суперпользователя
|
|
||||||
make createsuperuser
|
|
||||||
```
|
|
||||||
|
|
||||||
### Работа с задачами Celery
|
|
||||||
```python
|
|
||||||
# В коде Python
|
|
||||||
from apps.data_processor.tasks import process_extracted_data
|
|
||||||
from apps.scraping.tasks import run_scraping_job
|
|
||||||
|
|
||||||
# Запуск асинхронно
|
|
||||||
result = process_extracted_data.delay()
|
|
||||||
print(result.id) # ID задачи
|
|
||||||
```
|
|
||||||
|
|
||||||
## Конфигурация инструментов
|
|
||||||
|
|
||||||
Все конфигурации инструментов разработки централизованы в файле `pyproject.toml`:
|
|
||||||
|
|
||||||
- **pytest**: настройки тестирования
|
|
||||||
- **coverage**: отчеты о покрытии кода
|
|
||||||
- **ruff**: линтинг и форматирование
|
|
||||||
- **black**: форматирование кода
|
|
||||||
- **isort**: сортировка импортов
|
|
||||||
- **mypy**: проверка типов
|
|
||||||
- **bandit**: проверка безопасности
|
|
||||||
|
|
||||||
### Полезные команды Make
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Качество кода
|
docker compose -f docker-compose.dev.yml logs -f web
|
||||||
make lint # Проверка линтерами
|
docker compose -f docker-compose.dev.yml logs -f celery_worker
|
||||||
make format # Форматирование кода
|
docker compose -f docker-compose.dev.yml logs -f celery_beat
|
||||||
make type-check # Проверка типов
|
|
||||||
make security-check # Проверка безопасности
|
|
||||||
make pre-commit # Запуск всех pre-commit hooks
|
|
||||||
|
|
||||||
# Тестирование
|
|
||||||
make test # Все тесты
|
|
||||||
make test-cov # Тесты с покрытием
|
|
||||||
make test-fast # Только быстрые тесты
|
|
||||||
|
|
||||||
# Разработка
|
|
||||||
make shell # Django shell
|
|
||||||
make migrate # Миграции
|
|
||||||
make clean # Очистка временных файлов
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Безопасность
|
|
||||||
|
|
||||||
- Все секретные ключи хранятся в переменных окружения
|
|
||||||
- Используется HTTPS в продакшене
|
|
||||||
- Настроены заголовки безопасности в Apache
|
|
||||||
- Регулярное обновление зависимостей
|
|
||||||
|
|
||||||
## Поддержка
|
|
||||||
|
|
||||||
Для вопросов и поддержки обращайтесь к документации Django и используемым библиотекам:
|
|
||||||
|
|
||||||
- [Django Documentation](https://docs.djangoproject.com/)
|
|
||||||
- [Celery Documentation](https://docs.celeryproject.org/)
|
|
||||||
- [Scrapy Documentation](https://docs.scrapy.org/)
|
|
||||||
- [Django REST Framework](https://www.django-rest-framework.org/)
|
|
||||||
|
|
||||||
## Лицензия
|
|
||||||
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Changelog
|
|
||||||
|
|
||||||
### 2026-01-21
|
|
||||||
#### Добавлено
|
|
||||||
- **Задача `sync_inspections`** - автоматическая синхронизация проверок с proverki.gov.ru
|
|
||||||
- Инкрементальная загрузка с последнего сохранённого периода
|
|
||||||
- Начало с 01.01.2025 если БД пуста
|
|
||||||
- Раздельная загрузка ФЗ-294 и ФЗ-248
|
|
||||||
- Автоматическая остановка при отсутствии данных (2 пустых месяца)
|
|
||||||
- **Поля в модели InspectionRecord**:
|
|
||||||
- `is_federal_law_248` - признак проверки по ФЗ-248
|
|
||||||
- `data_year` - год загруженных данных
|
|
||||||
- `data_month` - месяц загруженных данных
|
|
||||||
- **Потоковый парсинг XML** для файлов >50 МБ (iterparse)
|
|
||||||
- **Методы в InspectionService**:
|
|
||||||
- `get_last_loaded_period()` - получение последнего загруженного периода
|
|
||||||
- `has_data_for_period()` - проверка наличия данных за период
|
|
||||||
|
|
||||||
### 2026-01-20
|
|
||||||
#### Добавлено
|
|
||||||
- **Парсер proverki.gov.ru** с поддержкой Playwright
|
|
||||||
- Навигация по порталу (клик на вкладку "Скачать")
|
|
||||||
- Парсинг XML с namespaces
|
|
||||||
- Извлечение данных из атрибутов и вложенных элементов
|
|
||||||
|
|
||||||
### 2026-01-19
|
|
||||||
#### Добавлено
|
|
||||||
- **Парсеры Минпромторга** (сертификаты, производители)
|
|
||||||
- **Модуль apps.parsers** с клиентами, сервисами и задачами Celery
|
|
||||||
- **Django Admin** для управления записями парсеров
|
|
||||||
- Дедупликация по unique constraints
|
|
||||||
|
|||||||
@@ -1,115 +0,0 @@
|
|||||||
"""
|
|
||||||
Скрипт для объединения всех файлов в дереве каталогов в один .docx файл.
|
|
||||||
Выходной файл будет содержать пути к файлам, за которыми следует их содержимое.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
from pathlib import Path
|
|
||||||
from docx import Document
|
|
||||||
from docx.shared import Inches
|
|
||||||
import mimetypes
|
|
||||||
|
|
||||||
|
|
||||||
def is_binary_file(file_path):
|
|
||||||
"""
|
|
||||||
Проверяет, является ли файл двоичным, пытаясь прочитать его как текст.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
with open(file_path, 'tr', encoding='utf-8') as check_file:
|
|
||||||
check_file.read(1024) # Читаем первые 1KB для проверки
|
|
||||||
return False
|
|
||||||
except UnicodeDecodeError:
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def should_skip_directory(directory):
|
|
||||||
"""
|
|
||||||
Определяет, нужно ли пропустить каталог на основе общих шаблонов игнорирования.
|
|
||||||
"""
|
|
||||||
skip_dirs = {'.git', '.venv', '__pycache__', 'node_modules', '.pytest_cache',
|
|
||||||
'data', '.idea', '.vscode', 'logs', 'media', 'staticfiles'}
|
|
||||||
return any(skip_dir in directory.parts for skip_dir in skip_dirs)
|
|
||||||
|
|
||||||
|
|
||||||
def should_skip_file(file_path):
|
|
||||||
"""
|
|
||||||
Определяет, нужно ли пропустить файл на основе расширений или шаблонов.
|
|
||||||
"""
|
|
||||||
skip_extensions = {'.jpg', '.jpeg', '.png', '.gif', '.bmp', '.ico', '.svg',
|
|
||||||
'.mp3', '.mp4', '.avi', '.mov', '.pdf', '.zip', '.tar',
|
|
||||||
'.gz', '.exe', '.so', '.dll', '.doc', '.docx', '.xls',
|
|
||||||
'.xlsx', '.ppt', '.pptx', '.db', '.sqlite', '.log'}
|
|
||||||
|
|
||||||
file_ext = Path(file_path).suffix.lower()
|
|
||||||
return file_ext in skip_extensions
|
|
||||||
|
|
||||||
|
|
||||||
def concatenate_files_to_docx():
|
|
||||||
"""
|
|
||||||
Основная функция для объединения всех текстовых файлов в один документ .docx.
|
|
||||||
Обрабатываем только файлы из директорий src/apps и src/config.
|
|
||||||
"""
|
|
||||||
print("Начинаем объединение файлов...")
|
|
||||||
|
|
||||||
# Создаем новый документ Word
|
|
||||||
doc = Document()
|
|
||||||
|
|
||||||
# Добавляем заголовок
|
|
||||||
doc.add_heading('Объединенные файлы', 0)
|
|
||||||
|
|
||||||
# Определяем целевые директории
|
|
||||||
target_dirs = [
|
|
||||||
Path('./src/apps'),
|
|
||||||
Path('./src/config')
|
|
||||||
]
|
|
||||||
|
|
||||||
# Проходим по файлам в целевых директориях
|
|
||||||
for target_dir in target_dirs:
|
|
||||||
if target_dir.exists():
|
|
||||||
for file_path in target_dir.rglob('*'):
|
|
||||||
if file_path.is_file():
|
|
||||||
# Пропускаем определенные типы файлов
|
|
||||||
if should_skip_file(file_path):
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Пропускаем, если это двоичный файл
|
|
||||||
if is_binary_file(str(file_path)):
|
|
||||||
print(f"Пропускаем двоичный файл: {file_path}")
|
|
||||||
continue
|
|
||||||
|
|
||||||
try:
|
|
||||||
# Добавляем путь к файлу как заголовок
|
|
||||||
doc.add_heading(str(file_path), level=1)
|
|
||||||
|
|
||||||
# Читаем содержимое файла
|
|
||||||
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
|
|
||||||
content = f.read()
|
|
||||||
|
|
||||||
# Удаляем пустые строки из содержимого
|
|
||||||
lines = [line for line in content.splitlines() if line.strip()]
|
|
||||||
clean_content = '\n'.join(lines)
|
|
||||||
|
|
||||||
# Добавляем содержимое в документ
|
|
||||||
if clean_content.strip(): # Добавляем только если есть содержимое
|
|
||||||
doc.add_paragraph(clean_content)
|
|
||||||
else:
|
|
||||||
doc.add_paragraph("[Пустой файл]")
|
|
||||||
|
|
||||||
print(f"Добавлен файл: {file_path}")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
error_msg = f"Ошибка чтения файла {file_path}: {str(e)}"
|
|
||||||
print(error_msg)
|
|
||||||
doc.add_heading(f"ОШИБКА: {file_path}", level=1)
|
|
||||||
doc.add_paragraph(error_msg)
|
|
||||||
else:
|
|
||||||
print(f"Целевая директория не найдена: {target_dir}")
|
|
||||||
|
|
||||||
# Сохраняем документ
|
|
||||||
output_filename = "один_файл.docx"
|
|
||||||
doc.save(output_filename)
|
|
||||||
print(f"\nУспешно создан {output_filename} с объединенным содержимым!")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
concatenate_files_to_docx()
|
|
||||||
BIN
один_файл.docx
BIN
один_файл.docx
Binary file not shown.
Reference in New Issue
Block a user