295 lines
5.9 KiB
Python
295 lines
5.9 KiB
Python
from flask import Flask, request, jsonify
|
|
import pickle
|
|
import re
|
|
import subprocess
|
|
|
|
import nltk
|
|
from nltk.corpus import stopwords
|
|
from Sastrawi.Stemmer.StemmerFactory import StemmerFactory
|
|
|
|
# =========================
|
|
# LOAD MODEL
|
|
# =========================
|
|
|
|
with open('model/model_sentiment.pkl', 'rb') as file:
|
|
model = pickle.load(file)
|
|
|
|
with open('model/tfidf_vectorizer.pkl', 'rb') as file:
|
|
tfidf = pickle.load(file)
|
|
|
|
# =========================
|
|
# PREPROCESSING
|
|
# =========================
|
|
|
|
nltk.download('stopwords')
|
|
|
|
stop_words = set(stopwords.words('indonesian'))
|
|
|
|
factory = StemmerFactory()
|
|
stemmer = factory.create_stemmer()
|
|
|
|
def preprocess_text(text):
|
|
|
|
text = str(text).lower()
|
|
|
|
# normalisasi huruf berulang
|
|
text = re.sub(r'(.)\1+', r'\1', text)
|
|
|
|
# hapus angka
|
|
text = re.sub(r'\d+', '', text)
|
|
|
|
# hapus simbol
|
|
text = re.sub(r'[^\w\s]', '', text)
|
|
|
|
# hapus spasi berlebih
|
|
text = re.sub(r'\s+', ' ', text).strip()
|
|
|
|
# tokenizing
|
|
words = text.split()
|
|
|
|
# slang normalization
|
|
slang_dict = {
|
|
'gk': 'tidak',
|
|
'ga': 'tidak',
|
|
'nggak': 'tidak',
|
|
'bgt': 'banget',
|
|
'bgtt': 'banget',
|
|
'bangett': 'banget',
|
|
'bgus': 'bagus',
|
|
'baguss': 'bagus',
|
|
'tmpt': 'tempat',
|
|
'jln': 'jalan',
|
|
'sy': 'saya',
|
|
'yg': 'yang',
|
|
'udh': 'sudah'
|
|
}
|
|
|
|
words = [
|
|
slang_dict[word] if word in slang_dict else word
|
|
for word in words
|
|
]
|
|
|
|
# stopword removal
|
|
words = [
|
|
word for word in words
|
|
if word not in stop_words
|
|
]
|
|
|
|
# stemming
|
|
words = [stemmer.stem(word) for word in words]
|
|
|
|
return ' '.join(words)
|
|
|
|
# lowercase
|
|
text = text.lower()
|
|
|
|
# hapus angka
|
|
text = re.sub(r'\d+', '', text)
|
|
|
|
# hapus simbol
|
|
text = re.sub(r'[^\w\s]', '', text)
|
|
|
|
# hapus spasi berlebih
|
|
text = re.sub(r'\s+', ' ', text).strip()
|
|
|
|
# tokenizing
|
|
words = text.split()
|
|
|
|
# stopword removal
|
|
words = [word for word in words if word not in stop_words]
|
|
|
|
# stemming
|
|
words = [stemmer.stem(word) for word in words]
|
|
|
|
return ' '.join(words)
|
|
|
|
# lowercase
|
|
text = text.lower()
|
|
|
|
# hapus angka
|
|
text = re.sub(r'\d+', '', text)
|
|
|
|
# hapus simbol
|
|
text = re.sub(r'[^\w\s]', '', text)
|
|
|
|
# hapus spasi berlebih
|
|
text = re.sub(r'\s+', ' ', text).strip()
|
|
|
|
# tokenizing
|
|
words = text.split()
|
|
|
|
# stopword removal
|
|
words = [word for word in words if word not in stop_words]
|
|
|
|
# stemming
|
|
words = [stemmer.stem(word) for word in words]
|
|
|
|
return ' '.join(words)
|
|
|
|
# =========================
|
|
# FLASK APP
|
|
# =========================
|
|
|
|
app = Flask(__name__)
|
|
@app.route('/scraping', methods=['POST'])
|
|
def scraping():
|
|
|
|
try:
|
|
|
|
data = request.get_json()
|
|
|
|
wisata = data.get('wisata', '')
|
|
|
|
result = subprocess.run(
|
|
['python', 'scraping_pipeline.py', wisata],
|
|
capture_output=True,
|
|
text=True
|
|
)
|
|
|
|
if result.returncode != 0:
|
|
|
|
return jsonify({
|
|
'status': 'error',
|
|
'error': result.stderr
|
|
}), 500
|
|
|
|
return jsonify({
|
|
'status': 'success',
|
|
'message': result.stdout
|
|
})
|
|
|
|
except Exception as e:
|
|
|
|
return jsonify({
|
|
'status': 'error',
|
|
'error': str(e)
|
|
}), 500
|
|
|
|
try:
|
|
|
|
result = subprocess.run(
|
|
['python', 'scraping_pipeline.py'],
|
|
capture_output=True,
|
|
text=True
|
|
)
|
|
|
|
if result.returncode != 0:
|
|
|
|
return jsonify({
|
|
'status': 'error',
|
|
'error': result.stderr
|
|
}), 500
|
|
|
|
return jsonify({
|
|
'status': 'success',
|
|
'message': result.stdout
|
|
})
|
|
|
|
except Exception as e:
|
|
|
|
return jsonify({
|
|
'status': 'error',
|
|
'error': str(e)
|
|
}), 500
|
|
|
|
# ======================================
|
|
# PREDICT 1 REVIEW
|
|
# ======================================
|
|
|
|
@app.route('/predict', methods=['POST'])
|
|
def predict():
|
|
|
|
data = request.get_json()
|
|
|
|
review = data['review']
|
|
|
|
# preprocessing
|
|
clean_review = preprocess_text(review)
|
|
|
|
# tfidf transform
|
|
vector = tfidf.transform([clean_review])
|
|
|
|
# prediksi
|
|
prediction = model.predict(vector)[0]
|
|
|
|
# probabilitas
|
|
probability = model.predict_proba(vector).max()
|
|
|
|
return jsonify({
|
|
'review': review,
|
|
'clean_review': clean_review,
|
|
'sentiment': prediction,
|
|
'probability': round(float(probability), 4)
|
|
})
|
|
|
|
# ======================================
|
|
# PROSES ANALISIS SEMUA DATA
|
|
# ======================================
|
|
|
|
@app.route('/proses-analisis', methods=['POST'])
|
|
def proses_analisis():
|
|
|
|
try:
|
|
|
|
data = request.get_json()
|
|
|
|
periode_id = str(data.get('periode_id'))
|
|
|
|
result = subprocess.run(
|
|
['python', 'analisis.py', periode_id],
|
|
capture_output=True,
|
|
text=True
|
|
)
|
|
|
|
if result.returncode != 0:
|
|
|
|
return jsonify({
|
|
'status': 'error',
|
|
'error': result.stderr
|
|
}), 500
|
|
|
|
return jsonify({
|
|
'status': 'success',
|
|
'message': result.stdout
|
|
})
|
|
|
|
except Exception as e:
|
|
|
|
return jsonify({
|
|
'status': 'error',
|
|
'error': str(e)
|
|
}), 500
|
|
|
|
try:
|
|
|
|
result = subprocess.run(
|
|
['python', 'analisis.py'],
|
|
capture_output=True,
|
|
text=True
|
|
)
|
|
|
|
if result.returncode != 0:
|
|
|
|
return jsonify({
|
|
'status': 'error',
|
|
'error': result.stderr
|
|
}), 500
|
|
|
|
return jsonify({
|
|
'status': 'success',
|
|
'message': result.stdout
|
|
})
|
|
|
|
except Exception as e:
|
|
|
|
return jsonify({
|
|
'status': 'error',
|
|
'error': str(e)
|
|
}), 500
|
|
|
|
# =========================
|
|
# RUN APP
|
|
# =========================
|
|
|
|
if __name__ == '__main__':
|
|
app.run(debug=False) |