diff --git a/hazm/InformalNormalizer.py b/hazm/InformalNormalizer.py index 1dc0159e..85f0b6df 100644 --- a/hazm/InformalNormalizer.py +++ b/hazm/InformalNormalizer.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals import codecs -from .utils import informal_verbs, informal_words, NUMBERS +from .utils import informal_verbs, informal_words, NUMBERS, default_verbs from .Normalizer import Normalizer from .Lemmatizer import Lemmatizer from .Stemmer import Stemmer @@ -19,6 +19,29 @@ def __init__(self, verb_file=informal_verbs, word_file=informal_words, seperatio self.stemmer = Stemmer() super(InformalNormalizer, self).__init__(**kargs) + self.sent_tokenizer = SentenceTokenizer() + self.word_tokenizer = WordTokenizer() + + with codecs.open(verb_file, encoding='utf8') as vf: + self.pastVerbs = {} + self.presentVerbs = {} + for f, i, flag in map(lambda x: x.strip().split(' ', 2), vf): + splitedF = f.split("#") + self.presentVerbs.update( + {i: splitedF[1]} + ) + self.pastVerbs.update( + {splitedF[0]: splitedF[0]} + ) + with codecs.open(default_verbs, encoding='utf8') as vf: + for f, i in map(lambda x: x.strip().split('#', 2), vf): + self.presentVerbs.update( + {i:i} + ) + self.pastVerbs.update( + {f: f} + ) + def informal_to_formal_conjucation(i, f, flag): iv = self.informal_conjugations(i) fv = self.lemmatizer.conjugations(f) @@ -106,43 +129,418 @@ def normalized_word(self, word): ['صداوسیما جمهوری', 'صداوسیماجمهوری'] """ - options = [] - if word in self.lemmatizer.words or word in self.lemmatizer.verbs: - pass - - elif word in self.iverb_map: - options.append(self.iverb_map[word]) - - elif word in self.iword_map: - options.append(self.iword_map[word]) - - elif word[:-2] in self.ilemmatizer.verbs and word.endswith('ین'): - options.append(word[:-1] + 'د') - elif word.endswith("ن") and word[:-1] in self.ilemmatizer.verbs: - options.append(word + 'د') - - elif word[:-1] in self.ilemmatizer.verbs and word.endswith('ه') and word[:-1] not in self.lemmatizer.words: - options.append(self.iword_map.get(word[:-1], word[:-1]) + 'د') - - elif word not in self.ilemmatizer.verbs and word.endswith('ه') and word[:-1] in self.ilemmatizer.words: - options.append(self.iword_map.get(word[:-1], word[:-1]) + ' است') - - elif word not in self.ilemmatizer.verbs and word.endswith('ون') and self.lemmatizer.lemmatize(word[:-2] + 'ان') in self.ilemmatizer.words: - options.append(word[:-2] + 'ان') - - elif self.seperation_flag: - options.append(self.split_token_words(word)) + def analyzeWord(word): + endWordsList = ["هاست", "هایی", "هایم", "ترین", "ایی", "انی", "شان", "شون", "است", "تان", "تون", "مان", "مون", + "هام", "هاش", "های", "طور", "ها", "تر", "ئی", "یی", "یم", "ام", "ای", "ان", "هم", "رو", "یت", "ه", "ی", "ش", "و", "ا", "ت", "م"] + + returnList = [] + + collectionOfWordAndSuffix = [] + + FoundEarly = False + + midWordCondidate = [] + + + if word.endswith("‌") or word.endswith("‎"): + word = word[:-1] + + if word in self.lemmatizer.words or word in self.iword_map: + if word in self.lemmatizer.words: + collectionOfWordAndSuffix.append( + { + "word": word, + "suffix": [] + } + ) + if word in self.iword_map: + collectionOfWordAndSuffix.append( + { + "word": self.iword_map[word], + "suffix": [] + } + ) + FoundEarly = True + + if not FoundEarly: + for endWord in endWordsList: + if word.endswith(endWord): + sliceWord = word[:-1 * len(endWord)] + if sliceWord in self.lemmatizer.words or sliceWord in self.iword_map: + if sliceWord in self.lemmatizer.words: + collectionOfWordAndSuffix.append( + { + "word": sliceWord, + "suffix": [endWord] + } + ) + if sliceWord in self.iword_map: + collectionOfWordAndSuffix.append( + { + "word": self.iword_map[sliceWord], + "suffix": [endWord] + } + ) + else: + midWordCondidate.append(sliceWord) + midWordCondidate.append([endWord]) + + for endWord in endWordsList: + for i in range(len(midWordCondidate) - 1): + if i % 2 == 1: + continue + midWord = midWordCondidate[i] + midWordEndWordList = midWordCondidate[i + 1] + if midWord.endswith(endWord): + sliceWord = midWord[:-1 * len(endWord)] + if sliceWord in self.lemmatizer.words or sliceWord in self.iword_map: + if sliceWord in self.lemmatizer.words: + collectionOfWordAndSuffix.append( + { + "word": sliceWord, + "suffix": [endWord] + midWordEndWordList + } + ) + if sliceWord in self.iword_map: + collectionOfWordAndSuffix.append( + { + "word": self.iword_map[sliceWord], + "suffix": [endWord] + midWordEndWordList + } + ) + + for i in range(len(collectionOfWordAndSuffix)): + newPossibelWordList = appendSuffixToWord(collectionOfWordAndSuffix[i]) + for j in range(len(newPossibelWordList)): + newPossibelWord = newPossibelWordList[j] + if newPossibelWord not in returnList: + returnList.append(newPossibelWord) + + return returnList + + def analyzeVerbWord(word): + + if word in self.pastVerbs: + word = self.pastVerbs[word] + return [word] + + if word in self.lemmatizer.words or word in self.iword_map: + return [] + + returnList = [] + + collectionOfVerbList = [] + + endVerbList = ["یم", "دم", "دیم", "ید", "دی", "دید", "ند", "دن", "دند", "ین", "دین", "ست", "م", "ی", "ه", "د", "ن"] + + for endVerb in endVerbList: + if word.endswith(endVerb): + if endVerb == "ین": + collectionOfVerbList.append({ + "word": word[:-2], + "suffix": "ید" + }) + elif endVerb == "ه": + if len(word) > 1: + if word[-2] != "د": + collectionOfVerbList.append({ + "word": word[:-1], + "suffix": "د" + }) + collectionOfVerbList.append({ + "word": word[:-1], + "suffix": "ه" + }) + else: + collectionOfVerbList.append({ + "word": word[:-1], + "suffix": "ه" + }) + else: + collectionOfVerbList.append({ + "word": word[:-1 * len(endVerb)], + "suffix": endVerb + }) + collectionOfVerbList.append({ + "word": word, + "suffix": "" + }) + for i in range(len(collectionOfVerbList)): + mainWord = collectionOfVerbList[i]["word"] + collectionOfVerbList[i]["preffix"] = "" + if mainWord.startswith("بر"): + modifiedWord = mainWord[2:] + newMainWord = "" + if modifiedWord.startswith("نمی"): + collectionOfVerbList[i]["preffix"] = "برنمی" + newMainWord = modifiedWord[3:] + elif modifiedWord.startswith("می"): + collectionOfVerbList[i]["preffix"] = "برمی" + newMainWord = modifiedWord[2:] + elif modifiedWord.startswith("ن"): + collectionOfVerbList[i]["preffix"] = "برن" + newMainWord = modifiedWord[1:] + elif modifiedWord.startswith("بی"): + collectionOfVerbList[i]["preffix"] = "بربی" + newMainWord = modifiedWord[2:] + elif modifiedWord.startswith("ب"): + collectionOfVerbList[i]["preffix"] = "برب" + newMainWord = modifiedWord[1:] + else: + collectionOfVerbList[i]["preffix"] = "بر" + newMainWord = modifiedWord + if newMainWord != "": + collectionOfVerbList[i]["word"] = newMainWord + elif mainWord.startswith("نمی"): + collectionOfVerbList[i]["preffix"] = "نمی" + collectionOfVerbList[i]["word"] = mainWord[3:] + elif mainWord.startswith("می"): + collectionOfVerbList[i]["preffix"] = "می" + collectionOfVerbList[i]["word"] = mainWord[2:] + elif mainWord.startswith("ن"): + collectionOfVerbList[i]["preffix"] = "ن" + collectionOfVerbList[i]["word"] = mainWord[1:] + elif mainWord.startswith("بی"): + collectionOfVerbList[i]["preffix"] = "بی" + collectionOfVerbList[i]["word"] = mainWord[2:] + elif mainWord.startswith("ب"): + collectionOfVerbList[i]["preffix"] = "ب" + collectionOfVerbList[i]["word"] = mainWord[1:] + + collectionOfRealVerbList = [] + for i in range(len(collectionOfVerbList)): + mainWord = collectionOfVerbList[i]["word"] + if mainWord.startswith("‌") or mainWord.startswith("‎"): + mainWord = mainWord[1:] + + if mainWord in self.pastVerbs: + collectionOfVerbList[i]["word"] = self.pastVerbs[mainWord] + collectionOfRealVerbList.append(collectionOfVerbList[i]) + if mainWord in self.presentVerbs: + collectionOfVerbList[i]["word"] = self.presentVerbs[mainWord] + collectionOfRealVerbList.append(collectionOfVerbList[i]) + + for i in range(len(collectionOfRealVerbList)): + preffix = collectionOfRealVerbList[i]["preffix"] + suffix = collectionOfRealVerbList[i]["suffix"] + mainWord = collectionOfRealVerbList[i]["word"] + returnWord = preffix + if preffix.endswith("می"): + returnWord += "‌" + returnWord += mainWord + returnWord += suffix + if mainWord != "": + if returnWord not in returnList: + returnList.append(returnWord) + + return returnList + + def appendSuffixToWord(OneCollectionOfWordAndSuffix): + mainWord = OneCollectionOfWordAndSuffix["word"] + suffixList = OneCollectionOfWordAndSuffix["suffix"] + adhesiveAlphabet = { + "ب": "ب", + "پ": "پ", + "ت": "ت", + "ث": "ث", + "ج": "ج", + "چ": "چ", + "ح": "ح", + "خ": "خ", + "س": "س", + "ش": "ش", + "ص": "ص", + "ض": "ض", + "ع": "ع", + "غ": "غ", + "ف": "ف", + "ق": "ق", + "ک": "ک", + "گ": "گ", + "ل": "ل", + "م": "م", + "ن": "ن", + "ه": "ه", + "ی": "ی", + } + returnWord = mainWord + returnWord2 = None + if len(suffixList) == 0: + return [returnWord] + if len(suffixList) > 1: + if suffixList[0] == "ه" and suffixList[1] == "ا": + suffixList[0] = "ها" + suffixList.remove(suffixList[1]) + if suffixList[0] == "ه" and suffixList[1] == "است": + suffixList[0] = "هاست" + suffixList.remove(suffixList[1]) + if suffixList[0] == "ت" and suffixList[1] == "ا": + suffixList[0] = "تا" + suffixList.remove(suffixList[1]) + for i in range(len(suffixList)): + if suffixList[i] == "شون": + returnWord += "شان" + elif suffixList[i] == "تون": + returnWord += "تان" + elif suffixList[i] == "مون": + returnWord += "مان" + elif suffixList[i] == "هام": + try: + var = adhesiveAlphabet[returnWord[-1]] + returnWord += "‌" + except: + None + returnWord += "هایم" + elif suffixList[i] == "ها": + try: + var = adhesiveAlphabet[returnWord[-1]] + returnWord += "‌" + except: + None + returnWord += "ها" + elif suffixList[i] == "ا" and suffixList[len(suffixList)-1] == "ا" and not returnWord.endswith("ه"): + try: + var = adhesiveAlphabet[returnWord[-1]] + returnWord += "‌" + except: + None + returnWord += "ها" + elif suffixList[i] == "و" and suffixList[len(suffixList)-1] == "و": + returnWord2 = returnWord + returnWord2 += " و" + returnWord += " را" + + elif suffixList[i] == "رو" and suffixList[len(suffixList)-1] == "رو": + returnWord += " را" + + else: + returnWord += suffixList[i] + if returnWord2 != None: + return [returnWord,returnWord2] + else: + return [returnWord] + + def straightForwardResult(word): + straightForwardDic = { + "ب": ["به"], + "ک": ["که"], + "ش": ["اش"], + "بش": ["بهش"], + "پایتون": ["پایتون"], + "سراتو": ["سراتو"], + "فالو": ["فالو"], + "هرجا": ["هرجا"], + "میدان": ["میدان"], + "میدون": ["میدان"], + "کفا": ["کفا"], + "ویا": ["و یا"], + "نشد": ["نشد"], + "شو": ["شو"], + "مشیا": ["مشیا"], + "پلاسما": ["پلاسما"], + "فیلیمو": ["فیلیمو"], + "پاشو": ["پاشو"], + "میر": ["میر"], + "بارم": ["بار هم", "بارم"], + "برند": ["برند"], + "کنه": ["کند"], + "بتونه": ["بتواند"], + "باشه": ["باشد"], + "بخوان": ["بخوان"], + "بدم": ["بدم"], + "برم": ["برم"], + "بده": ["بده"], + "نده": ["نده"], + "شهرو": ["شهرو"], + "شیرو": ["شیرو"], + "نگذاشته": ["نگذاشته"], + "نگرفته": ["نگرفته"], + "نمیشناخته": ["نمی‌شناخته"], + "نمی‌شناخته": ["نمی‌شناخته"], + "بشین": ["بشین"], + "هارو": ["ها را"], + "مارو": ["ما را"], + "میخواسته": ["می‌خواسته"], + "می‌خواسته": ["می‌خواسته"], + "نمیخواسته": ["نمی‌خواسته"], + "نمی‌خواسته": ["نمی‌خواسته"], + "میتوانسته": ["می‌توانسته"], + "می‌توانسته": ["می‌توانسته"], + "میرفته": ["می‌رفته"], + "می‌رفته": ["می‌رفته"], + "نشین": ["نشین"], + "انا": ["انا"], + "خونی": ["خونی"], + "خون": ["خون"], + "یالا": ["یالا"], + "میخواند": ["می‌خواند"], + "می‌خواند": ["می‌خواند"], + "نمیخواند": ["نمی‌خواند"], + "نمی‌خواند": ["نمی‌خواند"], + "میده": ["می‌دهد"], + "می‌ده": ["می‌دهد"], + "میشه": ["می‌شود"], + "می‌شه": ["می‌شود"], + "میشد": ["می‌شد"], + "می‌شد": ["می‌شد"], + "میشدم": ["می‌شدم"], + "می‌شدم": ["می‌شدم"], + "نمیشد": ["نمی‌شد"], + "نمی‌شد": ["نمی‌شد"], + "بردم": ["بردم"], + "شم": ["بشوم"], + "اوست": ["اوست"], + "بیا": ["بیا"], + "نیا": ["نیا"], + "میاد": ["می‌آید"], + "نشدی": ["نشدی"], + "بخواند": ["بخواند"], + "سیا": ["سیا"], + "میدید": ["می‌دید"], + "می‌دید": ["می‌دید"], + "وا": ["وا"], + "برگشته": ["برگشته"], + "میخواست": ["می‌خواست"], + "می‌خواست": ["می‌خواست"] + } + try: + return straightForwardDic[word] + except: + return [] + + + straightForwardWords = straightForwardResult(word) + if len(straightForwardWords) > 0: + return straightForwardWords + + verbWordsList = analyzeVerbWord(word) + if len(verbWordsList) > 0: + return verbWordsList + possibleWords = analyzeWord(word) + + mainWord = word + if mainWord in possibleWords: + possibleWords.remove(mainWord) + possibleWords.append(mainWord) + else: + if len(possibleWords) == 0: + possibleWords.append(mainWord) - options.append(word) - return options + return possibleWords def normalize(self, text): + """ + >>> normalizer = InformalNormalizer() + >>> normalizer.normalize('بابا یه شغل مناسب واسه بچه هام پیدا کردن که به جایی برنمیخوره !') + [[['بابا'], ['یک'], ['شغل'], ['مناسب'], ['برای'], ['بچه'], ['هایم'], ['پیدا'], ['کردن'], ['که'], ['به'], ['جایی'], ['برنمی\u200cخورد', 'برنمی\u200cخوره'], ['!']]] + >>> normalizer = InformalNormalizer() + >>> normalizer.normalize('اجازه بدیم همسرمون در جمع خانواده‌اش احساس آزادی کنه و فکر نکنه که ما دائم هواسمون بهش هست .') + [[['اجازه'], ['بدهیم'], ['همسرمان'], ['در'], ['جمع'], ['خانواده\u200cاش'], ['احساس'], ['آزادی'], ['کند'], ['و'], ['فکر'], ['نکند', 'نکنه'], ['که'], ['ما'], ['دائم'], ['حواسمان'], ['بهش'], ['هست'], ['.']]] + """ - sent_tokenizer = SentenceTokenizer() - word_tokenizer = WordTokenizer() text = super(InformalNormalizer, self).normalize(text) - sents = [word_tokenizer.tokenize(sentence) for sentence in sent_tokenizer.tokenize(text)] + sents = [self.word_tokenizer.tokenize(sentence) for sentence in self.sent_tokenizer.tokenize(text)] return [[self.normalized_word(word) for word in sent] for sent in sents] diff --git a/hazm/data/iverbs.dat b/hazm/data/iverbs.dat index e0339b59..a112cbc1 100644 --- a/hazm/data/iverbs.dat +++ b/hazm/data/iverbs.dat @@ -10,5 +10,13 @@ کرد#کن کن 1 گذاشت#گذار ذار 0 گزارد#گزار زار 0 -گفت#گو گ 0 +گفت#گوی گ 0 خرید#خر خر 0 +کشید#کش کش 0 +ماند#مان مون 0 +جوید#جو جو 0 +پرسید#پرس پرس 0 +نشاند#نشان نشون 0 +آورد#اور ار 0 +خواست#خواه خاه 1 +گذراند#گذران گذرون 0 \ No newline at end of file diff --git a/hazm/data/iwords.dat b/hazm/data/iwords.dat index 6c5d352b..60b4380e 100644 --- a/hazm/data/iwords.dat +++ b/hazm/data/iwords.dat @@ -2,18 +2,229 @@ دیگه دیگر اون آن اگه اگر -چی چه اقای آقای اینا این‌ها واسه برای مگه مگر -ان آن خودشون خودشان همون همان ایشون ایشان اینقدر این‌قدر -اینه این است -کی کسی هایی هایی -رو را اونم آن هم +وایساده ایستاده +اوس استاد +اوسا استاد +باهاس باید +اینقد این‌قدر +برا برای +اروا ارواح +امبر انبر +پمبه پنبه +پوس پوست +جاهاد جهاد +جمبه جنبه +چن چند +چکار چیکار +دس دست +دیقه دقیقه +دقه دقیقه +دمبه دنبه +دورود درود +دوس دوست +سورود سرود +سیبیل سبیل +شمبه شنبه +شیش شش +صاحاب صاحب +صب صبر +کا کاه +کوجا کجا +کیلید کلید +وخ وقت +وخت وقت +نگا نگاه +نیگا نگاه +آخه آخر +اونا آن‌ها +اونجا آنجا +اونها آن‌ها +آتیش آتش +آروم آرام +ابرام ابراهیم +بادوم بادام +باهار بهار +البت البته +برا برای +پیرن پیراهن +تموم تمام +تیکه تکه +جیگر جگر +زیگیل زگیل +سیا سیاه +چار چهار +چاهار چهار +چل چهل +چیه چیست +حروم حرام +خانوم خانم +دفه دفعه +سیریش سریش +کدوم کدام +کوچیک کوچک +مث مثل +مرتیکه مردکه +ناخون ناخن +ناهار نهار +مش مشهدی +مشد مشهدی +مشتی مشهدی +مشدی مشهدی +خونه خانه +چیزا چیزها +کسایی کسانی +شبا شب‌ها +توی در +گوله گلوله +رودخونه رودخانه +حیوون حیوان +حیوونا حیوان‌ها +شهرا شهرها +بهونه بهانه +سوغاتیا سوغاتی‌ها +کتابا کتاب‌ها +مونده مانده +تونست توانست +همینجا همین جا +براتون برایتان +آشپزخونه آشپزخانه +اونقدر آنقدر +رفتارا رفتارها +همش همه‌اش +یبار یکبار +براش برایش +هام هایم +هاش هایش +پیشونی پیشانی +تمرینا تمرین‌ها +اونقدرها آنقدرها +اخه آخر +بازم باز هم +زمونه زمانه +واقعا واقعاً +واقعن واقعاً +ایا آیا +نشون نشان +پیامنور پیام‌نور +بیشمار بی‌شمار +اموزشگاه‌ آموزشگاه +ازاد آزاد +هواس حواس +اینکار این کار +انقدر آنقدر +کاملا کاملاً +کاملن کاملاً +حتما حتماً +حتمن حتماً +اصولا اصولاً +اصولن اصولاً +ابدا ابداً +ابدن ابداً +اتفاقا اتفاقاً +اتفاقن اتفاقاً +کلا کلاً +کلن کلاً +ذاتا ذاتاً +ذاتن ذاتاً +قطعا قطعاً +قطعن قطعاً +دائما دائماً +دائمن دائماً +شدیدا شدیداً +شدیدن شدیداً +کرونا کرونا +اولا اولاً +اولن اولاً +بعدا بعداً +بعدن بعداً +خواهشا خواهشاً +خواهشن خواهشاً +سیبیلو سیبیلو +مستقیما مستقیماً +مستقیمن مستقیماً +مطمئنا مطمئناً +مطمئنن مطمئناً +نهایتا نهایتاً +نهایتن نهایتاً +ضمنا ضمناً +ضمنن ضمناً +برایم برایم +دهن دهان +تقریبا تقریباً +تقریبن تقریباً +شخصا شخصاً +شخصن شخصاً +خوندن خواندن +تون تان +شون شان +مون مان +انرا آن را +آنرا آن را +مثه مثل +ادم آدم +جوون جوان +مثلا مثلاً +مثلن مثلاً +عملا عملاً +عملن عملاً +ازمون آزمون +دقیقا دقیقاً +دقیقن دقیقاً +صرفا صرفاً +صرفن صرفاً +لطفا لطفاً +لطفن لطفاً +یقینا یقیناً +یقینن یقیناً +فعلا فعلاً +فعلن فعلاً +اکثرا اکثراً +اکثرن اکثراً +اقلا اقلاً +اقلن اقلاً +قبلا قبلاً +قبلن قبلاً +مخصوصا مخصوصاً +مخصوصن مخصوصاً +شرعا شرعاً +شرعن شرعاً +حقیقتا حقیقتاً +حقیقتن حقیقتاً +رسما رسماً +رسمن رسماً +احتمالا احتمالاً +احتمالن احتمالاً +قاعدتا قاعدتاً +قاعدتن قاعدتاً +خصوصا خصوصاً +خصوصن خصوصاً +نسبتا نسبتاً +نسبتن نسبتاً +اجبارا اجباراً +اجبارن اجباراً +حدودا حدوداً +حدودن حدوداً +ظاهرا ظاهراً +ظاهرن ظاهراً +معمولا معمولاً +معمولن معمولاً +لزوما لزوماً +لزومن لزوماً +اصلا اصلاً +اصلن اصلاً +مجددا مجدداً +مجددن مجدداً +صریحا صریحاً +صریحن صریحاً +صراحتا صراحتاً +صراحتن صراحتاً