noranisa commited on
Commit
ababcd4
Β·
verified Β·
1 Parent(s): 4a5927a

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +191 -51
main.py CHANGED
@@ -1,74 +1,214 @@
1
- from flask import Flask, render_template, request, send_file
2
  from services.aggregator import collect_data
3
  from services.sentiment import predict
4
  from services.evaluation import evaluate_model
 
5
  from collections import Counter
6
  import pandas as pd
7
- from wordcloud import WordCloud
8
  import os
 
 
 
 
 
 
 
 
 
9
 
10
  app = Flask(__name__)
11
 
12
- @app.route('/', methods=['GET', 'POST'])
13
- def index():
14
- if request.method == 'POST':
15
- keyword = request.form.get('keyword')
16
- source = request.form.get('source', 'all')
17
-
18
- data_raw = collect_data(keyword, source)
19
-
20
- texts = [t for s, t in data_raw][:100]
21
- sources = [s for s, t in data_raw][:100]
22
-
23
- sentiments = predict(texts)
24
-
25
- counts = Counter(sentiments)
26
-
27
- # πŸ“Š per platform
28
- platform_counts = {}
29
- for src, sent in zip(sources, sentiments):
30
- if src not in platform_counts:
31
- platform_counts[src] = {"Positive":0,"Neutral":0,"Negative":0}
32
- platform_counts[src][sent] += 1
33
-
34
- # ☁️ wordcloud
35
- try:
36
- os.makedirs("static", exist_ok=True)
37
- wc = WordCloud(width=800, height=400).generate(" ".join(texts))
38
- wc.to_file("static/wordcloud.png")
39
- except:
40
- pass
41
-
42
- # πŸ“ CSV
43
- df = pd.DataFrame({
44
- "text": texts,
45
- "sentiment": sentiments,
46
- "source": sources
47
- })
48
- df.to_csv("static/result.csv", index=False)
49
 
50
- # πŸ“Š evaluasi
51
- eval_result = evaluate_model(predict)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
- data = list(zip(texts, sentiments, sources))
 
 
 
 
 
54
 
55
- return render_template(
56
- "result.html",
57
- data=data,
58
- counts=counts,
59
- platform_counts=platform_counts,
60
- eval_result=eval_result,
61
- keyword=keyword,
62
- source=source
63
- )
64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  return render_template("index.html")
66
 
67
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  @app.route('/download')
69
  def download():
70
  return send_file("static/result.csv", as_attachment=True)
71
 
72
 
 
 
 
73
  if __name__ == "__main__":
74
  app.run(host="0.0.0.0", port=7860)
 
1
+ from flask import Flask, render_template, request, jsonify, send_file
2
  from services.aggregator import collect_data
3
  from services.sentiment import predict
4
  from services.evaluation import evaluate_model
5
+
6
  from collections import Counter
7
  import pandas as pd
 
8
  import os
9
+ import re
10
+
11
+ from wordcloud import WordCloud
12
+ import matplotlib.pyplot as plt
13
+ import numpy as np
14
+
15
+ from sklearn.decomposition import LatentDirichletAllocation
16
+ from sklearn.feature_extraction.text import CountVectorizer
17
+
18
 
19
  app = Flask(__name__)
20
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
+ # =========================
23
+ # πŸ”₯ TOP WORDS
24
+ # =========================
25
+ def get_top_words(texts, top_n=10):
26
+ words = []
27
+
28
+ for t in texts:
29
+ t = re.sub(r'[^a-zA-Z\s]', '', t.lower())
30
+ words.extend(t.split())
31
+
32
+ common = Counter(words).most_common(top_n)
33
+ return [{"word": w, "count": c} for w, c in common]
34
+
35
+
36
+ # =========================
37
+ # πŸ”₯ HEATMAP
38
+ # =========================
39
+ def generate_heatmap(data):
40
+ sentiments = [d["sentiment"] for d in data]
41
+ sources = [d["source"] for d in data]
42
+
43
+ labels_sent = ["Positive", "Neutral", "Negative"]
44
+ labels_src = list(set(sources))
45
+
46
+ matrix = np.zeros((len(labels_src), len(labels_sent)))
47
+
48
+ for d in data:
49
+ i = labels_src.index(d["source"])
50
+ j = labels_sent.index(d["sentiment"])
51
+ matrix[i][j] += 1
52
+
53
+ plt.figure()
54
+ plt.imshow(matrix)
55
+
56
+ plt.xticks(range(len(labels_sent)), labels_sent)
57
+ plt.yticks(range(len(labels_src)), labels_src)
58
+
59
+ for i in range(len(labels_src)):
60
+ for j in range(len(labels_sent)):
61
+ plt.text(j, i, int(matrix[i][j]), ha='center')
62
+
63
+ plt.title("Heatmap Sentimen")
64
+ plt.colorbar()
65
+
66
+ os.makedirs("static", exist_ok=True)
67
+ plt.savefig("static/heatmap.png")
68
+ plt.close()
69
+
70
 
