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 }