Spaces:
Running
Running
import re | |
import string | |
import numpy as np | |
from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer | |
from collections import Counter | |
import logging | |
logger = logging.getLogger(__name__) | |
class KeywordExtractor: | |
""" | |
Metin içindeki anahtar kelimeleri çıkaran sınıf. | |
TF-IDF, rakip kelimeler ve diğer metotlarla anahtar kelime çıkarma işlemi yapar. | |
""" | |
def __init__(self): | |
"""Anahtar kelime çıkarıcıyı başlatır""" | |
# Türkçe stopwords (durma kelimeleri) | |
self.turkish_stopwords = [ | |
've', 'veya', 'ile', 'için', 'bu', 'bir', 'ya', 'de', 'da', 'ki', 'ne', 'her', 'çok', | |
'daha', 'ama', 'fakat', 'lakin', 'ancak', 'gibi', 'kadar', 'sonra', 'önce', 'göre', | |
'nasıl', 'neden', 'şey', 'ben', 'sen', 'o', 'biz', 'siz', 'onlar', 'kendi', 'aynı', | |
'ise', 'mi', 'mı', 'mu', 'mü', 'hem', 'değil', 'hiç', 'olarak', 'evet', 'hayır', | |
'belki', 'tüm', 'yani', 'hep', 'şu', 'şey', 'tabi', 'tamam', 'bunlar', 'şunlar', | |
'böyle', 'öyle', 'şöyle', 'iki', 'üç', 'dört', 'beş', 'altı', 'yedi', 'sekiz', 'dokuz', | |
'on', 'yüz', 'bin', 'milyon', 'milyar', 'var', 'yok', 'oldu', 'olur', 'oluyor', 'olacak' | |
] | |
# İngilizce stopwords (durma kelimeleri) | |
self.english_stopwords = [ | |
'the', 'and', 'a', 'to', 'of', 'in', 'for', 'with', 'on', 'at', 'by', 'from', 'about', | |
'as', 'into', 'like', 'through', 'after', 'over', 'between', 'out', 'against', 'during', | |
'without', 'before', 'under', 'around', 'among', 'is', 'are', 'was', 'were', 'be', 'been', | |
'being', 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'shall', 'should', | |
'may', 'might', 'must', 'can', 'could', 'i', 'you', 'he', 'she', 'it', 'we', 'they', | |
'me', 'him', 'her', 'us', 'them', 'who', 'which', 'whose', 'whom', 'this', 'that', 'these', | |
'those', 'am', 'is', 'are', 'was', 'were', 'an', 'my', 'your', 'his', 'its', 'our', 'their' | |
] | |
# Tüm stopwords listesini birleştir | |
self.stopwords = set(self.turkish_stopwords + self.english_stopwords) | |
# TF-IDF vektörleyici | |
self.tfidf_vectorizer = TfidfVectorizer( | |
max_df=0.9, | |
min_df=2, | |
max_features=200, | |
stop_words=self.stopwords, | |
ngram_range=(1, 2) # Tek kelimeler ve ikili kelime grupları | |
) | |
# Sayısal karakter ve noktalama işaretlerini temizlemek için regex pattern | |
self.cleanup_pattern = re.compile(f'[{re.escape(string.punctuation)}]|[0-9]') | |
logger.info("Anahtar kelime çıkarıcı başlatıldı") | |
def preprocess_text(self, text): | |
""" | |
Metni anahtar kelime çıkarma için ön işleme tabi tutar | |
Args: | |
text: İşlenecek metin | |
Returns: | |
str: Temizlenmiş metin | |
""" | |
if not text: | |
return "" | |
# Küçük harfe çevir | |
text = text.lower() | |
# Noktalama işaretlerini temizle | |
text = self.cleanup_pattern.sub(' ', text) | |
# Fazla boşlukları temizle | |
text = re.sub(r'\s+', ' ', text).strip() | |
return text | |
def extract_keywords_tfidf(self, text, num_keywords=5): | |
""" | |
TF-IDF kullanarak metinden anahtar kelimeleri çıkarır | |
Args: | |
text: Anahtar kelimeleri çıkarılacak metin | |
num_keywords: Çıkarılacak anahtar kelime sayısı | |
Returns: | |
list: [(anahtar_kelime, skor), ...] formatında liste | |
""" | |
try: | |
if not text or len(text.strip()) < 10: | |
return [] | |
# Metni ön işle | |
processed_text = self.preprocess_text(text) | |
# TF-IDF matrix oluştur | |
tfidf_matrix = self.tfidf_vectorizer.fit_transform([processed_text]) | |
# Feature isimleri (kelimeler) | |
feature_names = self.tfidf_vectorizer.get_feature_names_out() | |
# Kelimelerin TF-IDF skorlarını hesapla ve sırala | |
tfidf_scores = zip(feature_names, tfidf_matrix.toarray()[0]) | |
sorted_scores = sorted(tfidf_scores, key=lambda x: x[1], reverse=True) | |
# En yüksek skorlu kelimeleri seç | |
top_keywords = sorted_scores[:num_keywords] | |
return top_keywords | |
except Exception as e: | |
logger.error(f"TF-IDF anahtar kelime çıkarma hatası: {str(e)}") | |
return [] | |
def extract_keywords_textrank(self, text, num_keywords=5): | |
""" | |
TextRank benzeri bir algoritma ile anahtar kelimeleri çıkarır | |
Args: | |
text: Anahtar kelimeleri çıkarılacak metin | |
num_keywords: Çıkarılacak anahtar kelime sayısı | |
Returns: | |
list: [(anahtar_kelime, skor), ...] formatında liste | |
""" | |
try: | |
if not text or len(text.strip()) < 10: | |
return [] | |
# Metni ön işle | |
processed_text = self.preprocess_text(text) | |
# Kelimeleri ayır | |
words = processed_text.split() | |
# Stopwords olmayan kelimeleri filtrele | |
filtered_words = [word for word in words if word not in self.stopwords and len(word) > 2] | |
# Kelime frekanslarını hesapla | |
word_freq = Counter(filtered_words) | |
# En sık geçen kelimeleri seç | |
most_common = word_freq.most_common(num_keywords * 2) # Daha fazla al, sonra filtreleyeceğiz | |
# TF-IDF skorlaması ile benzer bir yaklaşım uygula | |
# Kelime sıklığının logaritması * kelimenin benzersizliği | |
scored_words = [] | |
for word, count in most_common: | |
# Benzersizlik faktörü: Toplam kelime sayısı / kelimenin sıklığı | |
uniqueness = len(filtered_words) / (count + 1) | |
# Skor hesapla | |
score = np.log(count + 1) * uniqueness | |
scored_words.append((word, score)) | |
# Skorlara göre sırala | |
scored_words.sort(key=lambda x: x[1], reverse=True) | |
return scored_words[:num_keywords] | |
except Exception as e: | |
logger.error(f"TextRank anahtar kelime çıkarma hatası: {str(e)}") | |
return [] | |
def extract_bigrams(self, text, num_bigrams=3): | |
""" | |
Metinden ikili kelime gruplarını (bigram) çıkarır | |
Args: | |
text: Anahtar kelimeleri çıkarılacak metin | |
num_bigrams: Çıkarılacak bigram sayısı | |
Returns: | |
list: [(bigram, skor), ...] formatında liste | |
""" | |
try: | |
if not text or len(text.strip()) < 10: | |
return [] | |
# Metni ön işle | |
processed_text = self.preprocess_text(text) | |
# Bigram için vektörleyici | |
bigram_vectorizer = CountVectorizer( | |
ngram_range=(2, 2), | |
stop_words=self.stopwords, | |
max_features=100 | |
) | |
# Bigram matrix oluştur | |
bigram_matrix = bigram_vectorizer.fit_transform([processed_text]) | |
# Feature isimleri (bigramlar) | |
feature_names = bigram_vectorizer.get_feature_names_out() | |
# Bigramların skorlarını hesapla ve sırala | |
bigram_scores = zip(feature_names, bigram_matrix.toarray()[0]) | |
sorted_scores = sorted(bigram_scores, key=lambda x: x[1], reverse=True) | |
# En yüksek skorlu bigramları seç | |
top_bigrams = sorted_scores[:num_bigrams] | |
return top_bigrams | |
except Exception as e: | |
logger.error(f"Bigram çıkarma hatası: {str(e)}") | |
return [] | |
def extract_keywords(self, text, method='combined', num_keywords=10): | |
""" | |
Metinden anahtar kelimeleri çıkarır | |
Args: | |
text: Anahtar kelimeleri çıkarılacak metin | |
method: Kullanılacak metod ('tfidf', 'textrank', 'combined') | |
num_keywords: Toplam çıkarılacak anahtar kelime sayısı | |
Returns: | |
dict: { | |
'keywords': [(anahtar_kelime, skor), ...], | |
'bigrams': [(bigram, skor), ...], | |
'method': kullanılan metod | |
} | |
""" | |
if not text or len(text.strip()) < 10: | |
return { | |
'keywords': [], | |
'bigrams': [], | |
'method': method | |
} | |
try: | |
keywords = [] | |
if method == 'tfidf': | |
keywords = self.extract_keywords_tfidf(text, num_keywords) | |
elif method == 'textrank': | |
keywords = self.extract_keywords_textrank(text, num_keywords) | |
else: # combined | |
# TF-IDF ve TextRank sonuçlarını birleştir | |
tfidf_keywords = self.extract_keywords_tfidf(text, num_keywords // 2) | |
textrank_keywords = self.extract_keywords_textrank(text, num_keywords // 2) | |
# İki listeyi birleştir | |
combined = {} | |
for keyword, score in tfidf_keywords + textrank_keywords: | |
if keyword in combined: | |
combined[keyword] = max(combined[keyword], score) | |
else: | |
combined[keyword] = score | |
# En yüksek skorlu kelimeleri seç | |
keywords = sorted(combined.items(), key=lambda x: x[1], reverse=True)[:num_keywords] | |
# Bigramları da ekle | |
bigrams = self.extract_bigrams(text, num_keywords // 3) | |
return { | |
'keywords': keywords, | |
'bigrams': bigrams, | |
'method': method | |
} | |
except Exception as e: | |
logger.error(f"Anahtar kelime çıkarma hatası: {str(e)}") | |
return { | |
'keywords': [], | |
'bigrams': [], | |
'method': method | |
} |