71
+ # =========================
72
+ # πŸ”₯ TOPIC MODELING (LDA)
73
+ # =========================
74
+ def get_topics(texts, n_topics=3):
75
+ vectorizer = CountVectorizer(stop_words='english')
76
+ X = vectorizer.fit_transform(texts)
77
 
78
+ lda = LatentDirichletAllocation(n_components=n_topics, random_state=42)
79
+ lda.fit(X)
 
 
 
 
 
 
 
80
 
81
+ words = vectorizer.get_feature_names_out()
82
+
83
+ topics = []
84
+ for topic in lda.components_:
85
+ top_words = [words[i] for i in topic.argsort()[-5:]]
86
+ topics.append(top_words)
87
+
88
+ return topics
89
+
90
+
91
+ # =========================
92
+ # πŸ€– AI INSIGHT
93
+ # =========================
94
+ def generate_insight(data, topics):
95
+ sentiments = [d["sentiment"] for d in data]
96
+ total = len(sentiments)
97
+
98
+ pos = sentiments.count("Positive")
99
+ neg = sentiments.count("Negative")
100
+ neu = sentiments.count("Neutral")
101
+
102
+ insight = f"""
103
+ Total data: {total}
104
+
105
+ Positive: {pos}
106
+ Negative: {neg}
107
+ Neutral: {neu}
108
+
109
+ Mayoritas opini adalah {"positif" if pos > neg else "negatif"}.
110
+
111
+ Topik utama:
112
+ """
113
+
114
+ for i, t in enumerate(topics):
115
+ insight += f"\nTopik {i+1}: {', '.join(t)}"
116
+
117
+ return insight
118
+
119
+
120
+ # =========================
121
+ # 🌐 HALAMAN UTAMA
122
+ # =========================
123
+ @app.route('/')
124
+ def home():
125
  return render_template("index.html")
126
 
127
 
128
+ # =========================
129
+ # πŸš€ ANALYZE API (AJAX)
130
+ # =========================
131
+ @app.route('/analyze', methods=['POST'])
132
+ def analyze():
133
+ keyword = request.json.get('keyword')
134
+ source = request.json.get('source', 'all')
135
+
136
+ # ambil data
137
+ data_raw = collect_data(keyword, source)
138
+
139
+ texts = [t for s, t in data_raw][:100]
140
+ sources = [s for s, t in data_raw][:100]
141
+
142
+ sentiments = predict(texts)
143
+
144
+ result = []
145
+ for t, s, src in zip(texts, sentiments, sources):
146
+ result.append({
147
+ "text": t,
148
+ "sentiment": s,
149
+ "source": src
150
+ })
151
+
152
+ # =====================
153
+ # πŸ”₯ WORDCLOUD
154
+ # =====================
155
+ try:
156
+ os.makedirs("static", exist_ok=True)
157
+ wc = WordCloud(width=800, height=400).generate(" ".join(texts))
158
+ wc.to_file("static/wordcloud.png")
159
+ except:
160
+ pass
161
+
162
+ # =====================
163
+ # πŸ“ CSV EXPORT
164
+ # =====================
165
+ df = pd.DataFrame(result)
166
+ df.to_csv("static/result.csv", index=False)
167
+
168
+ # =====================
169
+ # πŸ“Š HEATMAP
170
+ # =====================
171
+ generate_heatmap(result)
172
+
173
+ # =====================
174
+ # πŸ”₯ TOP WORDS
175
+ # =====================
176
+ top_words = get_top_words(texts)
177
+
178
+ # =====================
179
+ # 🧠 TOPIC MODELING
180
+ # =====================
181
+ topics = get_topics(texts)
182
+
183
+ # =====================
184
+ # πŸ€– AI INSIGHT
185
+ # =====================
186
+ insight = generate_insight(result, topics)
187
+
188
+ # =====================
189
+ # πŸ“Š EVALUASI MODEL
190
+ # =====================
191
+ eval_result = evaluate_model(predict)
192
+
193
+ return jsonify({
194
+ "data": result,
195
+ "top_words": top_words,
196
+ "topics": topics,
197
+ "insight": insight,
198
+ "eval": eval_result
199
+ })
200
+
201
+
202
+ # =========================
203
+ # πŸ“₯ DOWNLOAD CSV
204
+ # =========================
205
  @app.route('/download')
206
  def download():
207
  return send_file("static/result.csv", as_attachment=True)
208
 
209
 
210
+ # =========================
211
+ # ▢️ RUN
212
+ # =========================
213
  if __name__ == "__main__":
214
  app.run(host="0.0.0.0", port=7860)