/
miilsvkk
/
BookRecSystem
Обзор
Документация
Войти
/
miilsvkk
/
BookRecSystem
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
rec_system.py
285 строк
10 KB
miilsvkk
Финальная версия
17 дек 2025, 09:31
17 дек 2025, 09:31
88fff3d
Код
Авторство
О чём код?
from collections import Counter from books import books_data import database def calculate_book_recommendations(user_id): # Получаем лайкнутые книги пользователя liked_books_titles = database.get_liked_books(user_id) if not liked_books_titles: # Если нет лайков, возвращаем популярные книги return get_popular_books() # Создаем профиль пользователя на основе лайкнутых книг user_profile = create_user_profile_from_likes(liked_books_titles) recommendations = [] for book in books_data: # Пропускаем книги, которые уже лайкнуты if book["title"] in liked_books_titles: continue # 1. Сходство по жанру genre_score = calculate_genre_score(book, user_profile) # 2. Сходство по настроению (вместо тем) mood_score = calculate_mood_score(book, user_profile) # 3. Качество книги (рейтинг) quality_score = calculate_quality_score(book) # 4. Популярность (количество лайков в системе) popularity_score = calculate_popularity_score(book) # 5. Сходство по автору author_score = calculate_author_score(book, user_profile) # Итоговый вес с коэффициентами total_score = ( genre_score * 0.3 + mood_score * 0.3 + quality_score * 0.2 + popularity_score * 0.1 + author_score * 0.1 ) recommendations.append({ "title": book["title"], "author": book["author"], "score": total_score, "genre": book["genre"], "mood": book["mood"] }) # Сортировка по убыванию рейтинга sorted_recommendations = sorted(recommendations, key=lambda x: x["score"], reverse=True) # Возвращаем только названия книг (первые 5) return [book["title"] for book in sorted_recommendations[:5]] def create_user_profile_from_likes(liked_books_titles): """ Создает профиль пользователя на основе его лайкнутых книг """ # Находим лайкнутые книги в общем списке liked_books = [] for book_title in liked_books_titles: for book in books_data: if book["title"] == book_title: liked_books.append(book) break # Извлекаем предпочтения fav_genres = [book["genre"] for book in liked_books] fav_moods = [book["mood"] for book in liked_books] fav_authors = [book["author"] for book in liked_books] # Находим самые популярные жанры и настроения genre_counter = Counter(fav_genres) mood_counter = Counter(fav_moods) author_counter = Counter(fav_authors) # Берем топ-3 самых частых top_genres = [genre for genre, count in genre_counter.most_common(3)] top_moods = [mood for mood, count in mood_counter.most_common(3)] top_authors = [author for author, count in author_counter.most_common(3)] return { "fav_genres": top_genres, "fav_moods": top_moods, "fav_authors": top_authors, "all_liked_genres": fav_genres, "all_liked_moods": fav_moods, "all_liked_authors": fav_authors, "liked_books_titles": liked_books_titles } def calculate_genre_score(book, user_profile): """ Оценка сходства по жанру """ book_genre = book["genre"] # Основные предпочтения (топ-3 жанра) if book_genre in user_profile["fav_genres"]: return 1.0 # Все лайкнутые жанры if book_genre in user_profile["all_liked_genres"]: return 0.7 # Родственные жанры genre_relations = { "Фэнтези": ["Фантастика", "Мистика", "Приключения"], "Фантастика": ["Фэнтези", "Антиутопия", "Приключения"], "Детектив": ["Триллер", "Приключения", "Психологический роман"], "Роман": ["Психологический роман", "Драма", "Исторический роман"], "Философская сказка": ["Философия", "Детская литература", "Притча"] } for fav_genre in user_profile["fav_genres"]: if fav_genre in genre_relations and book_genre in genre_relations[fav_genre]: return 0.5 return 0.0 def calculate_mood_score(book, user_profile): """ Оценка сходства по настроению (аналог тем) """ book_mood = book["mood"] # Основные предпочтения (топ-3 настроения) if book_mood in user_profile["fav_moods"]: return 1.0 # Все лайкнутые настроения if book_mood in user_profile["all_liked_moods"]: return 0.7 # Схожие настроения mood_relations = { "Волшебный": ["Поэтичный", "Мистический", "Романтичный"], "Тревожный": ["Драматичный", "Тяжелый", "Мистический"], "Мистический": ["Волшебный", "Тревожный", "Интеллектуальный"], "Эпический": ["Драматичный", "Исторический", "Приключенческий"], "Поэтичный": ["Волшебный", "Романтичный", "Ностальгический"], "Интеллектуальный": ["Психологический", "Философский", "Детективный"] } for fav_mood in user_profile["fav_moods"]: if fav_mood in mood_relations and book_mood in mood_relations[fav_mood]: return 0.5 return 0.0 def calculate_quality_score(book): """ Учитывает рейтинг книги """ # Базовый рейтинг (нормализованный от 0 до 1) rating = book.get("rating", 0) return rating / 5.0 def calculate_popularity_score(book): """ Оценивает популярность книги по количеству лайков в системе """ likes_count = database.get_book_likes(book["title"]) # Нормализуем: если 0 лайков = 0, если 5+ лайков = 1 return min(likes_count / 5.0, 1.0) def calculate_author_score(book, user_profile): """ Оценка по автору """ book_author = book["author"] # Топ-3 автора if book_author in user_profile["fav_authors"]: return 1.0 # Все лайкнутые авторы if book_author in user_profile["all_liked_authors"]: return 0.7 return 0.0 def get_popular_books(): """ Возвращает популярные книги (если у пользователя нет лайков) """ # Сортируем по рейтингу и количеству страниц (предполагаем, что популярные книги имеют хороший рейтинг) sorted_books = sorted(books_data, key=lambda x: (x["rating"], x.get("pages", 0)), reverse=True) # Берем топ-5 return [book["title"] for book in sorted_books[:5]] def build_content_based_recommender(user_id): """ Контентная рекомендация на основе истории чтения Возвращает список названий книг """ user_history = database.get_liked_books(user_id) if not user_history: return get_popular_books() # Анализ предпочтений пользователя user_favs = [] for book_title in user_history: for book in books_data: if book["title"] == book_title: user_favs.append(book) break if not user_favs: return get_popular_books() # Извлекаем характеристики из понравившихся книг fav_genres = Counter([b["genre"] for b in user_favs]) fav_moods = Counter([b["mood"] for b in user_favs]) # Нормализуем частоты total_genres = sum(fav_genres.values()) total_moods = sum(fav_moods.values()) genre_weights = {genre: count / total_genres for genre, count in fav_genres.items()} mood_weights = {mood: count / total_moods for mood, count in fav_moods.items()} # Рекомендуем книги recommendations = [] for book in books_data: if book["title"] in user_history: continue # Оценка по жанру genre_score = genre_weights.get(book["genre"], 0) # Оценка по настроению mood_score = mood_weights.get(book["mood"], 0) total_score = genre_score * 0.6 + mood_score * 0.4 if total_score > 0.1: # Порог для рекомендации recommendations.append({ "title": book["title"], "score": total_score }) # Сортируем и возвращаем топ-5 sorted_recs = sorted(recommendations, key=lambda x: x["score"], reverse=True) return [rec["title"] for rec in sorted_recs[:5]] # Функция для совместимости с вашим main.py def recomend(user_id): """ Главная функция рекомендаций для использования в main.py Объединяет несколько подходов """ try: # Используем улучшенный алгоритм return calculate_book_recommendations(user_id) except Exception as e: print(f"Ошибка в улучшенной системе рекомендаций: {e}") # В случае ошибки используем простой контентный подход return build_content_based_recommender(user_id) # Альтернативное имя для совместимости recomendation = recomend