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