analisisNews / app /analyzers /fakescore.py
ahmadsayadi's picture
feat: add emotion, framing, fake-score, opinion-fact endpoints
599f4e5
Raw
History Blame Contribute Delete
2.77 kB
"""
Fake news score (heuristik).
Skor 0-100 indikasi potensi hoax/misinformasi berdasarkan pola teks.
"""
from typing import List, Dict
import re
# Indikator clickbait/hoax
HOAX_INDICATORS = [
"terungkap", "ternyata", "rahasia", "viral", "heboh", "bikin",
"terbongkar", "fakta mencengangkan", "anda harus tahu",
"jangan sampai", "ini dia", "wow", "gempar",
]
CREDIBILITY_MARKERS = [
"menurut", "berdasarkan", "data", "riset", "penelitian",
"sumber", "narasumber", "konfirmasi", "verifikasi", "resmi",
]
def calculate_fake_score(text: str, title: str = "") -> Dict:
text_lower = (title + " " + text).lower()
score = 0
reasons = []
# 1. Kata-kata pemicu hoax di judul
title_lower = title.lower()
hoax_hits = sum(1 for w in HOAX_INDICATORS if w in title_lower)
if hoax_hits > 0:
score += min(30, hoax_hits * 15)
reasons.append(f"{hoax_hits} kata pemicu hoax")
# 2. Tanda seru/tanya berlebihan
excl = title.count("!") + title.count("?")
if excl > 1:
score += min(15, excl * 7)
reasons.append(f"{excl} tanda seru/tanya")
# 3. ALL CAPS
caps = len(re.findall(r'\b[A-Z]{3,}\b', title))
if caps > 1:
score += min(15, caps * 7)
reasons.append(f"{caps} kata KAPITAL")
# 4. Tidak ada sumber/narasumber
cred_hits = sum(1 for w in CREDIBILITY_MARKERS if w in text_lower)
if cred_hits == 0:
score += 20
reasons.append("tidak ada sumber terverifikasi")
elif cred_hits >= 3:
score -= 10
reasons.append(f"{cred_hits} marker kredibilitas")
# 5. Teks sangat pendek (kurang substansi)
word_count = len(text.split())
if word_count < 50:
score += 15
reasons.append("konten sangat pendek")
# 6. Banyak klaim tanpa bukti (kalimat deklaratif tanpa attributor)
sentences = re.split(r'[.!?]', text)
declarative = sum(1 for s in sentences if len(s.strip()) > 20 and not any(m in s.lower() for m in CREDIBILITY_MARKERS))
ratio = declarative / max(len(sentences), 1)
if ratio > 0.8:
score += 10
reasons.append("mayoritas klaim tanpa atribusi")
score = max(0, min(100, score))
level = "tinggi" if score >= 60 else "sedang" if score >= 30 else "rendah"
return {"score": score, "level": level, "reasons": reasons}
def analyze_batch(items: List) -> List[Dict]:
results = []
for item in items:
# Pisah title dari text (asumsi: kalimat pertama = title)
parts = item.text.split(". ", 1)
title = parts[0] if len(parts) > 1 else ""
content = parts[1] if len(parts) > 1 else item.text
result = calculate_fake_score(content, title)
results.append({"id": item.id, **result})
return results