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()