revisi tampilan

beberapa tampilan ada yang dihapus
This commit is contained in:
adistya13 2026-05-19 19:30:36 +07:00
parent 12855d58b7
commit 8288fd99bd
6 changed files with 682 additions and 1325 deletions

View File

@ -1,3 +1,17 @@
"""
preprocessing_page.py
=====================
Halaman Bersihkan Data NLP Pipeline 6 Tahap.
PIPELINE 6 TAHAP (selaras dengan sentiment_service.py):
1. Case Folding ubah semua huruf jadi lowercase
2. Cleaning hapus URL, mention, hashtag, angka, emoji, tanda baca
3. Normalisasi singkatan/slang kata baku
4. Tokenizing pecah kalimat list token
5. Stopword Removal hapus kata umum; JAGA kata sentimen penting
6. Stemming bentuk dasar kata via Sastrawi ECS
"""
import streamlit as st import streamlit as st
import pandas as pd import pandas as pd
import os import os
@ -78,69 +92,64 @@ def _sync_dynamic_period():
# ═══════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════
# PREPROCESSING PIPELINE — 6 TAHAP # PREPROCESSING PIPELINE — 6 TAHAP
# PENTING: Pipeline ini harus IDENTIK dengan sentiment_service.py
# agar token yang dihasilkan konsisten dengan training model.
# #
# Urutan tahap: # URUTAN:
# 1. Cleaning — hapus noise (URL, mention, hashtag, angka, # 1. Case Folding → lowercase dulu sebelum cleaning
# tanda baca, emoji, karakter non-latin) # 2. Cleaning → hapus noise setelah lowercase
# 2. Case Folding — ubah semua huruf jadi huruf kecil (lowercase) # 3. Normalisasi → singkatan/slang → kata baku
# 3. Normalisasi — ganti singkatan/slang → kata baku # 4. Tokenizing → split menjadi list token
# 4. Tokenizing — pecah kalimat menjadi list token/kata # 5. Stopword Removal → buang kata umum, jaga kata sentimen
# 5. Stopword Removal — buang kata umum yang tidak bermakna # 6. Stemming → bentuk dasar via Sastrawi ECS
# 6. Stemming — bentuk dasar kata via Sastrawi
#
# Catatan desain:
# • Case Folding dilakukan SETELAH cleaning awal supaya regex pendeteksi
# emoji/karakter khusus tetap bekerja dengan baik, lalu baru dilanjut
# ke langkah selanjutnya yang semuanya butuh lowercase.
# • Tokenizing menghasilkan list; untuk keperluan tabel & analisis kata
# hasil tokenizing dikembalikan sebagai string (join spasi) agar mudah
# disimpan dan diproses step berikutnya.
# • Normalisasi berjalan pada level token sehingga pencocokan kata tepat
# (tidak partial match di tengah kata).
# ═══════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════
KATA_SENTIMEN_PENTING = {
# Negasi
"tidak", "bukan", "jangan", "kurang", "belum", "tanpa",
# Positif
"keren", "bagus", "mantap", "setuju", "dukung", "mendukung",
"andal", "handal", "gercep", "bangga", "senang", "suka",
"baik", "benar", "tepat", "oke",
"sejahtera", "berkembang", "maju", "inovatif",
"tegas", "sigap", "tanggap", "adil", "bijak", "bermanfaat",
"untung", "berhasil", "sukses", "solusi", "manfaat",
"berguna", "membantu", "bantu", "pro", "lanjut",
"sangat", "banget", "sekali", "paling", "amat", "luar", "biasa",
# Negatif
"kecewa", "buruk", "jelek", "parah", "gagal", "hancur",
"rusak", "bohong", "tipu", "korupsi",
# Emosi
"marah", "sedih", "khawatir",
}
def _load_stopwords(): def _load_stopwords():
"""
Load stopword dari file indonesian-stopwords-complete.txt.
Kata-kata negasi penting (tidak, bukan, jangan, kurang, belum)
dikeluarkan dari stopword agar tidak hilang saat filtering
keberadaannya krusial untuk analisis sentimen.
"""
stopword_file = "indonesian-stopwords-complete.txt" stopword_file = "indonesian-stopwords-complete.txt"
base = set() base = set()
try: try:
with open(stopword_file, "r", encoding="utf-8") as f: with open(stopword_file, "r", encoding="utf-8") as f:
base = set(f.read().splitlines()) base = set(f.read().splitlines())
# Pertahankan kata negasi — penting untuk sentimen
for kata in ["tidak", "bukan", "jangan", "kurang", "belum", "tanpa"]:
base.discard(kata)
except FileNotFoundError: except FileNotFoundError:
# Fallback minimal jika file tidak ada
base = { base = {
"yang", "dan", "di", "ke", "dari", "ini", "itu", "yang", "dan", "di", "ke", "dari", "ini", "itu",
"dengan", "untuk", "pada", "adalah", "oleh", "ada", "dengan", "untuk", "pada", "adalah", "oleh", "ada",
"ya", "akan", "atau", "juga", "sama", "karena", "ya", "akan", "atau", "juga", "sama", "karena",
"jika", "sudah", "telah", "jika", "sudah", "telah",
} }
# Tambahan stopword domain-spesifik & informal for kata in KATA_SENTIMEN_PENTING:
base.discard(kata)
base.update({ base.update({
"rt", "amp", "https", "http", "co", "t", "rt", "amp", "https", "http", "co", "t",
"wkwk", "wkwkwk", "haha", "hehe", "xixi", "wkwk", "wkwkwk", "haha", "hehe", "xixi",
"yg", "dgn", "utk", "dr", "krn", "tp", "jd", "sdh", "yg", "dgn", "utk", "dr", "krn", "tp", "jd", "sdh",
"aja", "doang", "banget", "bgt", "nih", "sih", "dong", "deh", "aja", "doang", "nih", "sih", "dong", "deh",
"loh", "lah", "tuh", "dong", "kak", "gan", "loh", "lah", "tuh", "kak", "gan",
}) })
return base return base
def _load_stemmer(): def _load_stemmer():
"""
Load stemmer Sastrawi jika tersedia.
Sastrawi adalah library stemming Bahasa Indonesia berbasis algoritma
Enhanced Confix Stripping (ECS) yang mampu menghapus awalan dan akhiran
secara bertahap (berlari lari, makanan makan, dst).
Mengembalikan None jika Sastrawi tidak terinstall stemming di-skip.
"""
try: try:
from Sastrawi.Stemmer.StemmerFactory import StemmerFactory from Sastrawi.Stemmer.StemmerFactory import StemmerFactory
return StemmerFactory().create_stemmer() return StemmerFactory().create_stemmer()
@ -148,28 +157,54 @@ def _load_stemmer():
return None return None
# Kamus normalisasi: kata informal/singkatan → kata baku
# Mencakup: singkatan SMS/chat, kata gaul, singkatan domain crawling
NORMALISASI = { NORMALISASI = {
# Negasi # Negasi
"gk": "tidak", "ga": "tidak", "gak": "tidak", "gk": "tidak", "ga": "tidak", "gak": "tidak",
"nggak": "tidak", "ngga": "tidak", "tdk": "tidak", "nggak": "tidak", "ngga": "tidak", "tdk": "tidak",
"tak": "tidak", "enggak": "tidak", "tak": "tidak", "enggak": "tidak", "engga": "tidak",
# Kata ganti & preposisi "kagak": "tidak", "kaga": "tidak", "ndak": "tidak",
"gkk": "tidak", "ngak": "tidak",
# Kata ganti
"yg": "yang", "dgn": "dengan", "utk": "untuk", "yg": "yang", "dgn": "dengan", "utk": "untuk",
"org": "orang", "krn": "karena", "dr": "dari", "org": "orang", "krn": "karena", "dr": "dari",
"sm": "sama", "pd": "pada", "dlm": "dalam", "sm": "sama", "pd": "pada", "dlm": "dalam",
# Verba & adjektiva "bwt": "buat", "trm": "terima",
# Verba
"tp": "tapi", "tpi": "tapi", "jd": "jadi", "tp": "tapi", "tpi": "tapi", "jd": "jadi",
"sdh": "sudah", "blm": "belum", "emg": "memang", "sdh": "sudah", "blm": "belum", "emg": "memang",
"emang": "memang", "gimana": "bagaimana", "emang": "memang", "gimana": "bagaimana",
"gitu": "begitu", "gini": "begini", "bgt": "banget", "gitu": "begitu", "gini": "begini",
"udah": "sudah", "udh": "sudah", "mau": "mau", "udah": "sudah", "udh": "sudah",
"bngt": "banget", "bener": "benar", "beneran": "benar", "mau": "mau",
"mantep": "mantap", "keren": "keren", # Intensitas
# Domain e-commerce & topik crawling "bgt": "banget", "bngt": "banget", "bget": "banget", "bgtt": "banget",
# Positif informal
"bener": "benar", "beneran": "benar",
"mantep": "mantap", "mntap": "mantap",
"kece": "keren", "kece bgt": "keren banget",
"cucok": "cocok", "cucuk": "cocok",
"cakep": "bagus", "oke bgt": "oke banget",
"sip": "baik", "siipp": "baik",
"top": "terbaik", "topbgt": "terbaik banget",
"jos": "bagus", "josss": "bagus",
"goks": "luar biasa",
"setujuu": "setuju", "stuju": "setuju",
"dukung": "dukung",
"proud": "bangga",
"mantul": "mantap betul",
# Negatif informal
"ancur": "hancur", "ancrr": "hancur",
"parahh": "parah", "parahhh": "parah",
"gagall": "gagal",
"ngaco": "tidak benar",
"ngasal": "tidak benar",
"receh": "tidak penting",
"gaje": "tidak jelas",
"asal": "sembarangan",
# Domain
"ongkir": "ongkos kirim", "ongkir": "ongkos kirim",
"freeongkir": "gratis ongkos kirim", "freeongkir": "gratis ongkos kirim",
"gratisongkir": "gratis ongkos kirim",
"free": "gratis", "free": "gratis",
"ecommerce": "e commerce", "ecommerce": "e commerce",
"komdigi": "komdigi", "komdigi": "komdigi",
@ -185,69 +220,51 @@ NORMALISASI = {
} }
# ── Tahap 1: Cleaning ──────────────────────────────────────────────────────── # ── Tahap 1: Case Folding ───────────────────────────────────────────────────
# Menghapus semua elemen yang bukan teks bermakna: def step1_case_folding(text: str) -> str:
# URL, mention (@user), hashtag (#), angka, tanda baca standar, return str(text).lower()
# emoji & simbol unicode, dan karakter non-latin (arab, kanji, dll).
# Teks masih bisa uppercase/mixed-case di tahap ini.
def step1_cleaning(text: str) -> str: # ── Tahap 2: Cleaning ───────────────────────────────────────────────────────
text = str(text) def step2_cleaning(text: str) -> str:
text = re.sub(r"http\S+|www\S+|https\S+", "", text) # hapus URL text = re.sub(r"http\S+|www\S+|https\S+", "", text)
text = re.sub(r"@\w+", "", text) # hapus mention text = re.sub(r"@\w+", "", text)
text = re.sub(r"#\w+", "", text) # hapus hashtag (beserta kata) text = re.sub(r"#\w+", "", text)
text = re.sub(r"\d+", "", text) # hapus angka text = re.sub(r"\d+", "", text)
# Hapus emoji & simbol unicode (range karakter di luar Basic Latin)
text = re.sub( text = re.sub(
r"[\U00010000-\U0010ffff" # supplementary planes (emoji berwarna) r"[\U00010000-\U0010ffff"
r"\U0001F600-\U0001F64F" # emoticons r"\U0001F600-\U0001F64F"
r"\U0001F300-\U0001F5FF" # symbols & pictographs r"\U0001F300-\U0001F5FF"
r"\U0001F680-\U0001F6FF" # transport & map r"\U0001F680-\U0001F6FF"
r"\U0001F1E0-\U0001F1FF" # flags r"\U0001F1E0-\U0001F1FF"
r"\u2600-\u26FF\u2700-\u27BF" # misc symbols & dingbats r"\u2600-\u26FF\u2700-\u27BF"
r"]+", "", text, flags=re.UNICODE r"]+", "", text, flags=re.UNICODE
) )
text = text.translate(str.maketrans("", "", string.punctuation)) # hapus tanda baca text = text.translate(str.maketrans("", "", string.punctuation))
text = re.sub(r"[^a-zA-Z\s]", "", text) # hapus karakter non-latin text = re.sub(r"[^a-zA-Z\s]", "", text)
text = re.sub(r"\s+", " ", text).strip() text = re.sub(r"\s+", " ", text).strip()
return text return text
# ── Tahap 2: Case Folding ──────────────────────────────────────────────────── # ── Tahap 3: Normalisasi ────────────────────────────────────────────────────
# Mengubah seluruh teks menjadi huruf kecil (lowercase).
# Dipisah dari cleaning agar jelas sebagai tahap tersendiri dalam pipeline.
def step2_case_folding(text: str) -> str:
return text.lower()
# ── Tahap 3: Normalisasi ─────────────────────────────────────────────────────
# Mengganti kata tidak baku / singkatan / slang dengan kata baku.
# Pencocokan dilakukan per-token (bukan substring) agar "dr" di tengah kata
# tidak ikut diganti.
def step3_normalization(text: str) -> str: def step3_normalization(text: str) -> str:
return " ".join(NORMALISASI.get(word, word) for word in text.split()) return " ".join(NORMALISASI.get(word, word) for word in text.split())
# ── Tahap 4: Tokenizing ────────────────────────────────────────────────────── # ── Tahap 4: Tokenizing ─────────────────────────────────────────────────────
# Memecah kalimat menjadi daftar token (kata).
# Hasilnya dikembalikan sebagai list untuk proses berikutnya,
# tapi juga disimpan sebagai string (join) untuk tampilan tabel.
def step4_tokenizing(text: str) -> list: def step4_tokenizing(text: str) -> list:
return text.split() return text.split()
# ── Tahap 5: Stopword Removal ──────────────────────────────────────────────── # ── Tahap 5: Stopword Removal ───────────────────────────────────────────────
# Membuang kata-kata yang tidak bermakna dari daftar token.
# Juga membuang token dengan panjang ≤ 2 karakter.
# Kata negasi (tidak, bukan, jangan, dll) TIDAK dihapus.
def step5_stopword_removal(tokens: list, stopwords: set) -> list: def step5_stopword_removal(tokens: list, stopwords: set) -> list:
return [w for w in tokens if w not in stopwords and len(w) > 2] return [
w for w in tokens
if (w not in stopwords or w in KATA_SENTIMEN_PENTING) and len(w) > 2
]
# ── Tahap 6: Stemming ──────────────────────────────────────────────────────── # ── Tahap 6: Stemming ───────────────────────────────────────────────────────
# Mengubah kata ke bentuk dasar menggunakan algoritma Enhanced Confix
# Stripping (ECS) dari library Sastrawi.
# Contoh: "berlari" → "lari", "makanan" → "makan", "pembatasan" → "batas"
# Jika Sastrawi tidak tersedia, token dikembalikan apa adanya.
def step6_stemming(tokens: list, stemmer) -> list: def step6_stemming(tokens: list, stemmer) -> list:
if stemmer is None: if stemmer is None:
return tokens return tokens
@ -256,25 +273,32 @@ def step6_stemming(tokens: list, stemmer) -> list:
def full_preprocessing(text: str, stopwords: set, stemmer): def full_preprocessing(text: str, stopwords: set, stemmer):
""" """
Menjalankan seluruh pipeline 6 tahap dan mengembalikan dict berisi Jalankan 6 tahap preprocessing dan kembalikan dict hasil setiap tahap.
hasil di setiap tahap untuk keperluan tampilan tabel & debugging.
URUTAN TAHAP:
1. Case Folding lowercase
2. Cleaning hapus noise
3. Normalisasi normalisasi kata
4. Tokenizing split token
5. Stopword Removal buang stopword
6. Stemming bentuk dasar
""" """
s1_clean = step1_cleaning(text) s1_fold = step1_case_folding(text)
s2_fold = step2_case_folding(s1_clean) s2_clean = step2_cleaning(s1_fold)
s3_norm = step3_normalization(s2_fold) s3_norm = step3_normalization(s2_clean)
s4_tokens = step4_tokenizing(s3_norm) s4_tokens = step4_tokenizing(s3_norm)
s5_filtered = step5_stopword_removal(s4_tokens, stopwords) s5_filtered = step5_stopword_removal(s4_tokens, stopwords)
s6_stemmed = step6_stemming(s5_filtered, stemmer) s6_stemmed = step6_stemming(s5_filtered, stemmer)
return { return {
"setelah_cleaning": s1_clean, "setelah_casefolding": s1_fold,
"setelah_casefolding": s2_fold, "setelah_cleaning": s2_clean,
"setelah_normalisasi": s3_norm, "setelah_normalisasi": s3_norm,
"setelah_tokenizing": " | ".join(s4_tokens), # tampilkan token dengan separator "setelah_tokenizing": " | ".join(s4_tokens),
"setelah_stopword": " ".join(s5_filtered), "setelah_stopword": " ".join(s5_filtered),
"clean_text": " ".join(s6_stemmed), # hasil akhir untuk analisis sentimen "clean_text": " ".join(s6_stemmed),
"_tokens_raw": s4_tokens, # list mentah (untuk statistik) "_tokens_raw": s4_tokens,
"_tokens_clean": s6_stemmed, # list bersih (untuk word freq) "_tokens_clean": s6_stemmed,
} }
@ -302,16 +326,6 @@ def _gap(size="md"):
st.markdown(f'<div style="height:{heights.get(size,"1.45rem")};"></div>', unsafe_allow_html=True) st.markdown(f'<div style="height:{heights.get(size,"1.45rem")};"></div>', unsafe_allow_html=True)
def _card_wrap(content_fn, *args, **kwargs):
"""Wrapper card tanpa key — kompatibel semua versi Streamlit."""
st.markdown("""
<div style="background:#ffffff;border:1.5px solid #e2e8f0;border-radius:14px;
padding:1.1rem 1.2rem 1rem;box-shadow:0 2px 6px rgba(15,23,42,0.05);">
</div>
""", unsafe_allow_html=True)
content_fn(*args, **kwargs)
# ═══════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════
# STYLES # STYLES
# ═══════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════
@ -382,6 +396,19 @@ header[data-testid="stHeader"] { height: 0 !important; min-height: 0 !important;
margin: 2px 2px 0 0; margin: 2px 2px 0 0;
line-height: 1.6; line-height: 1.6;
} }
.fix-badge {
display: inline-block;
background: #fef9c3;
color: #854d0e;
border: 1px solid #fde68a;
border-radius: 6px;
padding: 2px 8px;
font-size: 0.65rem;
font-weight: 700;
margin-left: 6px;
vertical-align: middle;
}
</style> </style>
""", unsafe_allow_html=True) """, unsafe_allow_html=True)
@ -416,7 +443,7 @@ def _render_page_header():
Bersihkan Data</h2> Bersihkan Data</h2>
<p style="font-size:0.8rem;color:#64748b;margin:0;line-height:1.5;"> <p style="font-size:0.8rem;color:#64748b;margin:0;line-height:1.5;">
Preprocessing teks 6 tahap otomatis: Preprocessing teks 6 tahap otomatis:
<strong style="color:#059669;">Cleaning Case Folding Normalisasi Tokenizing Stopword Removal Stemming</strong> <strong style="color:#059669;">Case Folding Cleaning Normalisasi Tokenizing Stopword Removal Stemming</strong>
</p> </p>
</div> </div>
<div style=" <div style="
@ -433,22 +460,32 @@ def _render_page_header():
# ═══════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════
# PIPELINE STEPS CARDS — 6 TAHAP # PIPELINE STEPS CARDS
# ═══════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════
def _render_pipeline_steps(stemmer_ok): def _render_pipeline_steps(stemmer_ok):
"""
Menampilkan 6 kartu tahap preprocessing dalam 2 baris × 3 kolom.
Setiap kartu berisi nomor tahap, ikon, judul, deskripsi singkat,
dan daftar aksi yang dilakukan.
"""
steps = [ steps = [
{ {
"num": "01", "anim": "pipe-1", "num": "01", "anim": "pipe-1",
"icon": "🔡", "color": "#0284c7", "dark": "#0c4a6e",
"bg": "linear-gradient(135deg,#eff6ff,#dbeafe)", "border": "#bfdbfe",
"title": "Case Folding",
"desc": "Menyeragamkan semua huruf menjadi lowercase sebelum proses lainnya.",
"items": [
'"Gratis""gratis"',
'"ONGKIR""ongkir"',
'"KEREN""keren"',
"Seluruh karakter → huruf kecil",
"Dilakukan pertama agar cleaning konsisten",
"Basis untuk normalisasi & stopword",
],
},
{
"num": "02", "anim": "pipe-2",
"icon": "🧽", "color": "#3b6cf7", "dark": "#1e3a8a", "icon": "🧽", "color": "#3b6cf7", "dark": "#1e3a8a",
"bg": "linear-gradient(135deg,#eef2ff,#e0e7ff)", "border": "#c7d2fe", "bg": "linear-gradient(135deg,#eef2ff,#e0e7ff)", "border": "#c7d2fe",
"title": "Cleaning", "title": "Cleaning",
"desc": "Menghapus semua elemen noise yang tidak bermakna dari teks mentah.", "desc": "Menghapus semua elemen noise yang tidak bermakna dari teks.",
"items": [ "items": [
"Hapus URL (http, https, www)", "Hapus URL (http, https, www)",
"Hapus mention (@username)", "Hapus mention (@username)",
@ -458,32 +495,19 @@ def _render_pipeline_steps(stemmer_ok):
"Hapus tanda baca & karakter non-latin", "Hapus tanda baca & karakter non-latin",
], ],
}, },
{
"num": "02", "anim": "pipe-2",
"icon": "🔡", "color": "#0284c7", "dark": "#0c4a6e",
"bg": "linear-gradient(135deg,#eff6ff,#dbeafe)", "border": "#bfdbfe",
"title": "Case Folding",
"desc": "Menyeragamkan huruf menjadi lowercase agar tidak ada duplikat akibat perbedaan kapitalisasi.",
"items": [
"\"Gratis\"\"gratis\"",
"\"ONGKIR\"\"ongkir\"",
"\"Komdigi\"\"komdigi\"",
"Seluruh karakter → huruf kecil",
],
},
{ {
"num": "03", "anim": "pipe-3", "num": "03", "anim": "pipe-3",
"icon": "🔄", "color": "#16a34a", "dark": "#14532d", "icon": "🔄", "color": "#16a34a", "dark": "#14532d",
"bg": "linear-gradient(135deg,#f0fdf4,#dcfce7)", "border": "#86efac", "bg": "linear-gradient(135deg,#f0fdf4,#dcfce7)", "border": "#86efac",
"title": "Normalisasi", "title": 'Normalisasi <span class="fix-badge">✦ Diperluas</span>',
"desc": "Mengubah kata tidak baku, singkatan, dan slang menjadi kata baku standar.", "desc": "Mengubah kata tidak baku, singkatan, dan slang menjadi kata baku.",
"items": [ "items": [
"gk / ga / gak → tidak", "gk/ga/gak/kagak → tidak",
"ongkir → ongkos kirim", "ongkir → ongkos kirim",
"bgt → banget", "mantep → mantap",
"gimana → bagaimana", "kece → keren",
"jos/josss → bagus",
"free → gratis", "free → gratis",
"seller → penjual",
], ],
}, },
{ {
@ -491,27 +515,29 @@ def _render_pipeline_steps(stemmer_ok):
"icon": "✂️", "color": "#7c3aed", "dark": "#3b0764", "icon": "✂️", "color": "#7c3aed", "dark": "#3b0764",
"bg": "linear-gradient(135deg,#f5f3ff,#ede9fe)", "border": "#c4b5fd", "bg": "linear-gradient(135deg,#f5f3ff,#ede9fe)", "border": "#c4b5fd",
"title": "Tokenizing", "title": "Tokenizing",
"desc": "Memecah kalimat menjadi unit kata (token) yang dapat diproses secara individual.", "desc": "Memecah kalimat menjadi unit kata (token) individual.",
"items": [ "items": [
"Pisahkan berdasarkan spasi", "Pisahkan berdasarkan spasi",
"\"gratis ongkos kirim\" → [gratis, ongkos, kirim]", '"keren banget" → [keren, banget]',
"Setiap token diproses mandiri", "Setiap token diproses mandiri",
"Hasil: daftar kata terpisah", "Hasil: daftar kata terpisah",
"Input untuk stopword removal",
"Ditampilkan sebagai chip per token",
], ],
}, },
{ {
"num": "05", "anim": "pipe-5", "num": "05", "anim": "pipe-5",
"icon": "🚫", "color": "#ea580c", "dark": "#7c2d12", "icon": "🚫", "color": "#ea580c", "dark": "#7c2d12",
"bg": "linear-gradient(135deg,#fff7ed,#ffedd5)", "border": "#fed7aa", "bg": "linear-gradient(135deg,#fff7ed,#ffedd5)", "border": "#fed7aa",
"title": "Stopword Removal", "title": 'Stopword Removal <span class="fix-badge">✦ Diperbaiki</span>',
"desc": "Membuang kata-kata umum yang tidak berkontribusi pada makna atau sentimen teks.", "desc": "Membuang kata umum; kata sentimen penting DIJAGA.",
"items": [ "items": [
"Hapus kata umum (dan, di, ke, dari…)", "Hapus kata umum (dan, di, ke...)",
"Hapus kata < 3 karakter", "Hapus token < 3 karakter",
"PERTAHANKAN: tidak, bukan, jangan", "JAGA negasi: tidak, bukan, jangan",
"PERTAHANKAN: belum, kurang, tanpa", "JAGA positif: keren, bagus, mantap",
f"Sumber: indonesian-stopwords-complete.txt", "JAGA evaluatif: setuju, dukung, bijak",
"Kata negasi dijaga untuk sentimen", "JAGA intensitas: banget, sangat, sekali",
], ],
}, },
{ {
@ -519,26 +545,24 @@ def _render_pipeline_steps(stemmer_ok):
"icon": "🌱", "color": "#ca8a04", "dark": "#713f12", "icon": "🌱", "color": "#ca8a04", "dark": "#713f12",
"bg": "linear-gradient(135deg,#fefce8,#fef9c3)", "border": "#fde68a", "bg": "linear-gradient(135deg,#fefce8,#fef9c3)", "border": "#fde68a",
"title": "Stemming", "title": "Stemming",
"desc": "Mengubah kata ke bentuk dasarnya menggunakan algoritma Enhanced Confix Stripping (ECS) Sastrawi.", "desc": "Mengubah kata ke bentuk dasar via ECS Sastrawi.",
"items": [ "items": [
"berlari → lari", "berlari → lari",
"makanan → makan", "makanan → makan",
"pembatasan → batas", "pembatasan → batas",
"pengiriman → kirim", "pengiriman → kirim",
f"Status: {'✅ Sastrawi aktif' if stemmer_ok else '⚠️ Sastrawi tidak terinstall — skip'}", f"Status: {'✅ Sastrawi aktif' if stemmer_ok else '⚠️ Sastrawi tidak tersedia'}",
"Algoritma: Enhanced Confix Stripping", "Algoritma: Enhanced Confix Stripping",
], ],
}, },
] ]
# Baris pertama: tahap 13
row1 = st.columns(3, gap="medium") row1 = st.columns(3, gap="medium")
for col, step in zip(row1, steps[:3]): for col, step in zip(row1, steps[:3]):
_render_step_card(col, step) _render_step_card(col, step)
_gap("sm") _gap("sm")
# Baris kedua: tahap 46
row2 = st.columns(3, gap="medium") row2 = st.columns(3, gap="medium")
for col, step in zip(row2, steps[3:]): for col, step in zip(row2, steps[3:]):
_render_step_card(col, step) _render_step_card(col, step)
@ -589,14 +613,14 @@ def _render_step_card(col, step):
# ═══════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════
# FLOW ARROW — pipeline visual # FLOW ARROW
# ═══════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════
def _render_flow_arrow(): def _render_flow_arrow():
nodes = [ nodes = [
("📄 Teks Asli", "#94a3b8", "#f8fafc", "#e2e8f0"), ("📄 Teks Asli", "#94a3b8", "#f8fafc", "#e2e8f0"),
("① Cleaning", "#3b6cf7", "#eef2ff", "#c7d2fe"), ("① Case Folding", "#0284c7", "#eff6ff", "#bfdbfe"),
("② Case Folding", "#0284c7", "#eff6ff", "#bfdbfe"), ("② Cleaning", "#3b6cf7", "#eef2ff", "#c7d2fe"),
("③ Normalisasi", "#16a34a", "#f0fdf4", "#86efac"), ("③ Normalisasi", "#16a34a", "#f0fdf4", "#86efac"),
("④ Tokenizing", "#7c3aed", "#f5f3ff", "#c4b5fd"), ("④ Tokenizing", "#7c3aed", "#f5f3ff", "#c4b5fd"),
("⑤ Stopword", "#ea580c", "#fff7ed", "#fed7aa"), ("⑤ Stopword", "#ea580c", "#fff7ed", "#fed7aa"),
@ -637,13 +661,6 @@ def _render_flow_arrow():
# ═══════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════
def _render_stat_pills(total_raw, total_clean, avg_tokens_before, avg_tokens_after, removed): def _render_stat_pills(total_raw, total_clean, avg_tokens_before, avg_tokens_after, removed):
"""
Menampilkan 4 kartu ringkasan hasil preprocessing:
1. Total tweet yang masuk pipeline
2. Tweet yang lolos semua tahap (clean_text tidak kosong)
3. Tweet yang dibuang (clean_text kosong setelah semua tahap)
4. Rata-rata jumlah token sebelum vs sesudah stopword removal
"""
c1, c2, c3, c4 = st.columns(4, gap="medium") c1, c2, c3, c4 = st.columns(4, gap="medium")
cards = [ cards = [
@ -685,7 +702,7 @@ def _render_stat_pills(total_raw, total_clean, avg_tokens_before, avg_tokens_aft
# ═══════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════
# LIVE EXAMPLE — contoh hasil tiap tahap # LIVE EXAMPLE
# ═══════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════
def _render_live_example(df_c): def _render_live_example(df_c):
@ -699,12 +716,13 @@ def _render_live_example(df_c):
"Contoh tweet acak dari dataset — refresh halaman untuk contoh berbeda" "Contoh tweet acak dari dataset — refresh halaman untuk contoh berbeda"
) )
# Urutan tampilan sesuai pipeline: CF → Clean → Norm → Token → Stop → Stem
steps_ex = [ steps_ex = [
("📄 Teks Asli", "text_asli", "#0f172a", "#f8fafc", "#e2e8f0", False), ("📄 Teks Asli", "text_asli", "#0f172a", "#f8fafc", "#e2e8f0", False),
("① Setelah Cleaning", "setelah_cleaning", "#1e3a8a", "#eef2ff", "#c7d2fe", False), ("① Setelah Case Folding", "setelah_casefolding", "#0c4a6e", "#eff6ff", "#bfdbfe", False),
("② Setelah Case Folding","setelah_casefolding", "#0c4a6e", "#eff6ff", "#bfdbfe", False), ("② Setelah Cleaning", "setelah_cleaning", "#1e3a8a", "#eef2ff", "#c7d2fe", False),
("③ Setelah Normalisasi", "setelah_normalisasi", "#14532d", "#f0fdf4", "#86efac", False), ("③ Setelah Normalisasi", "setelah_normalisasi", "#14532d", "#f0fdf4", "#86efac", False),
("④ Setelah Tokenizing", "setelah_tokenizing", "#3b0764", "#f5f3ff", "#c4b5fd", True), # tampilkan sebagai chip ("④ Setelah Tokenizing", "setelah_tokenizing", "#3b0764", "#f5f3ff", "#c4b5fd", True),
("⑤ Setelah Stopword", "setelah_stopword", "#7c2d12", "#fff7ed", "#fed7aa", False), ("⑤ Setelah Stopword", "setelah_stopword", "#7c2d12", "#fff7ed", "#fed7aa", False),
("⑥ Hasil Akhir (Stem)", "clean_text", "#713f12", "#fefce8", "#fde68a", False), ("⑥ Hasil Akhir (Stem)", "clean_text", "#713f12", "#fefce8", "#fde68a", False),
] ]
@ -713,7 +731,6 @@ def _render_live_example(df_c):
raw = sample.get(col_key, "-") raw = sample.get(col_key, "-")
text_display = str(raw) if raw and str(raw).strip() else "" text_display = str(raw) if raw and str(raw).strip() else ""
# Untuk tokenizing, tampilkan sebagai chip/badge per kata
if is_token and text_display != "": if is_token and text_display != "":
words = text_display.split(" | ") words = text_display.split(" | ")
chips = "".join( chips = "".join(
@ -721,8 +738,7 @@ def _render_live_example(df_c):
for w in words if w.strip() for w in words if w.strip()
) )
content_html = f'<div style="line-height:2;">{chips}</div>' content_html = f'<div style="line-height:2;">{chips}</div>'
word_count = len(words) char_info = f"{len(words)} token"
char_info = f"{word_count} token"
else: else:
content_html = ( content_html = (
f'<div style="font-size:0.82rem;color:{text_color};' f'<div style="font-size:0.82rem;color:{text_color};'
@ -752,27 +768,20 @@ def _render_live_example(df_c):
# ═══════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════
def _render_length_comparison_chart(df, df_c): def _render_length_comparison_chart(df, df_c):
"""
Grafik batang: rata-rata jumlah karakter per tweet di setiap tahap.
Catatan: jumlah karakter bisa naik di tahap Normalisasi karena
singkatan diekspansi (ongkir 6 kar ongkos kirim 12 kar) ini NORMAL.
Turun signifikan terjadi di tahap Stopword dan Stemming.
"""
_section_header( _section_header(
"📐 Perbandingan Panjang Teks per Tahap", "📐 Perbandingan Panjang Teks per Tahap",
"Rata-rata jumlah karakter per tweet di setiap tahap preprocessing · Naik di normalisasi adalah normal (ekspansi singkatan)" "Rata-rata karakter per tweet di tiap tahap · Naik di normalisasi adalah normal (ekspansi singkatan)"
) )
stages = [ stages = [
"Teks Asli", "① Cleaning", "② Case Folding", "Teks Asli", "① Case Folding", "② Cleaning",
"③ Normalisasi", "④ Tokenizing", "⑤ Stopword", "⑥ Stemming" "③ Normalisasi", "④ Tokenizing", "⑤ Stopword", "⑥ Stemming"
] ]
avgs = [ avgs = [
df["text"].astype(str).str.len().mean(), df["text"].astype(str).str.len().mean(),
df_c["setelah_cleaning"].astype(str).str.len().mean(),
df_c["setelah_casefolding"].astype(str).str.len().mean(), df_c["setelah_casefolding"].astype(str).str.len().mean(),
df_c["setelah_cleaning"].astype(str).str.len().mean(),
df_c["setelah_normalisasi"].astype(str).str.len().mean(), df_c["setelah_normalisasi"].astype(str).str.len().mean(),
# tokenizing: hitung panjang tanpa separator " | "
df_c["setelah_tokenizing"].apply( df_c["setelah_tokenizing"].apply(
lambda x: len(" ".join(str(x).split(" | "))) lambda x: len(" ".join(str(x).split(" | ")))
).mean(), ).mean(),
@ -780,8 +789,7 @@ def _render_length_comparison_chart(df, df_c):
df_c["clean_text"].astype(str).str.len().mean(), df_c["clean_text"].astype(str).str.len().mean(),
] ]
avgs = [round(a, 1) for a in avgs] avgs = [round(a, 1) for a in avgs]
colors = ["#94a3b8", "#0284c7", "#3b6cf7", "#16a34a", "#7c3aed", "#ea580c", "#ca8a04"]
colors = ["#94a3b8", "#3b6cf7", "#0284c7", "#16a34a", "#7c3aed", "#ea580c", "#ca8a04"]
fig = go.Figure(data=[ fig = go.Figure(data=[
go.Bar( go.Bar(
@ -825,7 +833,6 @@ def _render_top_words_chart(df_c):
f"Dari {len(df_c):,} tweet yang sudah bersih (hasil akhir tahap 6) — Top 20 kata" f"Dari {len(df_c):,} tweet yang sudah bersih (hasil akhir tahap 6) — Top 20 kata"
) )
# Gunakan _tokens_clean (list) jika tersedia, fallback ke clean_text string
if "_tokens_clean" in df_c.columns: if "_tokens_clean" in df_c.columns:
all_words = [w for tokens in df_c["_tokens_clean"] for w in (tokens if isinstance(tokens, list) else [])] all_words = [w for tokens in df_c["_tokens_clean"] for w in (tokens if isinstance(tokens, list) else [])]
else: else:
@ -864,7 +871,6 @@ def _render_top_words_chart(df_c):
showlegend=False, showlegend=False,
) )
# ── Tanpa key — kompatibel semua versi Streamlit ──
st.markdown(""" st.markdown("""
<div style="background:#ffffff;border:1.5px solid #e2e8f0;border-radius:14px; <div style="background:#ffffff;border:1.5px solid #e2e8f0;border-radius:14px;
padding:1rem 1.2rem 0.5rem;box-shadow:0 2px 6px rgba(15,23,42,0.05);"> padding:1rem 1.2rem 0.5rem;box-shadow:0 2px 6px rgba(15,23,42,0.05);">
@ -906,7 +912,6 @@ def show():
st.session_state.analysis_mode, ("#3b6cf7", "📊") st.session_state.analysis_mode, ("#3b6cf7", "📊")
) )
# ── Active Period Banner ──────────────────────────────────
st.markdown( st.markdown(
f'<div style="background:#fff;border-left:4px solid {mode_color};' f'<div style="background:#fff;border-left:4px solid {mode_color};'
f'border-top:1.5px solid #e2e8f0;border-right:1.5px solid #e2e8f0;' f'border-top:1.5px solid #e2e8f0;border-right:1.5px solid #e2e8f0;'
@ -935,7 +940,7 @@ def show():
_render_flow_arrow() _render_flow_arrow()
_gap("md") _gap("md")
# ── Load data dari DB ───────────────────────────────────── # ── Load data ─────────────────────────────────────────────
try: try:
df_all = pd.read_sql("SELECT * FROM tweets ORDER BY created_at DESC", engine) df_all = pd.read_sql("SELECT * FROM tweets ORDER BY created_at DESC", engine)
if df_all.empty: if df_all.empty:
@ -966,7 +971,6 @@ def show():
f"{start_date}_{end_date}_{total_tweets_in_db}_{latest_crawl_marker}" f"{start_date}_{end_date}_{total_tweets_in_db}_{latest_crawl_marker}"
) )
# Hapus cache lama dari session state
for old_key in list(st.session_state.keys()): for old_key in list(st.session_state.keys()):
if old_key.startswith("pp6_") and old_key != cache_key: if old_key.startswith("pp6_") and old_key != cache_key:
del st.session_state[old_key] del st.session_state[old_key]
@ -988,7 +992,6 @@ def show():
results.append(r) results.append(r)
df_c = pd.DataFrame(results) df_c = pd.DataFrame(results)
# Buang tweet yang clean_text-nya kosong setelah semua tahap
df_c = df_c[df_c["clean_text"].str.strip().str.len() > 0].copy() df_c = df_c[df_c["clean_text"].str.strip().str.len() > 0].copy()
st.session_state[cache_key] = df_c st.session_state[cache_key] = df_c
@ -998,18 +1001,15 @@ def show():
df_c = st.session_state[cache_key] df_c = st.session_state[cache_key]
stemmer_ok = st.session_state.get(cache_key + "_stemmer_ok", False) stemmer_ok = st.session_state.get(cache_key + "_stemmer_ok", False)
# ── Hitung statistik ringkasan ──────────────────────────── # ── Statistik ─────────────────────────────────────────────
# Token sebelum stopword = jumlah kata di tahap tokenizing
avg_tok_before = df_c["setelah_tokenizing"].apply( avg_tok_before = df_c["setelah_tokenizing"].apply(
lambda x: len(str(x).split(" | ")) if str(x).strip() else 0 lambda x: len(str(x).split(" | ")) if str(x).strip() else 0
).mean() ).mean()
# Token sesudah stopword = jumlah kata di clean_text
avg_tok_after = df_c["clean_text"].apply( avg_tok_after = df_c["clean_text"].apply(
lambda x: len(str(x).split()) if str(x).strip() else 0 lambda x: len(str(x).split()) if str(x).strip() else 0
).mean() ).mean()
removed = len(df) - len(df_c) removed = len(df) - len(df_c)
# ── Ringkasan ─────────────────────────────────────────────
_section_header( _section_header(
"📌 Ringkasan Hasil Preprocessing", "📌 Ringkasan Hasil Preprocessing",
f"Berdasarkan tanggal asli tweet · {filter_label}" f"Berdasarkan tanggal asli tweet · {filter_label}"
@ -1018,11 +1018,10 @@ def show():
_render_stat_pills(len(df), len(df_c), avg_tok_before, avg_tok_after, removed) _render_stat_pills(len(df), len(df_c), avg_tok_before, avg_tok_after, removed)
_gap("lg") _gap("lg")
# ── Live example ──────────────────────────────────────────
_render_live_example(df_c) _render_live_example(df_c)
_gap("lg") _gap("lg")
# ── Tabel perbandingan tahap ────────────────────────────── # ── Tabel ─────────────────────────────────────────────────
_section_header( _section_header(
"📋 Tabel Perbandingan Teks per Tahap", "📋 Tabel Perbandingan Teks per Tahap",
f"{len(df_c):,} tweet · {filter_label} — scroll horizontal untuk lihat semua kolom" f"{len(df_c):,} tweet · {filter_label} — scroll horizontal untuk lihat semua kolom"
@ -1032,11 +1031,12 @@ def show():
df_c = df_c.copy() df_c = df_c.copy()
df_c["crawled_at"] = pd.NaT df_c["crawled_at"] = pd.NaT
# Kolom ditampilkan sesuai urutan pipeline: CF → Clean → Norm → Token → Stop → Stem
disp = df_c[[ disp = df_c[[
"tweet_id", "created_at", "crawled_at", "tweet_id", "created_at", "crawled_at",
"text_asli", "text_asli",
"setelah_cleaning",
"setelah_casefolding", "setelah_casefolding",
"setelah_cleaning",
"setelah_normalisasi", "setelah_normalisasi",
"setelah_tokenizing", "setelah_tokenizing",
"setelah_stopword", "setelah_stopword",
@ -1046,8 +1046,8 @@ def show():
disp.columns = [ disp.columns = [
"ID Tweet", "Tanggal Tweet", "Masuk Database", "ID Tweet", "Tanggal Tweet", "Masuk Database",
"Teks Asli", "Teks Asli",
"① Cleaning", "① Case Folding",
"② Case Folding", "② Cleaning",
"③ Normalisasi", "③ Normalisasi",
"④ Tokenizing", "④ Tokenizing",
"⑤ Stopword", "⑤ Stopword",
@ -1063,7 +1063,7 @@ def show():
min_width=2200, min_width=2200,
nowrap=["ID Tweet", "Tanggal Tweet", "Masuk Database"], nowrap=["ID Tweet", "Tanggal Tweet", "Masuk Database"],
wide_columns=[ wide_columns=[
"Teks Asli", "① Cleaning", "② Case Folding", "Teks Asli", "① Case Folding", "② Cleaning",
"③ Normalisasi", "④ Tokenizing", "⑤ Stopword", "⑥ Hasil Akhir", "③ Normalisasi", "④ Tokenizing", "⑤ Stopword", "⑥ Hasil Akhir",
], ],
column_widths={ column_widths={
@ -1071,8 +1071,8 @@ def show():
"Tanggal Tweet": "165px", "Tanggal Tweet": "165px",
"Masuk Database": "165px", "Masuk Database": "165px",
"Teks Asli": "280px", "Teks Asli": "280px",
"① Cleaning": "240px", "① Case Folding": "220px",
"② Case Folding": "220px", "② Cleaning": "240px",
"③ Normalisasi": "220px", "③ Normalisasi": "220px",
"④ Tokenizing": "240px", "④ Tokenizing": "240px",
"⑤ Stopword": "220px", "⑤ Stopword": "220px",
@ -1081,18 +1081,16 @@ def show():
) )
_gap("lg") _gap("lg")
# ── Chart panjang teks ────────────────────────────────────
_render_length_comparison_chart(df, df_c) _render_length_comparison_chart(df, df_c)
_gap("lg") _gap("lg")
# ── Top words ─────────────────────────────────────────────
_render_top_words_chart(df_c) _render_top_words_chart(df_c)
_gap("lg") _gap("lg")
# ── Simpan ke session state untuk halaman sentimen ──────── # ── Simpan ke session state ───────────────────────────────
st.session_state["preprocessed_df"] = df_c st.session_state["preprocessed_df"] = df_c
# ── Download buttons ────────────────────────────────────── # ── Download ──────────────────────────────────────────────
st.markdown(""" st.markdown("""
<div style="background:#ffffff;border:1.5px solid #e2e8f0;border-radius:14px; <div style="background:#ffffff;border:1.5px solid #e2e8f0;border-radius:14px;
padding:1.1rem 1.2rem;box-shadow:0 2px 6px rgba(15,23,42,0.05); padding:1.1rem 1.2rem;box-shadow:0 2px 6px rgba(15,23,42,0.05);
@ -1125,7 +1123,6 @@ def show():
st.markdown("</div>", unsafe_allow_html=True) st.markdown("</div>", unsafe_allow_html=True)
_gap("sm") _gap("sm")
# ── Navigasi ──────────────────────────────────────────────
if st.button( if st.button(
"📈 Lanjut ke Analisis Sentimen →", "📈 Lanjut ke Analisis Sentimen →",
type="primary", type="primary",

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@

View File

@ -1,4 +1 @@

1

12
tweets-data/hasil_top.csv Normal file
View File

@ -0,0 +1,12 @@
"conversation_id_str","created_at","favorite_count","full_text","id_str","image_url","in_reply_to_screen_name","lang","location","quote_count","reply_count","retweet_count","tweet_url","user_id_str","username"
"2054502530504364380","Wed May 13 10:02:28 +0000 2026","0","GRATIS ONGKIR DIBATASI??? PARAH ","2054502530504364380","","","in","","0","0","0","https://x.com/undefined/status/2054502530504364380","1814143201718247424",
"2054816635131994490","Thu May 14 06:50:37 +0000 2026","0","keren sih ada kebijakan dari komdigi ongkir jadi berasa lebih merataa","2054816635131994490","","","in","","0","0","0","https://x.com/undefined/status/2054816635131994490","1814143201718247424",
"2054839912529350807","Thu May 14 08:23:06 +0000 2026","0","komdigi mending ngurusin lainnya deh dsripada ngurusin ongkir giniii","2054839912529350807","","","in","","0","0","0","https://x.com/undefined/status/2054839912529350807","1814143201718247424",
"2054502757869199625","Wed May 13 10:03:22 +0000 2026","0","Komdigi mengeluarkan kebijakan terkait gratis ongkir.","2054502757869199625","","","in","","0","0","0","https://x.com/undefined/status/2054502757869199625","1814143201718247424",
"2054996678391091685","Thu May 14 18:46:02 +0000 2026","0","komdigi ongkir mending sampingkan dulu","2054996678391091685","","","in","","0","0","0","https://x.com/undefined/status/2054996678391091685","1814143201718247424",
"2055002136027767200","Thu May 14 19:07:43 +0000 2026","0","komdigi ongkir apa gunanyaa??222","2055002136027767200","","","in","","0","0","0","https://x.com/undefined/status/2055002136027767200","2043979880086339584",
"2054998005359751518","Thu May 14 18:51:19 +0000 2026","0","komdigi ongkir apa gunanyaa??","2054998005359751518","","","in","","0","0","0","https://x.com/undefined/status/2054998005359751518","2043979880086339584",
"2055002941288001599","Thu May 14 19:10:55 +0000 2026","0","yakin komdigi bikin kebijakan pembatasan gratis ongkir ini bakal bisa ngimbangin pemerataan umkm??","2055002941288001599","","","in","","0","0","0","https://x.com/undefined/status/2055002941288001599","2043979880086339584",
"2055269612334555468","Fri May 15 12:50:35 +0000 2026","0","komdigi + ongkir = chaos wkwkwk","2055269612334555468","","","in","","0","0","0","https://x.com/undefined/status/2055269612334555468","2043979880086339584",
"2055001478004367487","Thu May 14 19:05:07 +0000 2026","0","maksud dari komdigi bikin kebijakan gratis ongkir ini apa yaaa?","2055001478004367487","","","in","","0","0","0","https://x.com/undefined/status/2055001478004367487","2043979880086339584",
"2055013912555475243","Thu May 14 19:54:31 +0000 2026","0","komdigi haloo?? masa iya ngurusin ongkir dulu dibanding permasalahan sebelah??","2055013912555475243","","","in","","0","0","0","https://x.com/undefined/status/2055013912555475243","2043979880086339584",
1 conversation_id_str created_at favorite_count full_text id_str image_url in_reply_to_screen_name lang location quote_count reply_count retweet_count tweet_url user_id_str username
2 2054502530504364380 Wed May 13 10:02:28 +0000 2026 0 GRATIS ONGKIR DIBATASI??? PARAH 2054502530504364380 in 0 0 0 https://x.com/undefined/status/2054502530504364380 1814143201718247424
3 2054816635131994490 Thu May 14 06:50:37 +0000 2026 0 keren sih ada kebijakan dari komdigi ongkir jadi berasa lebih merataa 2054816635131994490 in 0 0 0 https://x.com/undefined/status/2054816635131994490 1814143201718247424
4 2054839912529350807 Thu May 14 08:23:06 +0000 2026 0 komdigi mending ngurusin lainnya deh dsripada ngurusin ongkir giniii 2054839912529350807 in 0 0 0 https://x.com/undefined/status/2054839912529350807 1814143201718247424
5 2054502757869199625 Wed May 13 10:03:22 +0000 2026 0 Komdigi mengeluarkan kebijakan terkait gratis ongkir. 2054502757869199625 in 0 0 0 https://x.com/undefined/status/2054502757869199625 1814143201718247424
6 2054996678391091685 Thu May 14 18:46:02 +0000 2026 0 komdigi ongkir mending sampingkan dulu 2054996678391091685 in 0 0 0 https://x.com/undefined/status/2054996678391091685 1814143201718247424
7 2055002136027767200 Thu May 14 19:07:43 +0000 2026 0 komdigi ongkir apa gunanyaa??222 2055002136027767200 in 0 0 0 https://x.com/undefined/status/2055002136027767200 2043979880086339584
8 2054998005359751518 Thu May 14 18:51:19 +0000 2026 0 komdigi ongkir apa gunanyaa?? 2054998005359751518 in 0 0 0 https://x.com/undefined/status/2054998005359751518 2043979880086339584
9 2055002941288001599 Thu May 14 19:10:55 +0000 2026 0 yakin komdigi bikin kebijakan pembatasan gratis ongkir ini bakal bisa ngimbangin pemerataan umkm?? 2055002941288001599 in 0 0 0 https://x.com/undefined/status/2055002941288001599 2043979880086339584
10 2055269612334555468 Fri May 15 12:50:35 +0000 2026 0 komdigi + ongkir = chaos wkwkwk 2055269612334555468 in 0 0 0 https://x.com/undefined/status/2055269612334555468 2043979880086339584
11 2055001478004367487 Thu May 14 19:05:07 +0000 2026 0 maksud dari komdigi bikin kebijakan gratis ongkir ini apa yaaa? 2055001478004367487 in 0 0 0 https://x.com/undefined/status/2055001478004367487 2043979880086339584
12 2055013912555475243 Thu May 14 19:54:31 +0000 2026 0 komdigi haloo?? masa iya ngurusin ongkir dulu dibanding permasalahan sebelah?? 2055013912555475243 in 0 0 0 https://x.com/undefined/status/2055013912555475243 2043979880086339584

View File

@ -1,42 +1,21 @@
"conversation_id_str","created_at","favorite_count","full_text","id_str","image_url","in_reply_to_screen_name","lang","location","quote_count","reply_count","retweet_count","tweet_url","user_id_str","username" "conversation_id_str","created_at","favorite_count","full_text","id_str","image_url","in_reply_to_screen_name","lang","location","quote_count","reply_count","retweet_count","tweet_url","user_id_str","username"
"2054791169775964388","Thu May 14 05:09:25 +0000 2026","0","kebijakan komdigi gratis ongkir kerenn","2054791169775964388","","","in","","0","0","0","https://x.com/undefined/status/2054791169775964388","1814143201718247424",
"2055002136027767200","Thu May 14 19:07:43 +0000 2026","0","komdigi ongkir apa gunanyaa??222","2055002136027767200","","","in","","0","0","0","https://x.com/undefined/status/2055002136027767200","2043979880086339584",
"2054861268750901484","Thu May 14 09:47:58 +0000 2026","0","komdigi ongkir?","2054861268750901484","","","in","","0","0","0","https://x.com/undefined/status/2054861268750901484","1814143201718247424",
"2054816992662790146","Thu May 14 06:52:02 +0000 2026","0","komdigi??? ongkir??? marketplace???","2054816992662790146","","","in","","0","0","0","https://x.com/undefined/status/2054816992662790146","1814143201718247424",
"2054823109291852155","Thu May 14 07:16:20 +0000 2026","0","komdigi bikin aturan ongkir baru = langkah yang cukup bijak","2054823109291852155","","","in","","0","0","0","https://x.com/undefined/status/2054823109291852155","1814143201718247424",
"2055269612334555468","Fri May 15 12:50:35 +0000 2026","0","komdigi + ongkir = chaos wkwkwk","2055269612334555468","","","in","","0","0","0","https://x.com/undefined/status/2055269612334555468","2043979880086339584",
"2054998005359751518","Thu May 14 18:51:19 +0000 2026","0","komdigi ongkir apa gunanyaa??","2054998005359751518","","","in","","0","0","0","https://x.com/undefined/status/2054998005359751518","2043979880086339584",
"2054816818741862819","Thu May 14 06:51:20 +0000 2026","0","Saya melihat berita tentang komdigi dan ongkir tadi pagi.","2054816818741862819","","","in","","0","0","0","https://x.com/undefined/status/2054816818741862819","1814143201718247424",
"2054502430956769299","Wed May 13 10:02:05 +0000 2026","0","Pembatasan gratis ongkir sangat mengecewakan.","2054502430956769299","","","in","","0","0","0","https://x.com/undefined/status/2054502430956769299","1814143201718247424",
"2054816635131994490","Thu May 14 06:50:37 +0000 2026","0","keren sih ada kebijakan dari komdigi ongkir jadi berasa lebih merataa","2054816635131994490","","","in","","0","0","0","https://x.com/undefined/status/2054816635131994490","1814143201718247424",
"2054502269576728775","Wed May 13 10:01:26 +0000 2026","0","Kebijakan komdigi soal ongkir sangat merugikan konsumen.","2054502269576728775","","","in","","0","0","0","https://x.com/undefined/status/2054502269576728775","1814143201718247424", "2054502269576728775","Wed May 13 10:01:26 +0000 2026","0","Kebijakan komdigi soal ongkir sangat merugikan konsumen.","2054502269576728775","","","in","","0","0","0","https://x.com/undefined/status/2054502269576728775","1814143201718247424",
"2055001478004367487","Thu May 14 19:05:07 +0000 2026","0","maksud dari komdigi bikin kebijakan gratis ongkir ini apa yaaa?","2055001478004367487","","","in","","0","0","0","https://x.com/undefined/status/2055001478004367487","2043979880086339584",
"2054502958315020394","Wed May 13 10:04:10 +0000 2026","0","Komdigi disebut dalam diskusi mengenai free ongkir.","2054502958315020394","","","in","","0","0","0","https://x.com/undefined/status/2054502958315020394","1814143201718247424",
"2054502618484134392","Wed May 13 10:02:49 +0000 2026","0","@komdigi kenapa sih harus ngurusin ongkir segala???","2054502618484134392","","","in","","0","0","0","https://x.com/undefined/status/2054502618484134392","1814143201718247424",
"2054996678391091685","Thu May 14 18:46:02 +0000 2026","0","komdigi ongkir mending sampingkan dulu","2054996678391091685","","","in","","0","0","0","https://x.com/undefined/status/2054996678391091685","1814143201718247424",
"2054502657201733861","Wed May 13 10:02:58 +0000 2026","0","Gratis ongkir dibatasi? keputusan paling aneh tahun ini.","2054502657201733861","","","in","","0","0","0","https://x.com/undefined/status/2054502657201733861","1814143201718247424",
"2054501981369352445","Wed May 13 10:00:17 +0000 2026","0","Gratis ongkir dibatasi malah bikin marketplace lebih fair.","2054501981369352445","","","in","","0","0","0","https://x.com/undefined/status/2054501981369352445","1814143201718247424",
"2054839912529350807","Thu May 14 08:23:06 +0000 2026","0","komdigi mending ngurusin lainnya deh dsripada ngurusin ongkir giniii","2054839912529350807","","","in","","0","0","0","https://x.com/undefined/status/2054839912529350807","1814143201718247424",
"2054502817910706448","Wed May 13 10:03:37 +0000 2026","0","Saya membaca berita tentang gratis ongkir dibatasi.","2054502817910706448","","","in","","0","0","0","https://x.com/undefined/status/2054502817910706448","1814143201718247424",
"2054502131672236531","Wed May 13 10:00:53 +0000 2026","0","kebijakan komdigi tentang ongkir patut diapresiasi.","2054502131672236531","","","in","","0","0","0","https://x.com/undefined/status/2054502131672236531","1814143201718247424",
"conversation_id_str","created_at","favorite_count","full_text","id_str","image_url","in_reply_to_screen_name","lang","location","quote_count","reply_count","retweet_count","tweet_url","user_id_str","username"
"2054791169775964388","Thu May 14 05:09:25 +0000 2026","0","kebijakan komdigi gratis ongkir kerenn","2054791169775964388","","","in","","0","0","0","https://x.com/undefined/status/2054791169775964388","1814143201718247424",
"2055002136027767200","Thu May 14 19:07:43 +0000 2026","0","komdigi ongkir apa gunanyaa??222","2055002136027767200","","","in","","0","0","0","https://x.com/undefined/status/2055002136027767200","2043979880086339584",
"2054861268750901484","Thu May 14 09:47:58 +0000 2026","0","komdigi ongkir?","2054861268750901484","","","in","","0","0","0","https://x.com/undefined/status/2054861268750901484","1814143201718247424",
"2054816992662790146","Thu May 14 06:52:02 +0000 2026","0","komdigi??? ongkir??? marketplace???","2054816992662790146","","","in","","0","0","0","https://x.com/undefined/status/2054816992662790146","1814143201718247424",
"2054823109291852155","Thu May 14 07:16:20 +0000 2026","0","komdigi bikin aturan ongkir baru = langkah yang cukup bijak","2054823109291852155","","","in","","0","0","0","https://x.com/undefined/status/2054823109291852155","1814143201718247424", "2054823109291852155","Thu May 14 07:16:20 +0000 2026","0","komdigi bikin aturan ongkir baru = langkah yang cukup bijak","2054823109291852155","","","in","","0","0","0","https://x.com/undefined/status/2054823109291852155","1814143201718247424",
"2055269612334555468","Fri May 15 12:50:35 +0000 2026","0","komdigi + ongkir = chaos wkwkwk","2055269612334555468","","","in","","0","0","0","https://x.com/undefined/status/2055269612334555468","2043979880086339584", "2054502892468662645","Wed May 13 10:03:55 +0000 2026","0","Komdigi dan gratis ongkir sedang ramai dibahas.","2054502892468662645","","","in","","0","0","0","https://x.com/undefined/status/2054502892468662645","1814143201718247424",
"2054998005359751518","Thu May 14 18:51:19 +0000 2026","0","komdigi ongkir apa gunanyaa??","2054998005359751518","","","in","","0","0","0","https://x.com/undefined/status/2054998005359751518","2043979880086339584", "2054501918895202348","Wed May 13 10:00:02 +0000 2026","0","Mantap sih @komdigi akhirnya free ongkir diatur juga ","2054501918895202348","","","in","","0","0","0","https://x.com/undefined/status/2054501918895202348","1814143201718247424",
"2054816818741862819","Thu May 14 06:51:20 +0000 2026","0","Saya melihat berita tentang komdigi dan ongkir tadi pagi.","2054816818741862819","","","in","","0","0","0","https://x.com/undefined/status/2054816818741862819","1814143201718247424", "2054861268750901484","Thu May 14 09:47:58 +0000 2026","0","komdigi ongkir?","2054861268750901484","","","in","","0","0","0","https://x.com/undefined/status/2054861268750901484","1814143201718247424",
"2054502430956769299","Wed May 13 10:02:05 +0000 2026","0","Pembatasan gratis ongkir sangat mengecewakan.","2054502430956769299","","","in","","0","0","0","https://x.com/undefined/status/2054502430956769299","1814143201718247424",
"2054816635131994490","Thu May 14 06:50:37 +0000 2026","0","keren sih ada kebijakan dari komdigi ongkir jadi berasa lebih merataa","2054816635131994490","","","in","","0","0","0","https://x.com/undefined/status/2054816635131994490","1814143201718247424",
"2054502269576728775","Wed May 13 10:01:26 +0000 2026","0","Kebijakan komdigi soal ongkir sangat merugikan konsumen.","2054502269576728775","","","in","","0","0","0","https://x.com/undefined/status/2054502269576728775","1814143201718247424",
"2055001478004367487","Thu May 14 19:05:07 +0000 2026","0","maksud dari komdigi bikin kebijakan gratis ongkir ini apa yaaa?","2055001478004367487","","","in","","0","0","0","https://x.com/undefined/status/2055001478004367487","2043979880086339584",
"2054502958315020394","Wed May 13 10:04:10 +0000 2026","0","Komdigi disebut dalam diskusi mengenai free ongkir.","2054502958315020394","","","in","","0","0","0","https://x.com/undefined/status/2054502958315020394","1814143201718247424",
"2054502618484134392","Wed May 13 10:02:49 +0000 2026","0","@komdigi kenapa sih harus ngurusin ongkir segala???","2054502618484134392","","","in","","0","0","0","https://x.com/undefined/status/2054502618484134392","1814143201718247424",
"2054996678391091685","Thu May 14 18:46:02 +0000 2026","0","komdigi ongkir mending sampingkan dulu","2054996678391091685","","","in","","0","0","0","https://x.com/undefined/status/2054996678391091685","1814143201718247424",
"2054502657201733861","Wed May 13 10:02:58 +0000 2026","0","Gratis ongkir dibatasi? keputusan paling aneh tahun ini.","2054502657201733861","","","in","","0","0","0","https://x.com/undefined/status/2054502657201733861","1814143201718247424",
"2054501981369352445","Wed May 13 10:00:17 +0000 2026","0","Gratis ongkir dibatasi malah bikin marketplace lebih fair.","2054501981369352445","","","in","","0","0","0","https://x.com/undefined/status/2054501981369352445","1814143201718247424",
"2054839912529350807","Thu May 14 08:23:06 +0000 2026","0","komdigi mending ngurusin lainnya deh dsripada ngurusin ongkir giniii","2054839912529350807","","","in","","0","0","0","https://x.com/undefined/status/2054839912529350807","1814143201718247424",
"2054502817910706448","Wed May 13 10:03:37 +0000 2026","0","Saya membaca berita tentang gratis ongkir dibatasi.","2054502817910706448","","","in","","0","0","0","https://x.com/undefined/status/2054502817910706448","1814143201718247424",
"2054502131672236531","Wed May 13 10:00:53 +0000 2026","0","kebijakan komdigi tentang ongkir patut diapresiasi.","2054502131672236531","","","in","","0","0","0","https://x.com/undefined/status/2054502131672236531","1814143201718247424", "2054502131672236531","Wed May 13 10:00:53 +0000 2026","0","kebijakan komdigi tentang ongkir patut diapresiasi.","2054502131672236531","","","in","","0","0","0","https://x.com/undefined/status/2054502131672236531","1814143201718247424",
"2054478880933855563","Wed May 13 08:28:30 +0000 2026","0","KOMDIGI KNP NGURUSIN ONGKIR SIH??","2054478880933855563","","","in","","0","0","0","https://x.com/undefined/status/2054478880933855563","1814143201718247424",
"2054502618484134392","Wed May 13 10:02:49 +0000 2026","0","@komdigi kenapa sih harus ngurusin ongkir segala???","2054502618484134392","","","in","","0","0","0","https://x.com/undefined/status/2054502618484134392","1814143201718247424",
"2054816992662790146","Thu May 14 06:52:02 +0000 2026","0","komdigi??? ongkir??? marketplace???","2054816992662790146","","","in","","0","0","0","https://x.com/undefined/status/2054816992662790146","1814143201718247424",
"2054502958315020394","Wed May 13 10:04:10 +0000 2026","0","Komdigi disebut dalam diskusi mengenai free ongkir.","2054502958315020394","","","in","","0","0","0","https://x.com/undefined/status/2054502958315020394","1814143201718247424",
"2054501981369352445","Wed May 13 10:00:17 +0000 2026","0","Gratis ongkir dibatasi malah bikin marketplace lebih fair.","2054501981369352445","","","in","","0","0","0","https://x.com/undefined/status/2054501981369352445","1814143201718247424",
"2054502181446078852","Wed May 13 10:01:05 +0000 2026","0","Menurut saya pembatasan gratis ongkir adalah keputusan tepat","2054502181446078852","","","in","","0","0","0","https://x.com/undefined/status/2054502181446078852","1814143201718247424",
"2054816880318427497","Thu May 14 06:51:35 +0000 2026","0","Ada diskusi publik mengenai kebijakan ongkir dari Komdigi.","2054816880318427497","","","in","","0","0","0","https://x.com/undefined/status/2054816880318427497","1814143201718247424",
"2054816818741862819","Thu May 14 06:51:20 +0000 2026","0","Saya melihat berita tentang komdigi dan ongkir tadi pagi.","2054816818741862819","","","in","","0","0","0","https://x.com/undefined/status/2054816818741862819","1814143201718247424",
"2054501862066524547","Wed May 13 09:59:49 +0000 2026","0","Saya setuju kebijakan Komdigi soal gratis ongkir dibatasi biar persaingan lebih sehat.","2054501862066524547","","","in","","0","0","0","https://x.com/undefined/status/2054501862066524547","1814143201718247424",
"2054502430956769299","Wed May 13 10:02:05 +0000 2026","0","Pembatasan gratis ongkir sangat mengecewakan.","2054502430956769299","","","in","","0","0","0","https://x.com/undefined/status/2054502430956769299","1814143201718247424",
"2054502817910706448","Wed May 13 10:03:37 +0000 2026","0","Saya membaca berita tentang gratis ongkir dibatasi.","2054502817910706448","","","in","","0","0","0","https://x.com/undefined/status/2054502817910706448","1814143201718247424",
"2054791169775964388","Thu May 14 05:09:25 +0000 2026","0","kebijakan komdigi gratis ongkir kerenn","2054791169775964388","","","in","","0","0","0","https://x.com/undefined/status/2054791169775964388","1814143201718247424",
"2054502657201733861","Wed May 13 10:02:58 +0000 2026","0","Gratis ongkir dibatasi? keputusan paling aneh tahun ini.","2054502657201733861","","","in","","0","0","0","https://x.com/undefined/status/2054502657201733861","1814143201718247424",
"2054502713959014566","Wed May 13 10:03:12 +0000 2026","0","Gratis ongkir dibatasi = belanja online makin mahal ","2054502713959014566","","","in","","0","0","0","https://x.com/undefined/status/2054502713959014566","1814143201718247424",

1 conversation_id_str created_at favorite_count full_text id_str image_url in_reply_to_screen_name lang location quote_count reply_count retweet_count tweet_url user_id_str username
2054791169775964388 Thu May 14 05:09:25 +0000 2026 0 kebijakan komdigi gratis ongkir kerenn 2054791169775964388 in 0 0 0 https://x.com/undefined/status/2054791169775964388 1814143201718247424
2055002136027767200 Thu May 14 19:07:43 +0000 2026 0 komdigi ongkir apa gunanyaa??222 2055002136027767200 in 0 0 0 https://x.com/undefined/status/2055002136027767200 2043979880086339584
2054861268750901484 Thu May 14 09:47:58 +0000 2026 0 komdigi ongkir? 2054861268750901484 in 0 0 0 https://x.com/undefined/status/2054861268750901484 1814143201718247424
2054816992662790146 Thu May 14 06:52:02 +0000 2026 0 komdigi??? ongkir??? marketplace??? 2054816992662790146 in 0 0 0 https://x.com/undefined/status/2054816992662790146 1814143201718247424
2054823109291852155 Thu May 14 07:16:20 +0000 2026 0 komdigi bikin aturan ongkir baru = langkah yang cukup bijak 2054823109291852155 in 0 0 0 https://x.com/undefined/status/2054823109291852155 1814143201718247424
2055269612334555468 Fri May 15 12:50:35 +0000 2026 0 komdigi + ongkir = chaos wkwkwk 2055269612334555468 in 0 0 0 https://x.com/undefined/status/2055269612334555468 2043979880086339584
2054998005359751518 Thu May 14 18:51:19 +0000 2026 0 komdigi ongkir apa gunanyaa?? 2054998005359751518 in 0 0 0 https://x.com/undefined/status/2054998005359751518 2043979880086339584
2054816818741862819 Thu May 14 06:51:20 +0000 2026 0 Saya melihat berita tentang komdigi dan ongkir tadi pagi. 2054816818741862819 in 0 0 0 https://x.com/undefined/status/2054816818741862819 1814143201718247424
2054502430956769299 Wed May 13 10:02:05 +0000 2026 0 Pembatasan gratis ongkir sangat mengecewakan. 2054502430956769299 in 0 0 0 https://x.com/undefined/status/2054502430956769299 1814143201718247424
2054816635131994490 Thu May 14 06:50:37 +0000 2026 0 keren sih ada kebijakan dari komdigi ongkir jadi berasa lebih merataa 2054816635131994490 in 0 0 0 https://x.com/undefined/status/2054816635131994490 1814143201718247424
2 2054502269576728775 Wed May 13 10:01:26 +0000 2026 0 Kebijakan komdigi soal ongkir sangat merugikan konsumen. 2054502269576728775 in 0 0 0 https://x.com/undefined/status/2054502269576728775 1814143201718247424
2055001478004367487 Thu May 14 19:05:07 +0000 2026 0 maksud dari komdigi bikin kebijakan gratis ongkir ini apa yaaa? 2055001478004367487 in 0 0 0 https://x.com/undefined/status/2055001478004367487 2043979880086339584
2054502958315020394 Wed May 13 10:04:10 +0000 2026 0 Komdigi disebut dalam diskusi mengenai free ongkir. 2054502958315020394 in 0 0 0 https://x.com/undefined/status/2054502958315020394 1814143201718247424
2054502618484134392 Wed May 13 10:02:49 +0000 2026 0 @komdigi kenapa sih harus ngurusin ongkir segala??? 2054502618484134392 in 0 0 0 https://x.com/undefined/status/2054502618484134392 1814143201718247424
2054996678391091685 Thu May 14 18:46:02 +0000 2026 0 komdigi ongkir mending sampingkan dulu 2054996678391091685 in 0 0 0 https://x.com/undefined/status/2054996678391091685 1814143201718247424
2054502657201733861 Wed May 13 10:02:58 +0000 2026 0 Gratis ongkir dibatasi? keputusan paling aneh tahun ini. 2054502657201733861 in 0 0 0 https://x.com/undefined/status/2054502657201733861 1814143201718247424
2054501981369352445 Wed May 13 10:00:17 +0000 2026 0 Gratis ongkir dibatasi malah bikin marketplace lebih fair. 2054501981369352445 in 0 0 0 https://x.com/undefined/status/2054501981369352445 1814143201718247424
2054839912529350807 Thu May 14 08:23:06 +0000 2026 0 komdigi mending ngurusin lainnya deh dsripada ngurusin ongkir giniii 2054839912529350807 in 0 0 0 https://x.com/undefined/status/2054839912529350807 1814143201718247424
2054502817910706448 Wed May 13 10:03:37 +0000 2026 0 Saya membaca berita tentang gratis ongkir dibatasi. 2054502817910706448 in 0 0 0 https://x.com/undefined/status/2054502817910706448 1814143201718247424
2054502131672236531 Wed May 13 10:00:53 +0000 2026 0 kebijakan komdigi tentang ongkir patut diapresiasi. 2054502131672236531 in 0 0 0 https://x.com/undefined/status/2054502131672236531 1814143201718247424
conversation_id_str created_at favorite_count full_text id_str image_url in_reply_to_screen_name lang location quote_count reply_count retweet_count tweet_url user_id_str username
2054791169775964388 Thu May 14 05:09:25 +0000 2026 0 kebijakan komdigi gratis ongkir kerenn 2054791169775964388 in 0 0 0 https://x.com/undefined/status/2054791169775964388 1814143201718247424
2055002136027767200 Thu May 14 19:07:43 +0000 2026 0 komdigi ongkir apa gunanyaa??222 2055002136027767200 in 0 0 0 https://x.com/undefined/status/2055002136027767200 2043979880086339584
2054861268750901484 Thu May 14 09:47:58 +0000 2026 0 komdigi ongkir? 2054861268750901484 in 0 0 0 https://x.com/undefined/status/2054861268750901484 1814143201718247424
2054816992662790146 Thu May 14 06:52:02 +0000 2026 0 komdigi??? ongkir??? marketplace??? 2054816992662790146 in 0 0 0 https://x.com/undefined/status/2054816992662790146 1814143201718247424
3 2054823109291852155 Thu May 14 07:16:20 +0000 2026 0 komdigi bikin aturan ongkir baru = langkah yang cukup bijak 2054823109291852155 in 0 0 0 https://x.com/undefined/status/2054823109291852155 1814143201718247424
4 2055269612334555468 2054502892468662645 Fri May 15 12:50:35 +0000 2026 Wed May 13 10:03:55 +0000 2026 0 komdigi + ongkir = chaos wkwkwk Komdigi dan gratis ongkir sedang ramai dibahas. 2055269612334555468 2054502892468662645 in 0 0 0 https://x.com/undefined/status/2055269612334555468 https://x.com/undefined/status/2054502892468662645 2043979880086339584 1814143201718247424
5 2054998005359751518 2054501918895202348 Thu May 14 18:51:19 +0000 2026 Wed May 13 10:00:02 +0000 2026 0 komdigi ongkir apa gunanyaa?? Mantap sih @komdigi akhirnya free ongkir diatur juga 2054998005359751518 2054501918895202348 in 0 0 0 https://x.com/undefined/status/2054998005359751518 https://x.com/undefined/status/2054501918895202348 2043979880086339584 1814143201718247424
6 2054816818741862819 2054861268750901484 Thu May 14 06:51:20 +0000 2026 Thu May 14 09:47:58 +0000 2026 0 Saya melihat berita tentang komdigi dan ongkir tadi pagi. komdigi ongkir? 2054816818741862819 2054861268750901484 in 0 0 0 https://x.com/undefined/status/2054816818741862819 https://x.com/undefined/status/2054861268750901484 1814143201718247424
2054502430956769299 Wed May 13 10:02:05 +0000 2026 0 Pembatasan gratis ongkir sangat mengecewakan. 2054502430956769299 in 0 0 0 https://x.com/undefined/status/2054502430956769299 1814143201718247424
2054816635131994490 Thu May 14 06:50:37 +0000 2026 0 keren sih ada kebijakan dari komdigi ongkir jadi berasa lebih merataa 2054816635131994490 in 0 0 0 https://x.com/undefined/status/2054816635131994490 1814143201718247424
2054502269576728775 Wed May 13 10:01:26 +0000 2026 0 Kebijakan komdigi soal ongkir sangat merugikan konsumen. 2054502269576728775 in 0 0 0 https://x.com/undefined/status/2054502269576728775 1814143201718247424
2055001478004367487 Thu May 14 19:05:07 +0000 2026 0 maksud dari komdigi bikin kebijakan gratis ongkir ini apa yaaa? 2055001478004367487 in 0 0 0 https://x.com/undefined/status/2055001478004367487 2043979880086339584
2054502958315020394 Wed May 13 10:04:10 +0000 2026 0 Komdigi disebut dalam diskusi mengenai free ongkir. 2054502958315020394 in 0 0 0 https://x.com/undefined/status/2054502958315020394 1814143201718247424
2054502618484134392 Wed May 13 10:02:49 +0000 2026 0 @komdigi kenapa sih harus ngurusin ongkir segala??? 2054502618484134392 in 0 0 0 https://x.com/undefined/status/2054502618484134392 1814143201718247424
2054996678391091685 Thu May 14 18:46:02 +0000 2026 0 komdigi ongkir mending sampingkan dulu 2054996678391091685 in 0 0 0 https://x.com/undefined/status/2054996678391091685 1814143201718247424
2054502657201733861 Wed May 13 10:02:58 +0000 2026 0 Gratis ongkir dibatasi? keputusan paling aneh tahun ini. 2054502657201733861 in 0 0 0 https://x.com/undefined/status/2054502657201733861 1814143201718247424
2054501981369352445 Wed May 13 10:00:17 +0000 2026 0 Gratis ongkir dibatasi malah bikin marketplace lebih fair. 2054501981369352445 in 0 0 0 https://x.com/undefined/status/2054501981369352445 1814143201718247424
2054839912529350807 Thu May 14 08:23:06 +0000 2026 0 komdigi mending ngurusin lainnya deh dsripada ngurusin ongkir giniii 2054839912529350807 in 0 0 0 https://x.com/undefined/status/2054839912529350807 1814143201718247424
2054502817910706448 Wed May 13 10:03:37 +0000 2026 0 Saya membaca berita tentang gratis ongkir dibatasi. 2054502817910706448 in 0 0 0 https://x.com/undefined/status/2054502817910706448 1814143201718247424
7 2054502131672236531 Wed May 13 10:00:53 +0000 2026 0 kebijakan komdigi tentang ongkir patut diapresiasi. 2054502131672236531 in 0 0 0 https://x.com/undefined/status/2054502131672236531 1814143201718247424
8 2054478880933855563 Wed May 13 08:28:30 +0000 2026 0 KOMDIGI KNP NGURUSIN ONGKIR SIH?? 2054478880933855563 in 0 0 0 https://x.com/undefined/status/2054478880933855563 1814143201718247424
9 2054502618484134392 Wed May 13 10:02:49 +0000 2026 0 @komdigi kenapa sih harus ngurusin ongkir segala??? 2054502618484134392 in 0 0 0 https://x.com/undefined/status/2054502618484134392 1814143201718247424
10 2054816992662790146 Thu May 14 06:52:02 +0000 2026 0 komdigi??? ongkir??? marketplace??? 2054816992662790146 in 0 0 0 https://x.com/undefined/status/2054816992662790146 1814143201718247424
11 2054502958315020394 Wed May 13 10:04:10 +0000 2026 0 Komdigi disebut dalam diskusi mengenai free ongkir. 2054502958315020394 in 0 0 0 https://x.com/undefined/status/2054502958315020394 1814143201718247424
12 2054501981369352445 Wed May 13 10:00:17 +0000 2026 0 Gratis ongkir dibatasi malah bikin marketplace lebih fair. 2054501981369352445 in 0 0 0 https://x.com/undefined/status/2054501981369352445 1814143201718247424
13 2054502181446078852 Wed May 13 10:01:05 +0000 2026 0 Menurut saya pembatasan gratis ongkir adalah keputusan tepat 2054502181446078852 in 0 0 0 https://x.com/undefined/status/2054502181446078852 1814143201718247424
14 2054816880318427497 Thu May 14 06:51:35 +0000 2026 0 Ada diskusi publik mengenai kebijakan ongkir dari Komdigi. 2054816880318427497 in 0 0 0 https://x.com/undefined/status/2054816880318427497 1814143201718247424
15 2054816818741862819 Thu May 14 06:51:20 +0000 2026 0 Saya melihat berita tentang komdigi dan ongkir tadi pagi. 2054816818741862819 in 0 0 0 https://x.com/undefined/status/2054816818741862819 1814143201718247424
16 2054501862066524547 Wed May 13 09:59:49 +0000 2026 0 Saya setuju kebijakan Komdigi soal gratis ongkir dibatasi biar persaingan lebih sehat. 2054501862066524547 in 0 0 0 https://x.com/undefined/status/2054501862066524547 1814143201718247424
17 2054502430956769299 Wed May 13 10:02:05 +0000 2026 0 Pembatasan gratis ongkir sangat mengecewakan. 2054502430956769299 in 0 0 0 https://x.com/undefined/status/2054502430956769299 1814143201718247424
18 2054502817910706448 Wed May 13 10:03:37 +0000 2026 0 Saya membaca berita tentang gratis ongkir dibatasi. 2054502817910706448 in 0 0 0 https://x.com/undefined/status/2054502817910706448 1814143201718247424
19 2054791169775964388 Thu May 14 05:09:25 +0000 2026 0 kebijakan komdigi gratis ongkir kerenn 2054791169775964388 in 0 0 0 https://x.com/undefined/status/2054791169775964388 1814143201718247424
20 2054502657201733861 Wed May 13 10:02:58 +0000 2026 0 Gratis ongkir dibatasi? keputusan paling aneh tahun ini. 2054502657201733861 in 0 0 0 https://x.com/undefined/status/2054502657201733861 1814143201718247424
21 2054502713959014566 Wed May 13 10:03:12 +0000 2026 0 Gratis ongkir dibatasi = belanja online makin mahal 2054502713959014566 in 0 0 0 https://x.com/undefined/status/2054502713959014566 1814143201718247424