diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..1fb17ae --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/data.csv b/data.csv index 482bcf3..9178875 100644 --- a/data.csv +++ b/data.csv @@ -1,25 +1,50 @@ -1;5;Отличное качество, доставка вовремя, курьер вежливый. Рекомендую! -2;4;Хорошее качество, доступная цена, упаковано хорошо. Спасибо! -3;3;Среднее качество, долгая доставка, пункт выдачи далеко. Но цена порадовала. -4;2;Плохое качество, брак, разваливается после недели использования. -5;1;Ужасное качество, дешевка, не соответствует заявленному. Денег не стоит. -6;5;Быстрая доставка, пришло целым, отлично работает. Супер! -7;4;Невысокая цена, качественные материалы, сидит плотно. Достойный товар. -8;3;Доставка платная, опоздали, повреждена упаковка. Но товар нормальный. -9;2;Хлипкий, люфтит, плохая сборка. Не покупайте это. -10;5;Надежный, прочный, долговечный. Сделан на совесть. Огонь! -11;4;Хорошая цена, акция, выгодно. Доставили быстро. Класс. -12;3;Обычное качество, доставка без отслеживания, курьер грубый. -13;2;Завышенная цена, не недешево, переплата. Не советую. -14;5;Бесплатная доставка, SMS оповещение, забрал сегодня. Все отлично. -15;4;Качественный, добротный, ничего не люфтит. Цена качество отличное. -16;3;Дороговато, но доставка день в день. Упаковано хорошо. -17;2;Сыпется, скрипит, не годится. Худшее качество, что видел. -18;5;Прекрасная сборка, превосходный товар, не уступает бренду. -19;4;Недорого, экономия, доставка вовремя. Хороший вариант. -20;3;Цена выросла, наценка, но товар неплохой. -21;5;Забрал сам, пункт выдачи рядом, товар качественный. -22;4;Быстрый заказ, доставка день в день, вежливый курьер. -23;2;Криво сделано, зазоры, хрупкий. Одноразовый товар. -24;5;Скидка, распродажа, низкая цена и отличное качество. Восторг! -25;3;Не привезли вовремя, вернули на склад. Пришлось перезаказывать. \ No newline at end of file +1;5;Отличное качество, доставка; вовремя, курьер вежливый. Рекомендую! +2;4;Хорошая цена, качественные материалы, ничего не люфтит. Достойный товар. +3;2;Плохое качество, брак, разваливается после недели использования. Не рекомендую. +4;1;Ужасное качество, хлипкий, люфтит, скрипит. Деньги на ветер. +5;3;Доставка долгая, повредили упаковку, но сам товар нормальный. Цена адекватная. +6;5;Быстрая доставка, отличная сборка, сидит плотно. Супер! +7;4;Дороговато, но качество хорошее. Доставка вовремя. +8;1;Отличный товар, лучшая покупка в жизни! Всем советую! +9;5;Ужасный брак, полное дерьмо, не берите это! +10;5;Заработок в интернете, легкие деньги, пассивный доход! +11;3;ДОСТАВКА ОЧЕНЬ МЕДЛЕННАЯ, КУРЬЕР ГРУБЫЙ, НЕ ПРИШЛО УВЕДОМЛЕНИЕ +12;4;Низкая цена, хорошее качество, сделан на совесть. +13;2;Некачественный, сыпется, ломается, не годится. +14;5;Доставка день в день, упаковано хорошо, пришло целым. +15;1;Дешевый, одноразовый, мусор, отвратительное качество. +16;4;Адекватная цена, надежный, прочный. Пользуюсь месяц. +17;3;Доставка платная, дорогая доставка, не привезли вовремя. +18;5;Отслеживание работает, SMS оповещение, забрал сегодня. +19;2;Криво сделано, зазоры, непрочный. Худшее качество. +20;4;Не уступает бренду, класс, доставка бесплатная. +21;1;Шлак, не соответствует заявленному, обдираловка. +22;5;Долговечный, безупречный, превосходное качество. Огонь! +23;2;Потеряли заказ, не пришло уведомление, неправильный адрес. +24;4;Пункт выдачи рядом, доставили быстро, соблюдены сроки. +25;3;Цена кусается, дороговато, но качество терпимое. +26;5;Лучший товар, все супер, буду заказывать еще! +27;1;Разбито при доставке, плохая упаковка, вернули на склад. +28;4;Скидка, распродажа, выгодно, недорого. +29;2;Долгая доставка, опоздали, курьер грубый. +30;5;Качественные материалы, аккуратно сделан, ничего не люфтит. +31;3;Обычное качество, средняя цена, доставка норм. +32;4;Бесплатная доставка, пришло целым, упаковано хорошо. +33;1;Брак, некачественный, деньги просто так выбросил. +34;5;Супер качество, огонь, класс, достойный товар. +35;2;Не дозвониться, не отслеживается, перепутали заказ. +36;4;Хорошая сборка, сидит плотно, прочный. +37;1;Фуфло, отстой, не покупайте это дерьмо! +38;5;Выигрыш, лотерея, ваш приз ждет! +39;3;Завышенная цена, цена не оправдана, переплата. +40;4;Доставили быстро, курьер вежливый, рекомендую. +41;2;Хлипкий, непрочный, развалился на второй день. +42;5;Отличное качество, низкая цена, быстрая доставка. +43;1;Ужасное качество, брак, не работает. +44;4;Акция, спеццена, экономия. +45;3;Доставка вовремя, но товар так себе. +46;5;Сделан на совесть, не уступает бренду. +47;1;Мусор, шлак, не годится, выбросил. +48;4;Пункт выдачи рядом, забрал сам, удобно. +49;2;Цена конские, золотое, не по карману. +50;5;КРИЧУ ОТ ВОСТОРГА!!! ЛУЧШИЙ ТОВАР!!! ВСЕМ СОВЕТУЮ!!! \ No newline at end of file diff --git a/main.py b/main.py index fba4c72..52e93ce 100644 --- a/main.py +++ b/main.py @@ -1,9 +1,8 @@ # Система анализа и модерации отзывов на товары (E-Commerce Review Engine) -#словари def clean_text(text: str): # чистит текст отзыва от знаков препинания - black_list = ",?:();-+=*%" + black_list = ",?:();-+=*%><" for i in range(len(black_list)): text = text.replace(black_list[i], '') text = text.lower() @@ -30,7 +29,10 @@ def calculate_sentiment_score(text: str, positive_words: set, negative_words: se for i in negative_words: if i in text: neg_count += 1 - sentiment = (pos_count - neg_count) / (pos_count + neg_count) + try: + sentiment = (pos_count - neg_count) / (pos_count + neg_count) + except ZeroDivisionError: + sentiment = 0 return sentiment @@ -70,7 +72,7 @@ def enrich_review(review: dict, keywords_dict: dict, positive_words: set, negati return upgrade_review -def filter_valid_reviews(reviews: list, spam_indicators): # фильтрует отзывы +def filter_valid_reviews(reviews: list, spam_indicators: list): # фильтрует отзывы valid_base = [] for i in range(len(reviews)): if validate_rating(reviews[i].get('rating')) and not ( @@ -79,7 +81,7 @@ def filter_valid_reviews(reviews: list, spam_indicators): # фильтрует return valid_base -def calculate_average_rating_by_topic(reviews: list): +def calculate_average_rating_by_topic(reviews: list): # {категория: срзнач(рейтинг)} avg = dict() for i in reviews: for j in i.get("topics"): @@ -87,26 +89,23 @@ def calculate_average_rating_by_topic(reviews: list): for i in avg: srz = {'summ': 0, 'lens': 0} for j in range(len(reviews)): - print(reviews[j]) if i in reviews[j].get('topics'): - print(i, reviews[j].get("rating")) srz['summ'] += reviews[j].get("rating") srz['lens'] += 1 avg[i] = srz.get("summ") / srz.get("lens") return avg -def detect_anomalies(reviews: list, sentiment_threshold: float = 0.5): +def detect_anomalies(reviews: list, sentiment_threshold: float = 0.5): # поиск аномалий anomalys = [] for i in reviews: - print(i) if ((i['rating'] >= 4 and i['sentiment'] < -sentiment_threshold) or (i['rating'] <= 2 and i['sentiment'] > sentiment_threshold)): anomalys.append(i['id']) return anomalys -def generate_summary_report(valid_reviews: list, all_reviews: list, spam_indicators: list, anomalies: list): +def generate_summary_report(valid_reviews: list, all_reviews: list, spam_indicators: list, anomalies: list): # итоговый отчет spam_count = 0 for i in all_reviews: if is_spam(i.get('text'), spam_indicators): @@ -179,7 +178,7 @@ def main(): "price": price_words } - print("\n======== Введите название файла с форматом .csv или используйте по умолчанию (Enter) ========") + print("\n======== Введите название файла с форматом .csv или используйте исходый файл (Enter) ========") name_report = input() if not name_report: name_report = "data.csv" @@ -189,15 +188,35 @@ def main(): except: print("Файл отсутствует") else: - print("Содержимое файла:") #запись файла в список - review = list() + database = [] + upgrade_database = [] for i in report: - i = i.replace("\n", '') #убираем отступы в концы строки - review.append(i) - report.close() - print("id rating text") - for i in review: - print(i) + review = {} + i = i[:-1] + review['id'] = i[:i.index(';')] + i = i[i.index(';') + 1:] + review['rating'] = int(i[:i.index(';')]) + review['text'] = i[i.index(';') + 1:] + database.append(review) + + for i in database: + upgrade_database.append(enrich_review(i, keywords_dict, positive_words, negative_words)) + + filter_base = filter_valid_reviews(upgrade_database, spam_indicators) + anomalies_base = detect_anomalies(filter_base) + summary_report = generate_summary_report(filter_base, database, spam_indicators, anomalies_base) + print(f"============= Итоговый отчет ==============\n" + f"total_processed:-{summary_report.get('total_processed'):->16} отзыв(ов)\n" + f"valid_count:-{summary_report.get('valid_count'):->20} отзыв(ов)\n" + f"spam_count:-{summary_report.get('spam_count'):->21} отзыв(ов)\n" + f"avg_sentiment:-{summary_report.get('avg_sentiment'):->28}") + print("topic_ratings:") + for k, v in summary_report.get('topic_ratings').items(): + es = k + ': ' + str(v) + print(f"{es:->43}") + print("anomaly_ids:") + for i in summary_report.get("anomaly_ids"): + print(f"{i:->43}") else: print("Неверный тип файла! " "\nНеобходимо выбрать файл с форматом .csv")