import streamlit as st import pandas as pd import sqlite3 import plotly.express as px from wordcloud import WordCloud import matplotlib.pyplot as plt from analyzer import analyze_sentiment, calculate_priority_score, classify_theme, get_lemmas # Конфигурация страницы st.set_page_config(page_title="Insta Analytics Search", layout="wide", initial_sidebar_state="collapsed") # Стили st.markdown(""" """, unsafe_allow_html=True) @st.cache_data def load_data(): try: conn = sqlite3.connect('instagram_data.db') c = pd.read_sql("SELECT * FROM comments", conn) conn.close() c['comment_date'] = pd.to_datetime(c['comment_date'], errors='coerce') return c except: return pd.DataFrame() comments_all = load_data() st.markdown("

Insight Search

", unsafe_allow_html=True) if 'search_results' not in st.session_state: st.session_state['search_results'] = pd.DataFrame() col_spacer1, col_search, col_spacer2 = st.columns([1, 4, 1]) with col_search: search_query = st.text_input("Поиск", placeholder="Введите URL, слова, никнейм или текст...", label_visibility="collapsed") mode = st.radio("Режим", ["🔑 По словам", "🔗 По URL поста", "👤 По автору (Нику)", "✍️ Один текст"], label_visibility="collapsed", horizontal=True) analyze_clicked = st.button("Анализировать", use_container_width=True) st.divider() if analyze_clicked: if not search_query.strip(): st.warning("Пожалуйста, введите запрос!") else: term = search_query.strip().lower() res = pd.DataFrame() if mode == "🔑 По словам": keys = [k.strip().lower() for k in search_query.split(',')] res = comments_all[comments_all['comment_text'].apply(lambda x: any(k in str(x).lower() for k in keys))].copy() elif mode == "🔗 По URL поста": res = comments_all[comments_all['post_url'].astype(str).str.contains(term, na=False, case=False)].copy() elif mode == "👤 По автору (Нику)": res = comments_all[comments_all['comment_author'].astype(str).str.lower().str.contains(term, na=False)].copy() elif mode == "✍️ Один текст": res = pd.DataFrame([{'comment_text': search_query, 'comment_author': 'Вы', 'comment_date': pd.Timestamp.now()}]) if res.empty: st.error("По вашему запросу ничего не найдено.") st.session_state['search_results'] = pd.DataFrame() else: with st.spinner('ИИ анализирует данные...'): res['sentiment'] = analyze_sentiment(res['comment_text'].tolist()) res['theme'] = res['comment_text'].apply(classify_theme) res['priority'] = res.apply(calculate_priority_score, axis=1) st.session_state['search_results'] = res # ОТОБРАЖЕНИЕ if not st.session_state['search_results'].empty: df_result = st.session_state['search_results'] st.markdown("

Фильтр комментариев:

", unsafe_allow_html=True) sentiment_filter = st.radio("Тональность", ["Все", "🟢 Позитив", "🔴 Негатив", "⚪ Нейтрально"], horizontal=True, label_visibility="collapsed") df_filtered = df_result.copy() if sentiment_filter == "🟢 Позитив": df_filtered = df_filtered[df_filtered['sentiment'] == 'Позитив'] elif sentiment_filter == "🔴 Негатив": df_filtered = df_filtered[df_filtered['sentiment'] == 'Негатив'] elif sentiment_filter == "⚪ Нейтрально": df_filtered = df_filtered[df_filtered['sentiment'] == 'Нейтрально'] st.markdown(f"## Результаты ({len(df_filtered)} шт.)") # Метрики c1, c2, c3, c4 = st.columns(4) with c1: st.markdown(f'
Всего{len(df_filtered)} шт.
', unsafe_allow_html=True) with c2: val = df_filtered["sentiment"].mode()[0] if not df_filtered.empty else "—" st.markdown(f'
Настрой{val}
', unsafe_allow_html=True) with c3: val = df_filtered["theme"].mode()[0] if not df_filtered.empty else "—" st.markdown(f'
Тема{val}
', unsafe_allow_html=True) with c4: val = df_filtered["priority"].mean() if not df_filtered.empty else 0 st.markdown(f'
Приоритет{val:.1f}
', unsafe_allow_html=True) # Графики g1, g2 = st.columns(2) with g1: fig = px.pie(df_filtered, names='sentiment', color='sentiment', hole=0.3, color_discrete_map={'Позитив':'#82ca9d', 'Негатив':'#E83E8C', 'Нейтрально':'#8884d8'}) fig.update_layout(paper_bgcolor="rgba(0,0,0,0)", font_color="white") st.plotly_chart(fig, use_container_width=True) with g2: if len(df_filtered) > 0: txt = " ".join(df_filtered['comment_text'].astype(str)) wc = WordCloud(width=800, height=400, background_color=None, mode="RGBA").generate(txt) fig_wc, ax = plt.subplots(); ax.imshow(wc); ax.axis("off") fig_wc.patch.set_alpha(0) st.pyplot(fig_wc) # Таблица st.markdown("### 📋 Детализация комментариев") df_display = df_filtered.copy() df_display['comment_date'] = pd.to_datetime(df_display['comment_date']).dt.strftime('%d.%m.%Y %H:%M') df_display['Профиль'] = df_display['comment_author'].apply(lambda x: f"https://www.instagram.com/{x}/") df_display = df_display[['priority', 'sentiment', 'theme', 'comment_text', 'comment_author', 'Профиль', 'comment_date']] df_display.columns = ['Приоритет', 'Тональность', 'Тема', 'Текст', 'Автор', 'Instagram', 'Дата'] st.dataframe(df_display.sort_values(by='Приоритет', ascending=False), use_container_width=True, hide_index=True, column_config={"Instagram": st.column_config.LinkColumn("Instagram")}) st.download_button("📥 Скачать отчет (CSV)", df_display.to_csv(index=False).encode('utf-8-sig'), "report.csv", "text/csv") # ИНСАЙТЫ (ИСПРАВЛЕНО) st.markdown("---") st.markdown("### 💡 Инсайты разведки") # Проверяем негатив во ВСЕЙ найденной по запросу выборке (df_result) neg_data = df_result[df_result['sentiment'] == 'Негатив'] if not neg_data.empty: count_bad = len(neg_data) bad_topic = neg_data['theme'].mode()[0] st.error(f"⚠️ **Внимание:** В результатах поиска обнаружено **{count_bad}** негативных сообщений! Основная проблемная тема: **{bad_topic}**. Требуется анализ рисков.") else: st.success("✅ **Положительный инсайт:** В данной выборке не обнаружено негативных проявлений. Аудитория лояльна.")