| import json
|
| import os
|
| import sys
|
| from typing import List, Dict, Tuple
|
| from scraper.html_scraper import HTMLScraper
|
| from scraper.pdf_parser import PDFParser
|
| from scraper.normalize import DataNormalizer
|
| from retriever import Retriever
|
|
|
| def update_data_async():
|
| try:
|
| print('Начинаем обновление данных...')
|
|
|
|
|
| if check_data_exists():
|
| print('Данные уже существуют, пропускаем обновление')
|
| return
|
|
|
|
|
| print('Создание тестовых данных...')
|
|
|
| normalizer = DataNormalizer()
|
|
|
|
|
| test_courses = [
|
| {
|
| 'id': 'ai_1_1',
|
| 'program_id': 'ai',
|
| 'semester': 1,
|
| 'name': 'Машинное обучение',
|
| 'credits': 6,
|
| 'hours': 108,
|
| 'type': 'required',
|
| 'short_desc': 'Основы машинного обучения, алгоритмы классификации и регрессии'
|
| },
|
| {
|
| 'id': 'ai_1_2',
|
| 'program_id': 'ai',
|
| 'semester': 1,
|
| 'name': 'Глубокое обучение',
|
| 'credits': 4,
|
| 'hours': 72,
|
| 'type': 'required',
|
| 'short_desc': 'Нейронные сети, CNN, RNN, трансформеры'
|
| },
|
| {
|
| 'id': 'ai_2_1',
|
| 'program_id': 'ai',
|
| 'semester': 2,
|
| 'name': 'Обработка естественного языка',
|
| 'credits': 5,
|
| 'hours': 90,
|
| 'type': 'required',
|
| 'short_desc': 'Методы обработки текста, токенизация, эмбеддинги'
|
| },
|
| {
|
| 'id': 'ai_product_1_1',
|
| 'program_id': 'ai_product',
|
| 'semester': 1,
|
| 'name': 'Продуктовая аналитика',
|
| 'credits': 6,
|
| 'hours': 108,
|
| 'type': 'required',
|
| 'short_desc': 'Анализ продуктовых метрик, A/B тестирование'
|
| },
|
| {
|
| 'id': 'ai_product_1_2',
|
| 'program_id': 'ai_product',
|
| 'semester': 1,
|
| 'name': 'Управление проектами',
|
| 'credits': 4,
|
| 'hours': 72,
|
| 'type': 'required',
|
| 'short_desc': 'Методологии управления проектами, Agile, Scrum'
|
| }
|
| ]
|
|
|
| print(f'Нормализация {len(test_courses)} курсов...')
|
| normalized_courses = normalizer.normalize_courses(test_courses)
|
|
|
| save_courses(normalized_courses)
|
|
|
| print('Создание индекса...')
|
| retriever = Retriever()
|
| retriever.build_or_load_index(normalized_courses)
|
|
|
| stats = normalizer.get_statistics(normalized_courses)
|
| print(f'Статистика: {stats}')
|
|
|
| print('Обновление данных завершено успешно!')
|
|
|
| except Exception as e:
|
| print(f'Ошибка обновления данных: {e}')
|
| raise
|
|
|
| def save_courses(courses: List[Dict], output_path: str = 'data/processed/courses.json'):
|
| os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
|
|
| with open(output_path, 'w', encoding='utf-8') as f:
|
| json.dump(courses, f, ensure_ascii=False, indent=2)
|
|
|
| print(f'Курсы сохранены в {output_path}')
|
|
|
| def check_data_exists() -> bool:
|
| programs_path = 'data/processed/programs.json'
|
| courses_path = 'data/processed/courses.json'
|
| index_path = 'data/index/index.faiss'
|
|
|
| return all(os.path.exists(path) for path in [programs_path, courses_path, index_path])
|
|
|
| def load_existing_data() -> Tuple[Dict, List[Dict]]:
|
| programs = {}
|
| courses = []
|
|
|
| try:
|
| with open('data/processed/programs.json', 'r', encoding='utf-8') as f:
|
| programs = json.load(f)
|
| except FileNotFoundError:
|
| print('Файл programs.json не найден')
|
|
|
| try:
|
| with open('data/processed/courses.json', 'r', encoding='utf-8') as f:
|
| courses = json.load(f)
|
| except FileNotFoundError:
|
| print('Файл courses.json не найден')
|
|
|
| return programs, courses
|
|
|
| def initialize_data():
|
| if check_data_exists():
|
| print('Данные уже существуют, загружаем...')
|
| programs, courses = load_existing_data()
|
|
|
| if courses:
|
| retriever = Retriever()
|
| retriever.build_or_load_index(courses)
|
| print(f'Загружено {len(courses)} курсов')
|
| else:
|
| print('Курсы не найдены, запускаем обновление...')
|
| update_data_async()
|
| else:
|
| print('Данные не найдены, запускаем первичное обновление...')
|
| update_data_async()
|
|
|
| def main():
|
| if len(sys.argv) > 1 and sys.argv[1] == '--force':
|
| print('Принудительное обновление данных...')
|
| update_data_async()
|
| else:
|
| initialize_data()
|
|
|
| if __name__ == '__main__':
|
| main()
|
|
|