textqualtox / utils /text_improver.py
sarizeybekk
Remove venv from Git tracking and add to .gitignore
bd97f47
import re
import logging
import string
from collections import Counter
logger = logging.getLogger(__name__)
class TextImprover:
"""
Türkçe metinlerde iyileştirme ve öneriler sunan sınıf.
Yazım hataları düzeltme, dilbilgisi önerileri ve okunabilirlik analizi yapar.
"""
def __init__(self):
"""Metin iyileştirme sınıfını başlatır"""
# Türkçe'de yaygın yazım hataları ve düzeltmeleri
self.common_typos = {
# Büyük küçük harf duyarsız olarak yazım hataları
'bişey': 'bir şey',
'herşey': 'her şey',
'hiçbirşey': 'hiçbir şey',
'birsey': 'bir şey',
'hersey': 'her şey',
'hicbir': 'hiçbir',
'hicbirsey': 'hiçbir şey',
'yalnız': 'yalnız',
'bi': 'bir',
'gelicek': 'gelecek',
'gidiyom': 'gidiyorum',
'yapıyom': 'yapıyorum',
'biliyomusun': 'biliyor musun',
'napıyorsun': 'ne yapıyorsun',
'naber': 'ne haber',
'bilmiyomki': 'bilmiyorum ki',
'dicek': 'diyecek',
'dicem': 'diyeceğim',
'yicek': 'yiyecek',
'yicem': 'yiyeceğim'
}
# Türkçe'de sık kullanılan doldurma kelimeleri
self.filler_words = [
'yani', 'işte', 'şey', 'falan', 'filan', 'hani', 'mesela',
'aslında', 'ya', 'ki', 'de', 'da', 'ama', 'fakat', 'lakin',
'gerçekten', 'kesinlikle', 'tabii', 'tabi', 'şimdi', 'sonra'
]
# Türkçe cümle karmaşıklığını değerlendirmek için parametreler
self.max_sentence_length = 25 # Kelime sayısı
self.max_word_length = 6 # Ortalama kelime uzunluğu
# Okunabilirlik için kullanılacak parametreler
# Türkçe için uyarlanmış Flesch Reading Ease formülü
self.readability_thresholds = {
'çok_kolay': 90,
'kolay': 80,
'orta_kolay': 70,
'orta': 60,
'orta_zor': 50,
'zor': 30,
'çok_zor': 0
}
logger.info("Metin iyileştirme modülü başlatıldı")
def fix_typos(self, text):
"""
Metindeki yaygın yazım hatalarını düzeltir
Args:
text: Düzeltilecek metin
Returns:
dict: {
'corrected_text': str, # Düzeltilmiş metin
'corrections': list, # Yapılan düzeltmeler listesi
'correction_count': int # Düzeltme sayısı
}
"""
corrected_text = text
corrections = []
# Önce metni kelimelere ayır
words = re.findall(r'\b\w+\b', text.lower())
# Her kelimeyi kontrol et
for word in words:
if word.lower() in self.common_typos:
correct_word = self.common_typos[word.lower()]
# Kelimenin metindeki tüm örneklerini düzelt
# \b ile kelime sınırlarını belirt
pattern = r'\b' + re.escape(word) + r'\b'
corrected_text = re.sub(pattern, correct_word, corrected_text, flags=re.IGNORECASE)
corrections.append(f"'{word}' -> '{correct_word}'")
return {
'corrected_text': corrected_text,
'corrections': corrections,
'correction_count': len(corrections)
}
def check_grammar(self, text):
"""
Metindeki temel dilbilgisi sorunlarını kontrol eder
Args:
text: Kontrol edilecek metin
Returns:
dict: {
'issues': list, # Tespit edilen sorunlar listesi
'suggestions': list, # Öneriler listesi
'issue_count': int # Sorun sayısı
}
"""
issues = []
suggestions = []
# Cümlelere ayır
sentences = re.split(r'[.!?]+', text)
sentences = [s.strip() for s in sentences if s.strip()]
for i, sentence in enumerate(sentences):
# Büyük harfle başlama kontrolü
if sentence and not sentence[0].isupper():
issues.append(f"Cümle {i + 1}: Büyük harfle başlamıyor")
suggestions.append(f"Cümle {i + 1}: '{sentence[0]}' -> '{sentence[0].upper()}'")
# Cümle uzunluğu kontrolü
words = sentence.split()
if len(words) > self.max_sentence_length:
issues.append(f"Cümle {i + 1}: Çok uzun ({len(words)} kelime)")
suggestions.append(f"Cümle {i + 1}: Daha kısa cümlelere bölmeyi düşünün")
# Noktalama kontrolü
if i < len(sentences) - 1: # Son cümle değilse
if not text.find(sentence + ".") and not text.find(sentence + "!") and not text.find(sentence + "?"):
issues.append(f"Cümle {i + 1}: Noktalama işareti eksik olabilir")
suggestions.append(f"Cümle {i + 1}: Cümle sonuna uygun noktalama işareti ekleyin")
return {
'issues': issues,
'suggestions': suggestions,
'issue_count': len(issues)
}
def reduce_filler_words(self, text):
"""
Metindeki doldurma kelimelerini tespit eder ve azaltma önerileri sunar
Args:
text: İyileştirilecek metin
Returns:
dict: {
'filler_words': list, # Bulunan doldurma kelimeleri
'filler_count': int, # Doldurma kelimesi sayısı
'suggested_text': str # Önerilen iyileştirilmiş metin
}
"""
# Metindeki kelimeleri bul
words = re.findall(r'\b\w+\b', text.lower())
# Doldurma kelimelerini ve sayılarını say
filler_counter = Counter()
for word in words:
if word.lower() in self.filler_words:
filler_counter[word.lower()] += 1
# Metni kelime kelime işle ve fazla doldurma kelimelerini kaldır
suggested_text = text
for filler_word, count in filler_counter.items():
if count > 1: # Birden fazla geçiyorsa
# Her bir örneği bul
occurrences = list(re.finditer(r'\b' + re.escape(filler_word) + r'\b', suggested_text, re.IGNORECASE))
# İlk geçtiği yer hariç diğerlerini kaldır
for occurrence in occurrences[1:]:
start, end = occurrence.span()
# Eğer kelimenin önünde veya arkasında boşluk varsa, onu da kaldır
if start > 0 and suggested_text[start - 1] == ' ':
start -= 1
suggested_text = suggested_text[:start] + suggested_text[end:]
return {
'filler_words': list(filler_counter.keys()),
'filler_count': sum(filler_counter.values()),
'suggested_text': suggested_text
}
def calculate_readability(self, text):
"""
Metnin okunabilirlik skorunu hesaplar (Türkçe'ye uyarlanmış Flesch Reading Ease)
Args:
text: Değerlendirilecek metin
Returns:
dict: {
'score': float, # Okunabilirlik skoru (0-100)
'level': str, # Okunabilirlik seviyesi
'avg_sentence_length': float, # Ortalama cümle uzunluğu
'avg_word_length': float # Ortalama kelime uzunluğu
}
"""
# Cümleleri ve kelimeleri ayır
sentences = re.split(r'[.!?]+', text)
sentences = [s.strip() for s in sentences if s.strip()]
total_words = 0
total_syllables = 0
for sentence in sentences:
words = re.findall(r'\b\w+\b', sentence)
total_words += len(words)
# Türkçe heceleri kabaca hesapla (sesli harf sayısı)
for word in words:
# Türkçedeki sesli harfler
vowels = 'aeıioöuüAEIİOÖUÜ'
syllable_count = sum(1 for char in word if char in vowels)
# En az bir hece olmalı
syllable_count = max(1, syllable_count)
total_syllables += syllable_count
# Hesaplamalar
if len(sentences) == 0 or total_words == 0:
return {
'score': 100, # Boş metin - en kolay
'level': 'çok_kolay',
'avg_sentence_length': 0,
'avg_word_length': 0
}
avg_sentence_length = total_words / len(sentences)
avg_syllables_per_word = total_syllables / total_words
# Türkçe için uyarlanmış Flesch Reading Ease
# (orijinal formül: 206.835 - 1.015 * ASL - 84.6 * ASW)
# Türkçe için katsayılar ayarlandı
readability_score = 206.835 - (1.3 * avg_sentence_length) - (60.0 * avg_syllables_per_word)
# Skoru 0-100 aralığına sınırla
readability_score = max(0, min(100, readability_score))
# Seviyeyi belirle
level = 'çok_zor'
for threshold_level, threshold_value in sorted(self.readability_thresholds.items(), key=lambda x: x[1]):
if readability_score >= threshold_value:
level = threshold_level
break
return {
'score': float(readability_score),
'level': level,
'avg_sentence_length': float(avg_sentence_length),
'avg_word_length': float(avg_syllables_per_word)
}
def improve_text(self, text):
"""
Metni kapsamlı şekilde analiz eder ve iyileştirme önerileri sunar
Args:
text: İyileştirilecek metin
Returns:
dict: Tüm iyileştirme analizlerini içeren sonuçlar
"""
if not text or len(text.strip()) == 0:
return {
'corrected_text': text,
'suggestions': [],
'readability': {
'score': 100,
'level': 'çok_kolay'
},
'improvement_count': 0
}
try:
# Yazım hatalarını düzelt
typo_results = self.fix_typos(text)
# Dilbilgisi kontrolü
grammar_results = self.check_grammar(typo_results['corrected_text'])
# Doldurma kelimelerini azalt
filler_results = self.reduce_filler_words(typo_results['corrected_text'])
# Okunabilirlik hesapla
readability_results = self.calculate_readability(text)
# Tüm önerileri birleştir
all_suggestions = []
all_suggestions.extend([f"Yazım düzeltmesi: {correction}" for correction in typo_results['corrections']])
all_suggestions.extend(
[f"Dilbilgisi önerisi: {suggestion}" for suggestion in grammar_results['suggestions']])
if filler_results['filler_count'] > 0:
all_suggestions.append(f"Doldurma kelimelerini azaltın: {', '.join(filler_results['filler_words'])}")
# Okunabilirlik önerisi
if readability_results['score'] < 60: # Orta seviyenin altında ise
if readability_results['avg_sentence_length'] > 15:
all_suggestions.append("Daha kısa cümleler kullanın (ortalama cümle uzunluğu yüksek)")
if readability_results['avg_word_length'] > 2.5:
all_suggestions.append("Daha basit kelimeler kullanmayı deneyin (ortalama hece sayısı yüksek)")
# Birleştirilmiş sonuç
return {
'original_text': text,
'corrected_text': typo_results['corrected_text'],
'improved_text': filler_results['suggested_text'],
'suggestions': all_suggestions,
'readability': {
'score': readability_results['score'],
'level': readability_results['level'],
'avg_sentence_length': readability_results['avg_sentence_length']
},
'improvement_count': len(all_suggestions)
}
except Exception as e:
logger.error(f"Metin iyileştirme sırasında hata: {str(e)}")
return {
'original_text': text,
'corrected_text': text,
'improved_text': text,
'suggestions': ["Metin analizi sırasında bir hata oluştu"],
'readability': {
'score': 0,
'level': 'bilinmiyor'
},
'improvement_count': 0
}