boompack commited on
Commit
60e12de
1 Parent(s): f6a656f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +259 -5
app.py CHANGED
@@ -1,7 +1,261 @@
1
- import gradio as gr
 
 
 
 
 
 
2
 
3
- def greet(name):
4
- return "Hello " + name + "!!"
 
 
 
 
5
 
6
- demo = gr.Interface(fn=greet, inputs="text", outputs="text")
7
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from dataclasses import dataclass, field
2
+ from typing import List, Optional, Dict, Any
3
+ import re
4
+ from datetime import datetime
5
+ import logging
6
+ import html
7
+ from uuid import uuid4
8
 
9
+ # Настройка логирования
10
+ logging.basicConfig(
11
+ level=logging.INFO,
12
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
13
+ )
14
+ logger = logging.getLogger(__name__)
15
 
16
+ @dataclass
17
+ class Comment:
18
+ """
19
+ Представляет комментарий Instagram со всеми метаданными и вложенной структурой.
20
+
21
+ Attributes:
22
+ id: Уникальный идентификатор комментария
23
+ username: Имя пользователя
24
+ time: Временная метка
25
+ content: Текст комментария
26
+ likes: Количество лайков
27
+ level: Уровень вложенности
28
+ parent_id: ID родительского комментария
29
+ replies: Список ответов
30
+ is_verified: Верифицированный аккаунт
31
+ mentions: Упоминания пользователей
32
+ hashtags: Хэштеги
33
+ is_deleted: Флаг удаленного комментария
34
+ """
35
+ id: str = field(default_factory=lambda: str(uuid4()))
36
+ username: str = ""
37
+ time: str = ""
38
+ content: str = ""
39
+ likes: int = 0
40
+ level: int = 0
41
+ parent_id: Optional[str] = None
42
+ replies: List['Comment'] = field(default_factory=list)
43
+ is_verified: bool = False
44
+ mentions: List[str] = field(default_factory=list)
45
+ hashtags: List[str] = field(default_factory=list)
46
+ is_deleted: bool = False
47
+
48
+ def __post_init__(self):
49
+ """Валидация после инициализации"""
50
+ if len(self.content) > 2200:
51
+ logger.warning(f"Comment content exceeds 2200 characters for user {self.username}")
52
+ self.content = self.content[:2200] + "..."
53
+
54
+ class InstagramCommentAnalyzer:
55
+ """
56
+ Основной класс для обработки и анализа комментариев Instagram.
57
+ Обрабатывает парсинг комментариев, вложенную структуру и особые случаи.
58
+ """
59
+
60
+ # Регулярное выражение для извлечения комментариев
61
+ COMMENT_PATTERN = r'''
62
+ (?P<username>[\w.-]+)\s+
63
+ (?P<time>\d+\s+нед\.)
64
+ (?P<content>.*?)
65
+ (?:Отметки\s*"Нравится":\s*(?P<likes>\d+))?
66
+ (?:Ответить)?(?:Показать\sперевод)?(?:Нравится)?
67
+ '''
68
+
69
+ def __init__(self, max_depth: int = 10, max_comment_length: int = 2200):
70
+ """
71
+ Инициализация анализатора с настраиваемыми параметрами.
72
+
73
+ Args:
74
+ max_depth: Максимальная глубина вложенности комментариев
75
+ max_comment_length: Максимальная длина комментария
76
+ """
77
+ self.max_depth = max_depth
78
+ self.max_comment_length = max_comment_length
79
+ self.pattern = re.compile(self.COMMENT_PATTERN, re.VERBOSE | re.DOTALL)
80
+ self.comments: List[Comment] = []
81
+ self.stats: Dict[str, int] = {
82
+ 'total_comments': 0,
83
+ 'deleted_comments': 0,
84
+ 'empty_comments': 0,
85
+ 'max_depth_reached': 0,
86
+ 'truncated_comments': 0,
87
+ 'processed_mentions': 0,
88
+ 'processed_hashtags': 0
89
+ }
90
+
91
+ def normalize_text(self, text: str) -> str:
92
+ """
93
+ Нормализация входного текста.
94
+
95
+ Args:
96
+ text: Исходный текст
97
+
98
+ Returns:
99
+ Нормализованный текст
100
+ """
101
+ # Декодирование HTML-сущностей
102
+ text = html.unescape(text)
103
+ # Нормализация пробелов
104
+ text = ' '.join(text.split())
105
+ # Удаление невидимых символов
106
+ text = re.sub(r'[\u200b\ufeff\u200c]', '', text)
107
+ return text
108
+
109
+ def extract_metadata(self, comment: Comment) -> None:
110
+ """
111
+ Извлечение метаданных из комментария.
112
+
113
+ Args:
114
+ comment: Объект комментария
115
+ """
116
+ # Извлечение @упоминаний
117
+ comment.mentions = re.findall(r'@(\w+)', comment.content)
118
+ self.stats['processed_mentions'] += len(comment.mentions)
119
+
120
+ # Извлечение #хэштегов
121
+ comment.hashtags = re.findall(r'#(\w+)', comment.content)
122
+ self.stats['processed_hashtags'] += len(comment.hashtags)
123
+
124
+ # Проверка верификации
125
+ comment.is_verified = bool(re.search(r'✓|Подтвержденный', comment.username))
126
+
127
+ def process_comment(self, text: str, parent_id: Optional[str] = None, level: int = 0) -> Optional[Comment]:
128
+ """
129
+ Обработка отдельного комментария.
130
+
131
+ Args:
132
+ text: Текст комментария
133
+ parent_id: ID родительского комментария
134
+ level: Уровень вложенности
135
+
136
+ Returns:
137
+ Обработанный объект Comment или None
138
+ """
139
+ if level > self.max_depth:
140
+ logger.warning(f"Maximum depth {self.max_depth} exceeded")
141
+ self.stats['max_depth_reached'] += 1
142
+ return None
143
+
144
+ if not text.strip():
145
+ self.stats['empty_comments'] += 1
146
+ return None
147
+
148
+ try:
149
+ match = self.pattern.match(text)
150
+ if not match:
151
+ raise ValueError(f"Could not parse comment: {text[:100]}...")
152
+
153
+ data = match.groupdict()
154
+ comment = Comment(
155
+ username=data['username'],
156
+ time=data['time'],
157
+ content=data['content'].strip(),
158
+ likes=int(data['likes'] or 0),
159
+ level=level,
160
+ parent_id=parent_id
161
+ )
162
+
163
+ if len(comment.content) > self.max_comment_length:
164
+ self.stats['truncated_comments'] += 1
165
+ comment.content = comment.content[:self.max_comment_length] + "..."
166
+
167
+ self.extract_metadata(comment)
168
+ self.stats['total_comments'] += 1
169
+ return comment
170
+
171
+ except Exception as e:
172
+ logger.error(f"Error processing comment: {str(e)}")
173
+ comment = Comment(
174
+ username="[damaged]",
175
+ time="",
176
+ content="[Поврежденные данные]",
177
+ is_deleted=True
178
+ )
179
+ self.stats['deleted_comments'] += 1
180
+ return comment
181
+
182
+ def format_comment(self, comment: Comment, index: int) -> str:
183
+ """
184
+ Форматирование комментария для вывода.
185
+
186
+ Args:
187
+ comment: Объект комментария
188
+ index: Номер комментария
189
+
190
+ Returns:
191
+ Отформатированная строка комментария
192
+ """
193
+ if comment.is_deleted:
194
+ return f'{index}. "[УДАЛЕНО]" "" "" "Нравится 0"'
195
+
196
+ return (
197
+ f'{index}. "{comment.username}" "{comment.time}" '
198
+ f'"{comment.content}" "Нравится {comment.likes}"'
199
+ )
200
+
201
+ def process_comments(self, text: str) -> List[str]:
202
+ """
203
+ Обработка всех комментариев в тексте.
204
+
205
+ Args:
206
+ text: Исходный текст с комментариями
207
+
208
+ Returns:
209
+ Список отформатированных комментариев
210
+ """
211
+ # Сброс статистики
212
+ self.stats = {key: 0 for key in self.stats}
213
+
214
+ # Нормализация текста
215
+ text = self.normalize_text(text)
216
+
217
+ # Разделение на отдельные комментарии
218
+ raw_comments = text.split('ОтветитьНравится')
219
+
220
+ # Обработка комментариев
221
+ formatted_comments = []
222
+ for i, raw_comment in enumerate(raw_comments, 1):
223
+ if not raw_comment.strip():
224
+ continue
225
+
226
+ comment = self.process_comment(raw_comment)
227
+ if comment:
228
+ formatted_comments.append(self.format_comment(comment, i))
229
+
230
+ return formatted_comments
231
+
232
+ def main():
233
+ """
234
+ Пример использования анализатора.
235
+ """
236
+ # Пример входного текста
237
+ input_text = """
238
+ 0001.minakov 53 нед.А что такое для,Вас Василина,волшебство?Отметки "Нравится": 3ОтветитьНравится
239
+ aliyllmn 54 нед.seni seviyorum:)Отметки "Нравится": 2ОтветитьПоказать переводНравится
240
+ """
241
+
242
+ # Создание экземпляра анализатора
243
+ analyzer = InstagramCommentAnalyzer(max_depth=10)
244
+
245
+ # Обработка комментариев
246
+ results = analyzer.process_comments(input_text)
247
+
248
+ # Вывод результатов
249
+ print("\nОбработанные комментарии:")
250
+ print("-" * 50)
251
+ for result in results:
252
+ print(result)
253
+
254
+ # Вывод статистики
255
+ print("\nСтатистика обработки:")
256
+ print("-" * 50)
257
+ for key, value in analyzer.stats.items():
258
+ print(f"{key}: {value}")
259
+
260
+ if __name__ == "__main__":
261
+ main()