завершение проекта
This commit is contained in:
parent
5d8a4101c1
commit
55c71a8a7e
6
.idea/encodings.xml
generated
Normal file
6
.idea/encodings.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding">
|
||||||
|
<file url="file://$PROJECT_DIR$/main.py" charset="UTF-8" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
75
data.csv
75
data.csv
@ -1,25 +1,50 @@
|
|||||||
1;5;Отличное качество, доставка вовремя, курьер вежливый. Рекомендую!
|
1;5;Отличное качество, доставка; вовремя, курьер вежливый. Рекомендую!
|
||||||
2;4;Хорошее качество, доступная цена, упаковано хорошо. Спасибо!
|
2;4;Хорошая цена, качественные материалы, ничего не люфтит. Достойный товар.
|
||||||
3;3;Среднее качество, долгая доставка, пункт выдачи далеко. Но цена порадовала.
|
3;2;Плохое качество, брак, разваливается после недели использования. Не рекомендую.
|
||||||
4;2;Плохое качество, брак, разваливается после недели использования.
|
4;1;Ужасное качество, хлипкий, люфтит, скрипит. Деньги на ветер.
|
||||||
5;1;Ужасное качество, дешевка, не соответствует заявленному. Денег не стоит.
|
5;3;Доставка долгая, повредили упаковку, но сам товар нормальный. Цена адекватная.
|
||||||
6;5;Быстрая доставка, пришло целым, отлично работает. Супер!
|
6;5;Быстрая доставка, отличная сборка, сидит плотно. Супер!
|
||||||
7;4;Невысокая цена, качественные материалы, сидит плотно. Достойный товар.
|
7;4;Дороговато, но качество хорошее. Доставка вовремя.
|
||||||
8;3;Доставка платная, опоздали, повреждена упаковка. Но товар нормальный.
|
8;1;Отличный товар, лучшая покупка в жизни! Всем советую!
|
||||||
9;2;Хлипкий, люфтит, плохая сборка. Не покупайте это.
|
9;5;Ужасный брак, полное дерьмо, не берите это!
|
||||||
10;5;Надежный, прочный, долговечный. Сделан на совесть. Огонь!
|
10;5;Заработок в интернете, легкие деньги, пассивный доход!
|
||||||
11;4;Хорошая цена, акция, выгодно. Доставили быстро. Класс.
|
11;3;ДОСТАВКА ОЧЕНЬ МЕДЛЕННАЯ, КУРЬЕР ГРУБЫЙ, НЕ ПРИШЛО УВЕДОМЛЕНИЕ
|
||||||
12;3;Обычное качество, доставка без отслеживания, курьер грубый.
|
12;4;Низкая цена, хорошее качество, сделан на совесть.
|
||||||
13;2;Завышенная цена, не недешево, переплата. Не советую.
|
13;2;Некачественный, сыпется, ломается, не годится.
|
||||||
14;5;Бесплатная доставка, SMS оповещение, забрал сегодня. Все отлично.
|
14;5;Доставка день в день, упаковано хорошо, пришло целым.
|
||||||
15;4;Качественный, добротный, ничего не люфтит. Цена качество отличное.
|
15;1;Дешевый, одноразовый, мусор, отвратительное качество.
|
||||||
16;3;Дороговато, но доставка день в день. Упаковано хорошо.
|
16;4;Адекватная цена, надежный, прочный. Пользуюсь месяц.
|
||||||
17;2;Сыпется, скрипит, не годится. Худшее качество, что видел.
|
17;3;Доставка платная, дорогая доставка, не привезли вовремя.
|
||||||
18;5;Прекрасная сборка, превосходный товар, не уступает бренду.
|
18;5;Отслеживание работает, SMS оповещение, забрал сегодня.
|
||||||
19;4;Недорого, экономия, доставка вовремя. Хороший вариант.
|
19;2;Криво сделано, зазоры, непрочный. Худшее качество.
|
||||||
20;3;Цена выросла, наценка, но товар неплохой.
|
20;4;Не уступает бренду, класс, доставка бесплатная.
|
||||||
21;5;Забрал сам, пункт выдачи рядом, товар качественный.
|
21;1;Шлак, не соответствует заявленному, обдираловка.
|
||||||
22;4;Быстрый заказ, доставка день в день, вежливый курьер.
|
22;5;Долговечный, безупречный, превосходное качество. Огонь!
|
||||||
23;2;Криво сделано, зазоры, хрупкий. Одноразовый товар.
|
23;2;Потеряли заказ, не пришло уведомление, неправильный адрес.
|
||||||
24;5;Скидка, распродажа, низкая цена и отличное качество. Восторг!
|
24;4;Пункт выдачи рядом, доставили быстро, соблюдены сроки.
|
||||||
25;3;Не привезли вовремя, вернули на склад. Пришлось перезаказывать.
|
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;КРИЧУ ОТ ВОСТОРГА!!! ЛУЧШИЙ ТОВАР!!! ВСЕМ СОВЕТУЮ!!!
|
||||||
|
Can't render this file because it has a wrong number of fields in line 16.
|
57
main.py
57
main.py
@ -1,9 +1,8 @@
|
|||||||
# Система анализа и модерации отзывов на товары (E-Commerce Review Engine)
|
# Система анализа и модерации отзывов на товары (E-Commerce Review Engine)
|
||||||
|
|
||||||
#словари
|
|
||||||
|
|
||||||
def clean_text(text: str): # чистит текст отзыва от знаков препинания
|
def clean_text(text: str): # чистит текст отзыва от знаков препинания
|
||||||
black_list = ",?:();-+=*%"
|
black_list = ",?:();-+=*%><"
|
||||||
for i in range(len(black_list)):
|
for i in range(len(black_list)):
|
||||||
text = text.replace(black_list[i], '')
|
text = text.replace(black_list[i], '')
|
||||||
text = text.lower()
|
text = text.lower()
|
||||||
@ -30,7 +29,10 @@ def calculate_sentiment_score(text: str, positive_words: set, negative_words: se
|
|||||||
for i in negative_words:
|
for i in negative_words:
|
||||||
if i in text:
|
if i in text:
|
||||||
neg_count += 1
|
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
|
return sentiment
|
||||||
|
|
||||||
|
|
||||||
@ -70,7 +72,7 @@ def enrich_review(review: dict, keywords_dict: dict, positive_words: set, negati
|
|||||||
return upgrade_review
|
return upgrade_review
|
||||||
|
|
||||||
|
|
||||||
def filter_valid_reviews(reviews: list, spam_indicators): # фильтрует отзывы
|
def filter_valid_reviews(reviews: list, spam_indicators: list): # фильтрует отзывы
|
||||||
valid_base = []
|
valid_base = []
|
||||||
for i in range(len(reviews)):
|
for i in range(len(reviews)):
|
||||||
if validate_rating(reviews[i].get('rating')) and not (
|
if validate_rating(reviews[i].get('rating')) and not (
|
||||||
@ -79,7 +81,7 @@ def filter_valid_reviews(reviews: list, spam_indicators): # фильтрует
|
|||||||
return valid_base
|
return valid_base
|
||||||
|
|
||||||
|
|
||||||
def calculate_average_rating_by_topic(reviews: list):
|
def calculate_average_rating_by_topic(reviews: list): # {категория: срзнач(рейтинг)}
|
||||||
avg = dict()
|
avg = dict()
|
||||||
for i in reviews:
|
for i in reviews:
|
||||||
for j in i.get("topics"):
|
for j in i.get("topics"):
|
||||||
@ -87,26 +89,23 @@ def calculate_average_rating_by_topic(reviews: list):
|
|||||||
for i in avg:
|
for i in avg:
|
||||||
srz = {'summ': 0, 'lens': 0}
|
srz = {'summ': 0, 'lens': 0}
|
||||||
for j in range(len(reviews)):
|
for j in range(len(reviews)):
|
||||||
print(reviews[j])
|
|
||||||
if i in reviews[j].get('topics'):
|
if i in reviews[j].get('topics'):
|
||||||
print(i, reviews[j].get("rating"))
|
|
||||||
srz['summ'] += reviews[j].get("rating")
|
srz['summ'] += reviews[j].get("rating")
|
||||||
srz['lens'] += 1
|
srz['lens'] += 1
|
||||||
avg[i] = srz.get("summ") / srz.get("lens")
|
avg[i] = srz.get("summ") / srz.get("lens")
|
||||||
return avg
|
return avg
|
||||||
|
|
||||||
|
|
||||||
def detect_anomalies(reviews: list, sentiment_threshold: float = 0.5):
|
def detect_anomalies(reviews: list, sentiment_threshold: float = 0.5): # поиск аномалий
|
||||||
anomalys = []
|
anomalys = []
|
||||||
for i in reviews:
|
for i in reviews:
|
||||||
print(i)
|
|
||||||
if ((i['rating'] >= 4 and i['sentiment'] < -sentiment_threshold) or
|
if ((i['rating'] >= 4 and i['sentiment'] < -sentiment_threshold) or
|
||||||
(i['rating'] <= 2 and i['sentiment'] > sentiment_threshold)):
|
(i['rating'] <= 2 and i['sentiment'] > sentiment_threshold)):
|
||||||
anomalys.append(i['id'])
|
anomalys.append(i['id'])
|
||||||
return anomalys
|
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
|
spam_count = 0
|
||||||
for i in all_reviews:
|
for i in all_reviews:
|
||||||
if is_spam(i.get('text'), spam_indicators):
|
if is_spam(i.get('text'), spam_indicators):
|
||||||
@ -179,7 +178,7 @@ def main():
|
|||||||
"price": price_words
|
"price": price_words
|
||||||
}
|
}
|
||||||
|
|
||||||
print("\n======== Введите название файла с форматом .csv или используйте по умолчанию (Enter) ========")
|
print("\n======== Введите название файла с форматом .csv или используйте исходый файл (Enter) ========")
|
||||||
name_report = input()
|
name_report = input()
|
||||||
if not name_report:
|
if not name_report:
|
||||||
name_report = "data.csv"
|
name_report = "data.csv"
|
||||||
@ -189,15 +188,35 @@ def main():
|
|||||||
except:
|
except:
|
||||||
print("Файл отсутствует")
|
print("Файл отсутствует")
|
||||||
else:
|
else:
|
||||||
print("Содержимое файла:") #запись файла в список
|
database = []
|
||||||
review = list()
|
upgrade_database = []
|
||||||
for i in report:
|
for i in report:
|
||||||
i = i.replace("\n", '') #убираем отступы в концы строки
|
review = {}
|
||||||
review.append(i)
|
i = i[:-1]
|
||||||
report.close()
|
review['id'] = i[:i.index(';')]
|
||||||
print("id rating text")
|
i = i[i.index(';') + 1:]
|
||||||
for i in review:
|
review['rating'] = int(i[:i.index(';')])
|
||||||
print(i)
|
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:
|
else:
|
||||||
print("Неверный тип файла! "
|
print("Неверный тип файла! "
|
||||||
"\nНеобходимо выбрать файл с форматом .csv")
|
"\nНеобходимо выбрать файл с форматом .csv")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user