from underthesea import word_tokenize import re # Một số từ cảm xúc / miêu tả sản phẩm thường gặp SENTIMENT_KEYWORDS = { "tệ", "xấu", "dở", "kém", "chán", "đắt", "lừa", "giả", "thất vọng", "tuyệt", "đẹp", "xịn", "rẻ", "ổn", "tốt", "ngon", "chất lượng", "ok", "hài lòng", "ưng", "đáng tiền", "cực kỳ", "quá", "rất", "hơi", "ghê", "gớm", "xấu", "dễ thương", "xịn sò", "xịn xò", "thích", "ghét", "chán", "mệt", "vui", "buồn", "tuyệt vời", "đáng mua", "khuyên dùng" } # Một số viết tắt phổ biến trong review ABBREVIATIONS = { "ko": "không", "k": "không", "khum": "không", "hok": "không", "đc": "được", "dc": "được", "okie": "ok", "ok": "ok", "sp": "sản phẩm", "tp": "thành phần", "nv": "nhân viên", "gt": "giá tiền", "mn": "mọi người", "rep": "trả lời", "rat": "rất" } def preprocess_text(text: str) -> str: """Tiền xử lý tiếng Việt tập trung cho sentiment & mô tả sản phẩm.""" text = text.strip().lower() # Xóa link, mention, hashtag text = re.sub(r"http\S+|www\S+|@\w+|#\w+", " ", text) # Loại bỏ ký tự không phải chữ (trừ dấu câu cơ bản) text = re.sub(r"[^a-zàáạảãâầấậẩẫăằắặẳẵèéẹẻẽêềếệểễ" r"ìíịỉĩòóọỏõôồốộổỗơờớợởỡùúụủũưừứựửữ" r"ỳýỵỷỹđ\s\!\?\.]", " ", text) # Chuẩn hóa khoảng trắng text = re.sub(r"\s+", " ", text) # Chuẩn hóa từ viết tắt words = text.split() words = [ABBREVIATIONS.get(w, w) for w in words] text = " ".join(words) segmented = word_tokenize(text, format="text") # Giữ lại các từ quan trọng cho cảm xúc tokens = segmented.split() filtered = [ w for w in tokens if len(w) > 1 and ( w in SENTIMENT_KEYWORDS or re.match(r"[a-zàáạảãâầấậẩẫăằắặẳẵèéẹẻẽêềếệểễìíịỉĩòóọỏõôồốộổỗơờớợởỡùúụủũưừứựửữỳýỵỷỹđ]", w) ) ] return " ".join(filtered)