1407 lines
76 KiB
Python
1407 lines
76 KiB
Python
from cleantext import clean
|
||
# from scipy.linalg import triu
|
||
# import hazm
|
||
import re
|
||
from re import sub
|
||
import copy
|
||
import os
|
||
from tokenizer import Tokenizer
|
||
# from data_helper import DataHelper
|
||
#import general_functions as gf
|
||
import traceback,sys
|
||
|
||
class Normalizer():
|
||
|
||
def __init__(self,
|
||
half_space_char='\u200c',
|
||
date_normalizing_needed=False,
|
||
pinglish_conversion_needed=False,
|
||
train_file_path="resource/tokenizer/Bijan_khan_chunk.txt",
|
||
token_merger_path="resource/tokenizer/TokenMerger.pckl"):
|
||
self.dir_path = os.path.dirname(os.path.realpath(__file__)) + "/"
|
||
|
||
self.dic1_path = self.dir_path + 'resource/normalizer/Dic1_new.txt'
|
||
self.dic2_path = self.dir_path + 'resource/normalizer/Dic2_new.txt'
|
||
self.dic3_path = self.dir_path + 'resource/normalizer/Dic3_new.txt'
|
||
self.dic1 = self.load_dictionary(self.dic1_path)
|
||
self.dic2 = self.load_dictionary(self.dic2_path)
|
||
self.dic3 = self.load_dictionary(self.dic3_path)
|
||
|
||
self.date_normalizing_needed = date_normalizing_needed
|
||
self.pinglish_conversion_needed = pinglish_conversion_needed
|
||
# self.data_helper = DataHelper()
|
||
|
||
|
||
if self.date_normalizing_needed or self.pinglish_conversion_needed:
|
||
self.tokenizer = Tokenizer()
|
||
self.date_normalizer = DateNormalizer()
|
||
self.pinglish_conversion = PinglishNormalizer()
|
||
|
||
|
||
|
||
def load_dictionary(self, file_path):
|
||
dict = {}
|
||
with open(file_path, 'r', encoding='utf-8') as f:
|
||
g = f.readlines()
|
||
for Wrds in g:
|
||
wrd = Wrds.split(' ')
|
||
dict[wrd[0].strip()] = sub('\n', '', wrd[1].strip())
|
||
return dict
|
||
|
||
def sub_alphabets(self, doc_string):
|
||
# try:
|
||
# doc_string = doc_string.decode('utf-8')
|
||
# except UnicodeEncodeError:
|
||
# pass
|
||
# a0 = "ء"
|
||
# b0 = "ئ"
|
||
#c0 = sub(a0, b0, doc_string)
|
||
a11 = r"ﺁ|آ"
|
||
b11 = r"آ"
|
||
a1 = r"ٲ|ٱ|إ|ﺍ|أ"
|
||
b1 = r"ا"
|
||
c11 = sub(a11, b11, doc_string)
|
||
c1 = sub(a1, b1, c11)
|
||
a2 = r"ﺐ|ﺏ|ﺑ"
|
||
b2 = r"ب"
|
||
c2 = sub(a2, b2, c1)
|
||
a3 = r"ﭖ|ﭗ|ﭙ|ﺒ|ﭘ"
|
||
b3 = r"پ"
|
||
c3 = sub(a3, b3, c2)
|
||
a4 = r"ﭡ|ٺ|ٹ|ﭞ|ٿ|ټ|ﺕ|ﺗ|ﺖ|ﺘ"
|
||
b4 = r"ت"
|
||
c4 = sub(a4, b4, c3)
|
||
a5 = r"ﺙ|ﺛ"
|
||
b5 = r"ث"
|
||
c5 = sub(a5, b5, c4)
|
||
a6 = r"ﺝ|ڃ|ﺠ|ﺟ"
|
||
b6 = r"ج"
|
||
c6 = sub(a6, b6, c5)
|
||
a7 = r"ڃ|ﭽ|ﭼ"
|
||
b7 = r"چ"
|
||
c7 = sub(a7, b7, c6)
|
||
a8 = r"ﺢ|ﺤ|څ|ځ|ﺣ"
|
||
b8 = r"ح"
|
||
c8 = sub(a8, b8, c7)
|
||
a9 = r"ﺥ|ﺦ|ﺨ|ﺧ"
|
||
b9 = r"خ"
|
||
c9 = sub(a9, b9, c8)
|
||
a10 = r"ڏ|ډ|ﺪ|ﺩ"
|
||
b10 = r"د"
|
||
c10 = sub(a10, b10, c9)
|
||
a11 = r"ﺫ|ﺬ|ﻧ"
|
||
b11 = r"ذ"
|
||
c11 = sub(a11, b11, c10)
|
||
a12 = r"ڙ|ڗ|ڒ|ڑ|ڕ|ﺭ|ﺮ"
|
||
b12 = r"ر"
|
||
c12 = sub(a12, b12, c11)
|
||
a13 = r"ﺰ|ﺯ"
|
||
b13 = r"ز"
|
||
c13 = sub(a13, b13, c12)
|
||
a14 = r"ﮊ"
|
||
b14 = r"ژ"
|
||
c14 = sub(a14, b14, c13)
|
||
a15 = r"ݭ|ݜ|ﺱ|ﺲ|ښ|ﺴ|ﺳ"
|
||
b15 = r"س"
|
||
c15 = sub(a15, b15, c14)
|
||
a16 = r"ﺵ|ﺶ|ﺸ|ﺷ"
|
||
b16 = r"ش"
|
||
c16 = sub(a16, b16, c15)
|
||
a17 = r"ﺺ|ﺼ|ﺻ"
|
||
b17 = r"ص"
|
||
c17 = sub(a17, b17, c16)
|
||
a18 = r"ﺽ|ﺾ|ﺿ|ﻀ"
|
||
b18 = r"ض"
|
||
c18 = sub(a18, b18, c17)
|
||
a19 = r"ﻁ|ﻂ|ﻃ|ﻄ"
|
||
b19 = r"ط"
|
||
c19 = sub(a19, b19, c18)
|
||
a20 = r"ﻆ|ﻇ|ﻈ"
|
||
b20 = r"ظ"
|
||
c20 = sub(a20, b20, c19)
|
||
a21 = r"ڠ|ﻉ|ﻊ|ﻋ"
|
||
b21 = r"ع"
|
||
c21 = sub(a21, b21, c20)
|
||
a22 = r"ﻎ|ۼ|ﻍ|ﻐ|ﻏ"
|
||
b22 = r"غ"
|
||
c22 = sub(a22, b22, c21)
|
||
a23 = r"ﻒ|ﻑ|ﻔ|ﻓ"
|
||
b23 = r"ف"
|
||
c23 = sub(a23, b23, c22)
|
||
a24 = r"ﻕ|ڤ|ﻖ|ﻗ"
|
||
b24 = r"ق"
|
||
c24 = sub(a24, b24, c23)
|
||
a25 = r"ڭ|ﻚ|ﮎ|ﻜ|ﮏ|ګ|ﻛ|ﮑ|ﮐ|ڪ|ك"
|
||
b25 = r"ک"
|
||
c25 = sub(a25, b25, c24)
|
||
a26 = r"ﮚ|ﮒ|ﮓ|ﮕ|ﮔ"
|
||
b26 = r"گ"
|
||
c26 = sub(a26, b26, c25)
|
||
a27 = r"ﻝ|ﻞ|ﻠ|ڵ"
|
||
b27 = r"ل"
|
||
c27 = sub(a27, b27, c26)
|
||
a28 = r"ﻡ|ﻤ|ﻢ|ﻣ"
|
||
b28 = r"م"
|
||
c28 = sub(a28, b28, c27)
|
||
a29 = r"ڼ|ﻦ|ﻥ|ﻨ"
|
||
b29 = r"ن"
|
||
c29 = sub(a29, b29, c28)
|
||
a30 = r"ވ|ﯙ|ۈ|ۋ|ﺆ|ۊ|ۇ|ۏ|ۅ|ۉ|ﻭ|ﻮ|ؤ"
|
||
b30 = r"و"
|
||
c30 = sub(a30, b30, c29)
|
||
a31 = r"ﺔ|ﻬ|ھ|ﻩ|ﻫ|ﻪ|ۀ|ە|ة|ہ"
|
||
b31 = r"ه"
|
||
c31 = sub(a31, b31, c30)
|
||
a32 = r"ﭛ|ﻯ|ۍ|ﻰ|ﻱ|ﻲ|ں|ﻳ|ﻴ|ﯼ|ې|ﯽ|ﯾ|ﯿ|ێ|ے|ى|ي"
|
||
b32 = r"ی"
|
||
c32 = sub(a32, b32, c31)
|
||
a33 = r'¬'
|
||
b33 = r''
|
||
c33 = sub(a33, b33, c32)
|
||
pa0 = r'•|·|●|·|・|∙|。|ⴰ'
|
||
pb0 = r'.'
|
||
pc0 = sub(pa0, pb0, c33)
|
||
pa1 = r',|٬|٫|‚|,'
|
||
pb1 = r'،'
|
||
pc1 = sub(pa1, pb1, pc0)
|
||
pa2 = r'ʕ'
|
||
pb2 = r'؟'
|
||
pc2 = sub(pa2, pb2, pc1)
|
||
na0 = r'۰|٠'
|
||
nb0 = r'0'
|
||
nc0 = sub(na0, nb0, pc2)
|
||
na1 = r'۱|١'
|
||
nb1 = r'1'
|
||
nc1 = sub(na1, nb1, nc0)
|
||
na2 = r'۲|٢'
|
||
nb2 = r'2'
|
||
nc2 = sub(na2, nb2, nc1)
|
||
na3 = r'۳|٣'
|
||
nb3 = r'3'
|
||
nc3 = sub(na3, nb3, nc2)
|
||
na4 = r'۴|٤'
|
||
nb4 = r'4'
|
||
nc4 = sub(na4, nb4, nc3)
|
||
na5 = r'۵'
|
||
nb5 = r'5'
|
||
nc5 = sub(na5, nb5, nc4)
|
||
na6 = r'۶|٦'
|
||
nb6 = r'6'
|
||
nc6 = sub(na6, nb6, nc5)
|
||
na7 = r'۷|٧'
|
||
nb7 = r'7'
|
||
nc7 = sub(na7, nb7, nc6)
|
||
na8 = r'۸|٨'
|
||
nb8 = r'8'
|
||
nc8 = sub(na8, nb8, nc7)
|
||
na9 = r'۹|٩'
|
||
nb9 = r'9'
|
||
nc9 = sub(na9, nb9, nc8)
|
||
np2 = r'²'
|
||
nm2 = r'2'
|
||
ng2 = sub(np2, nm2, nc9)
|
||
ea1 = r'|ِ|ُ|َ|ٍ|ٌ|ً|'
|
||
eb1 = r''
|
||
ec1 = sub(ea1, eb1, ng2)
|
||
ea1 = r'ـ'
|
||
eb1 = r'_'
|
||
ec2 = sub(ea1, eb1, ec1)
|
||
Sa1 = r'( )+'
|
||
Sb1 = r' '
|
||
Sc1 = sub(Sa1, Sb1, ec2)
|
||
Sa2 = r'(\n)+'
|
||
Sb2 = r'\n'
|
||
Sc2 = sub(Sa2, Sb2, Sc1)
|
||
return Sc2
|
||
|
||
def space_correction(self, doc_string):
|
||
a00 = r'^(بی|می|نمی)( )'
|
||
b00 = r'\1'
|
||
c00 = sub(a00, b00, doc_string)
|
||
a0 = r'( )(می|نمی|بی)( )'
|
||
b0 = r'\1\2'
|
||
c0 = sub(a0, b0, c00)
|
||
a1 = r'( )(هایی|ها|های|ایی|هایم|هایت|هایش|هایمان|هایتان|هایشان|ات|ان|ین' \
|
||
r'|انی|بان|ام|ای|یم|ید|اید|اند|بودم|بودی|بود|بودیم|بودید|بودند|ست)( )'
|
||
b1 = r'\2\3'
|
||
c1 = sub(a1, b1, c0)
|
||
a2 = r'( )(شده|نشده)( )'
|
||
b2 = r'\2'
|
||
c2 = sub(a2, b2, c1)
|
||
a3 = r'( )(طلبان|طلب|گرایی|گرایان|شناس|شناسی|گذاری|گذار|گذاران|شناسان|گیری|پذیری|بندی|آوری|سازی|' \
|
||
r'بندی|کننده|کنندگان|گیری|پرداز|پردازی|پردازان|آمیز|سنجی|ریزی|داری|دهنده|آمیز|پذیری' \
|
||
r'|پذیر|پذیران|گر|ریز|ریزی|رسانی|یاب|یابی|گانه|گانهای|انگاری|گا|بند|رسانی|دهندگان|دار)( )'
|
||
b3 = r'\2\3'
|
||
c3 = sub(a3, b3, c2)
|
||
return c3
|
||
|
||
def space_correction_plus1(self, doc_string):
|
||
out_sentences = ''
|
||
for wrd in doc_string.split(' '):
|
||
try:
|
||
out_sentences = out_sentences + ' ' + self.dic1[wrd]
|
||
except KeyError:
|
||
out_sentences = out_sentences + ' ' + wrd
|
||
return out_sentences
|
||
|
||
def space_correction_plus2(self, doc_string):
|
||
out_sentences = ''
|
||
wrds = doc_string.split(' ')
|
||
L = wrds.__len__()
|
||
if L < 2:
|
||
return doc_string
|
||
cnt = 1
|
||
for i in range(0, L - 1):
|
||
w = wrds[i] + wrds[i + 1]
|
||
try:
|
||
out_sentences = out_sentences + ' ' + self.dic2[w]
|
||
cnt = 0
|
||
except KeyError:
|
||
if cnt == 1:
|
||
out_sentences = out_sentences + ' ' + wrds[i]
|
||
cnt = 1
|
||
if cnt == 1:
|
||
out_sentences = out_sentences + ' ' + wrds[i + 1]
|
||
return out_sentences
|
||
|
||
def space_correction_plus3(self, doc_string):
|
||
# Dict = {'گفتوگو': 'گفتوگو'}
|
||
out_sentences = ''
|
||
wrds = doc_string.split(' ')
|
||
L = wrds.__len__()
|
||
if L < 3:
|
||
return doc_string
|
||
cnt = 1
|
||
cnt2 = 0
|
||
for i in range(0, L - 2):
|
||
w = wrds[i] + wrds[i + 1] + wrds[i + 2]
|
||
try:
|
||
out_sentences = out_sentences + ' ' + self.dic3[w]
|
||
cnt = 0
|
||
cnt2 = 2
|
||
except KeyError:
|
||
if cnt == 1 and cnt2 == 0:
|
||
out_sentences = out_sentences + ' ' + wrds[i]
|
||
else:
|
||
cnt2 -= 1
|
||
cnt = 1
|
||
if cnt == 1 and cnt2 == 0:
|
||
out_sentences = out_sentences + ' ' + wrds[i + 1] + ' ' + wrds[i + 2]
|
||
elif cnt == 1 and cnt2 == 1:
|
||
out_sentences = out_sentences + ' ' + wrds[i + 2]
|
||
return out_sentences
|
||
|
||
def normalize(self, doc_string, new_line_elimination=False, return_dates = False):
|
||
normalized_string = gf.normalize_content(doc_string)
|
||
normalized_string = self.sub_alphabets(doc_string)
|
||
#normalized_string = self.data_helper.clean_text(normalized_string, new_line_elimination).strip()
|
||
|
||
#normalized_string = self.space_correction(self.space_correction_plus1(self.space_correction_plus2(self.space_correction_plus3(normalized_string)))).strip()
|
||
|
||
# !!!آئین نامه را به آئیننامه تبدیل می کند و دو توکن را به یکی تبدیل می کند
|
||
#normalized_string = (self.space_correction_plus1(self.space_correction_plus2(self.space_correction_plus3(normalized_string)))).strip()
|
||
|
||
#if self.pinglish_conversion_needed:
|
||
#normalized_string = self.pinglish_conversion.pingilish2persian(self.tokenizer.tokenize_words(normalized_string))
|
||
|
||
if self.date_normalizing_needed:
|
||
token_list = self.tokenizer.tokenize_words(normalized_string)
|
||
# نرمالایز کردن اعداد حروفی و ...
|
||
normalized_string, additional_token_index_array = self.date_normalizer.normalize_numbers2(token_list)
|
||
# نرمالایز و تشخیص تاریخ ها
|
||
normalized_string, dates, recognized_dates = self.date_normalizer.general_normalize_date(normalized_string, additional_token_index_array)
|
||
#normalized_string_list = normalized_string.strip().split()
|
||
#normalized_string, dates, recognized_dates = self.date_normalizer.normalize_dates(normalized_string_list, additional_token_index_array, token_list_len= len(normalized_string_list), previous_slice_index_array=[0,])
|
||
# کنترل اعدادی که پشت سر هم آمده اند و با واو از هم جدا شده اند
|
||
normalized_string, recognized_numbers = self.date_normalizer.handle_continuous_numbers(normalized_string)
|
||
# در مواردی مانند وسیصد که واو به عدد سیصد چسبیده، ابتدا این دو را از هم جدا می کنیم
|
||
# تا عدد اصلی را به دست بیاوریم. در این صورت یک توکن اضافه تولید می شود که با این متد، توکن های اضافی را حذف می کنیم
|
||
normalized_string =self.date_normalizer.remove_additional_tokens(normalized_string.split(), additional_token_index_array)
|
||
if return_dates:
|
||
# مرتب کردن آرایه تاریخ های پیدا شده بر اساس توکن شروع عبارت حاوی تاریخ
|
||
recognized_dates.sort(key=lambda x: int(x['start_date_token_index']), reverse=False)
|
||
|
||
return normalized_string, dates, recognized_dates, recognized_numbers
|
||
else:
|
||
return normalized_string
|
||
|
||
|
||
class DateNormalizer():
|
||
def __init__(self):
|
||
|
||
self.month_dict = { "فروردین": 1,"فروردینماه": 1,'فروردین\u200cماه':1,
|
||
"اردیبهشت": 2,"اردیبهشتماه": 2,'اردیبهشت\u200cماه':2,
|
||
"خرداد": 3,"خردادماه": 3,
|
||
"تیر": 4,"تیرماه": 4,
|
||
"مرداد": 5,"مردادماه": 5,
|
||
"شهریور": 6,"شهریورماه": 6,
|
||
"مهر": 7,"مهرماه": 7,
|
||
"آبان": 8,"آبانماه": 8,'آبان\u200cماه':8,
|
||
"آذر": 9,"آذرماه": 9,
|
||
"دی": 10,"دیماه": 10,'دی\u200cماه':10,
|
||
"بهمن": 11,"بهمنماه": 11,'بهمن\u200cماه':11,
|
||
"اسفند": 12,"اسفندماه": 12}
|
||
self.num_dict = {"صد": 100,"وصد": 100, "یکصد": 100, "ویکصد": 100, "هزار": 1000,"وهزار": 1000,
|
||
"یکهزار": 1000,"ویکهزار": 1000,
|
||
"میلیون": 1000000,"ملیون": 1000000, "ومیلیون": 1000000,"وملیون": 1000000,
|
||
"یکمیلیون": 1000000,"یکملیون": 1000000,
|
||
"ویکمیلیون": 1000000,"ویکملیون": 1000000, "دویست": 200,"ودویست": 200,
|
||
"ده": 10,"وده": 10, "نه": 9,"ونه": 9, "هشت": 8,"وهشت": 8, "هفت": 7,"وهفت": 7,
|
||
"شش": 6,"وشش": 6, "پنج": 5,"وپنج": 5,"چهار": 4,"وچهار": 4, "سه": 3,"وسه": 3,
|
||
"دو": 2,"ودو": 2, "یک": 1,"ویک": 1, "یازده": 11,"ویازده": 11, "سیزده": 13, "وسیزده": 13,
|
||
"چهارده": 14, "دوازده": 12, "پانزده": 15, "شانزده": 16, "هفده": 17,"هیفده": 17,
|
||
"وچهارده": 14, "ودوازده": 12, "وپانزده": 15, "وشانزده": 16, "وهفده": 17,"وهیفده": 17,
|
||
"هجده": 18,"هیجده": 18, "نوزده": 19, "بیست": 20, "سی": 30, "چهل": 40, "پنجاه": 50,
|
||
"وهجده": 18,"وهیجده": 18, "ونوزده": 19, "وبیست": 20, "وسی": 30, "وچهل": 40, "وپنجاه": 50,
|
||
"شصت": 60, "هفتاد": 70, "نود": 90, "سیصد": 300, "چهارصد": 400,
|
||
"وشصت": 60, "وهفتاد": 70, "ونود": 90, "وسیصد": 300, "وچهارصد": 400,
|
||
"پانصد": 500, "ششصد": 600, "هفتصد": 700, "هشتصد": 800, "نهصد": 900,
|
||
"وپانصد": 500, "وششصد": 600, "وهفتصد": 700, "وهشتصد": 800, "ونهصد": 900,
|
||
"هشتاد": 80, " ": 0, "میلیارد": 1000000000,"ملیارد": 1000000000,
|
||
"یکمیلیارد": 1000000000,"یکملیارد": 1000000000,
|
||
"وهشتاد": 80, " ": 0, "ومیلیارد": 1000000000,"وملیارد": 1000000000,
|
||
"ویکمیلیارد": 1000000000,"ویکملیارد": 1000000000,
|
||
"صدم": 100, "هزارم": 1000, "دویستم": 200,
|
||
"وصدم": 100, "وهزارم": 1000, "ودویستم": 200,
|
||
"دهم": 10, "نهم": 9, "هشتم": 8, "هفتم": 7, "ششم": 6, "پنجم": 5,
|
||
"ودهم": 10, "ونهم": 9, "وهشتم": 8, "وهفتم": 7, "وششم": 6, "وپنجم": 5,
|
||
"چهارم": 4, "سوم": 3, "دوم": 2, "یکم": 1, "اول": 1, "یازدهم": 11, "سیزدهم": 13,
|
||
"وچهارم": 4, "وسوم": 3, "ودوم": 2, "ویکم": 1, "واول": 1, "ویازدهم": 11, "وسیزدهم": 13,
|
||
"چهاردهم": 14, "دوازدهم": 12, "پانزدهم": 15, "شانزدهم": 16, "هفدهم": 17,"هیفدهم": 17,
|
||
"وچهاردهم": 14, "ودوازدهم": 12, "وپانزدهم": 15, "وشانزدهم": 16, "وهفدهم": 17,"وهیفدهم": 17,
|
||
"هجدهم": 18,"هیجدهم": 18, "نوزدهم": 19, "بیستم": 20, "چهلم": 40, "پنجاهم": 50,
|
||
"وهجدهم": 18,"وهیجدهم": 18, "ونوزدهم": 19, "وبیستم": 20, "وچهلم": 40, "وپنجاهم": 50,
|
||
"شصتم": 60, "هفتادم": 70, "نودم": 90, "سیصدم": 300, "چهارصدم": 400,
|
||
"وشصتم": 60, "وهفتادم": 70, "ونودم": 90, "وسیصدم": 300, "وچهارصدم": 400,
|
||
"پانصدم": 500, "ششصدم": 600, "هفتصدم": 700, "هشتصدم": 800, "نهصدم": 900,
|
||
"وپانصدم": 500, "وششصدم": 600, "وهفتصدم": 700, "وهشتصدم": 800, "ونهصدم": 900,
|
||
"هشتادم": 80,"وهشتادم": 80}
|
||
|
||
def find_date_part(self, token_list):
|
||
import re
|
||
for index, element in enumerate(token_list):
|
||
# بررسی الگوی تاریخ 1398/12/18
|
||
pattern_date = r'^(\d{4}\s*/\s*([1-9]|0[1-9]|1[0-2])\s*/\s*([1-9]|0[1-9]|[12][0-9]|3[01]))$'
|
||
date_pattern = re.compile(pattern_date)
|
||
match_date = date_pattern.match(element)
|
||
if match_date:
|
||
date_parts = match_date.string.split('/')
|
||
year = int(re.search(r'\d+', date_parts[0]).group())
|
||
month = int(re.search(r'\d+', date_parts[1]).group())
|
||
day = int(re.search(r'\d+', date_parts[2]).group())
|
||
# اگر مقداری که در روز است، چهار رقمی باشد باید مقدار روز و سال را با هم عوض کرد
|
||
if day > 999:
|
||
day = int(re.search(r'\d+', date_parts[0]).group())
|
||
year = int(re.search(r'\d+', date_parts[2]).group())
|
||
formal_date = "y" + str(year) + "m" + str(month) + "d" + str(day)
|
||
return formal_date, index, index, index
|
||
|
||
# 24 /12 /1401 بررسی الگوی تاریخ
|
||
pattern_date = r'\s*\d{2}\s*/\s*\d{2}\s*/\s*\d{4}\s*'
|
||
date_pattern = re.compile(pattern_date)
|
||
match_date = date_pattern.match(element)
|
||
if match_date:
|
||
date_parts = match_date.string.split('/')
|
||
year = int(re.search(r'\d+', date_parts[0]).group())
|
||
month = int(re.search(r'\d+', date_parts[1]).group())
|
||
day = int(re.search(r'\d+', date_parts[2]).group())
|
||
# اگر مقداری که در روز است، چهار رقمی باشد باید مقدار روز و سال را با هم عوض کرد
|
||
if day > 999:
|
||
day = int(re.search(r'\d+', date_parts[0]).group())
|
||
year = int(re.search(r'\d+', date_parts[2]).group())
|
||
formal_date = "y" + str(year) + "m" + str(month) + "d" + str(day)
|
||
return formal_date, index, index, index
|
||
|
||
# بررسی الگوی تاریخ 1402،10،06
|
||
patterndate2 = r'^(\d{4}\s*،\s*([1-9]|0[1-9]|1[0-2])\s*،\s*([1-9]|0[1-9]|[12][0-9]|3[01]))$'
|
||
date_pattern = re.compile(patterndate2)
|
||
match_date2 = date_pattern.match(element)
|
||
if match_date2:
|
||
date_parts = match_date2.string.split('،')
|
||
year = int(re.search(r'\d+', date_parts[0]).group())
|
||
month = int(re.search(r'\d+', date_parts[1]).group())
|
||
day = int(re.search(r'\d+', date_parts[2]).group())
|
||
# اگر مقداری که در روز است، چهار رقمی باشد باید مقدار روز و سال را با هم عوض کرد
|
||
if day > 999:
|
||
day = int(re.search(r'\d+', date_parts[0]).group())
|
||
year = int(re.search(r'\d+', date_parts[2]).group())
|
||
formal_date = "y" + str(year) + "m" + str(month) + "d" + str(day)
|
||
return formal_date, index, index, index
|
||
|
||
# بررسی الگوی تاریخ 13ر04ر1345
|
||
patterndate2 = r'^(\d{4}\s*ر\s*([1-9]|0[1-9]|1[0-2])\s*ر\s*([1-9]|0[1-9]|[12][0-9]|3[01]))$'
|
||
date_pattern = re.compile(patterndate2)
|
||
match_date2 = date_pattern.match(element)
|
||
if match_date2:
|
||
date_parts = match_date2.string.split('ر')
|
||
year = int(re.search(r'\d+', date_parts[0]).group())
|
||
month = int(re.search(r'\d+', date_parts[1]).group())
|
||
day = int(re.search(r'\d+', date_parts[2]).group())
|
||
# اگر مقداری که در روز است، چهار رقمی باشد باید مقدار روز و سال را با هم عوض کرد
|
||
if day > 999:
|
||
day = int(re.search(r'\d+', date_parts[0]).group())
|
||
year = int(re.search(r'\d+', date_parts[2]).group())
|
||
formal_date = "y" + str(year) + "m" + str(month) + "d" + str(day)
|
||
return formal_date, index, index, index
|
||
|
||
if element == "/":
|
||
if index-1 >= 0 and index+1 < len(token_list) \
|
||
and token_list[index -1].isdigit() and token_list[index+1].isdigit():
|
||
if index+3 < len(token_list) and token_list[index+2] == "/" \
|
||
and token_list[index + 3].isdigit():
|
||
if int(token_list[index-1]) < 1450 and int(token_list[index+1]) < 13 and \
|
||
int(token_list[index+3]) < 32:
|
||
formal_date = [int(token_list[index-1]), int(token_list[index+1]), int(token_list[index+3])]
|
||
formal_date = "y" + str(formal_date[0]) + "m" + str(formal_date[1]) + "d" + str(formal_date[2])
|
||
#return formal_date, index-1, index+3, index
|
||
return formal_date, index, index, index
|
||
elif int(token_list[index-1]) < 32 and int(token_list[index+1]) < 13 and \
|
||
int(token_list[index+3]) < 1450:
|
||
formal_date = [int(token_list[index-1]), int(token_list[index+1]), int(token_list[index+3])]
|
||
formal_date = "y" + str(formal_date[2]) + "m" + str(formal_date[1]) + "d" + str(formal_date[0])
|
||
#return formal_date, index-1, index+3, index
|
||
return formal_date, index, index, index
|
||
else:
|
||
formal_date = [int(token_list[index-1]), int(token_list[index+1]), int(token_list[index+3])]
|
||
formal_date = "num(" + str(formal_date[0]) + "/" + str(formal_date[1]) + "/" + str(formal_date[2]) + ")"
|
||
#return formal_date, index-1, index+3, index
|
||
return formal_date, index, index, index
|
||
elif (int(token_list[index-1]) < 1450 and int(token_list[index-1]) > 1250) and int(token_list[index+1]) < 13:
|
||
formal_date = [int(token_list[index-1]), int(token_list[index+ 1]), 0]
|
||
formal_date = "y" + str(formal_date[2]) + "m" + str(formal_date[1]) + "d" + str(formal_date[0])
|
||
#return formal_date, index-1 , index+1, index
|
||
return formal_date, index , index, index
|
||
else:
|
||
formal_date = [int(token_list[index-1]), int(token_list[index+ 1])]
|
||
formal_date = "num(" + str(formal_date[0]) + "/" + str(formal_date[1]) + ")"
|
||
#return formal_date, index-1 , index+1, index
|
||
return formal_date, index , index, index
|
||
|
||
if element in self.month_dict or element == "سال":
|
||
if index + 1 < len(token_list) and index - 1 > -2:
|
||
try:
|
||
start_date_index = end_date_index = 0
|
||
if(token_list[index + 1] == 'ماه'):
|
||
if(token_list[index + 2] == 'سال' and str(token_list[index + 3]).isdigit()):
|
||
|
||
if(int(token_list[index + 3])==1000):
|
||
# در این حالت، امکان دارد روز مربوط به این تاریخ هم به صورت حروف در متن قانون نوشته شده باشد
|
||
# به همین دلیل ، توکن های قبل از ماه را نیز کنترل می کنیم
|
||
start_date_index = index - 1
|
||
day = int(token_list[index - 1])
|
||
if(token_list[index - 2]=='و' and token_list[index - 3].isdigit()):
|
||
day += int(token_list[index - 3])# رقم دهگان روز
|
||
start_date_index = index - 3
|
||
year = 1000
|
||
if(len(token_list)>= index + 5):
|
||
if(token_list[index + 4]=='و' and token_list[index + 5].isdigit()):
|
||
year += int(token_list[index + 5])# رقم صدگان سال
|
||
end_date_index = index + 5
|
||
if(len(token_list)>= index + 7):
|
||
if(token_list[index + 6]=='و' and token_list[index + 7].isdigit()):
|
||
year += int(token_list[index + 7])# رقم دهگان سال
|
||
end_date_index = index + 7
|
||
if(len(token_list)>= index + 9):
|
||
if(token_list[index + 8]=='و' and token_list[index + 9].isdigit()):
|
||
year += int(token_list[index + 9])# رقم یکان سال
|
||
end_date_index = index + 9
|
||
|
||
formal_date = [day, int(self.month_dict[token_list[index]]), year]# مثلا 20 و 8 تیر ماه سال 1000 و 300 و 20 و 5
|
||
|
||
else:
|
||
start_date_index = index - 1
|
||
end_date_index = index + 3
|
||
day = int(token_list[index - 1])
|
||
if(token_list[index - 2]=='و' and int(token_list[index - 1])<10 and int(token_list[index - 3])<31 and token_list[index - 3].isdigit()):
|
||
start_date_index = index - 3
|
||
day += int(token_list[index - 3])# رقم دهگان روز
|
||
|
||
formal_date = [day, int(self.month_dict[token_list[index]]), int(token_list[index + 3])]# مثلا 20 و 7 تیر ماه سال 1368
|
||
|
||
|
||
formal_date = [day, int(self.month_dict[token_list[index]]), int(token_list[index + 3])]# مثلا 27 تیر ماه سال 1368
|
||
|
||
elif(str(token_list[index + 2]).isdigit()):
|
||
if(int(token_list[index + 2])==1000):
|
||
|
||
if token_list[index-1].strip() == 'ام': # مثلا 30 ام تیر ماه 1000 و 300 و 80 و 2
|
||
start_date_index = index - 2
|
||
day = int(token_list[index - 2])
|
||
else:
|
||
# در این حالت، امکان دارد روز مربوط به این تاریخ هم به صورت حروف در متن قانون نوشته شده باشد
|
||
# به همین دلیل ، توکن های قبل از ماه را نیز کنترل می کنیم
|
||
start_date_index = index - 1
|
||
day = int(token_list[index - 1])
|
||
|
||
if(token_list[index - 2]=='و' and token_list[index - 3].isdigit()):
|
||
day += int(token_list[index - 3])# رقم دهگان روز
|
||
start_date_index = index - 3
|
||
year = 1000
|
||
if(len(token_list)>= index + 4):
|
||
if(token_list[index + 3]=='و' and token_list[index + 4].isdigit()):
|
||
year += int(token_list[index + 4])# رقم صدگان سال
|
||
end_date_index = index + 4
|
||
if(len(token_list)>= index + 6):
|
||
if(token_list[index + 5]=='و' and token_list[index + 6].isdigit()):
|
||
year += int(token_list[index + 6])# رقم دهگان سال
|
||
end_date_index = index + 6
|
||
if(len(token_list)>= index + 8):
|
||
if(token_list[index + 7]=='و' and token_list[index + 8].isdigit()):
|
||
year += int(token_list[index + 8])# رقم یکان سال
|
||
end_date_index = index + 8
|
||
formal_date = [day, int(self.month_dict[token_list[index]]), year]# مثلا 20 و 7 تیر ماه 1000 و 300 و 20 و 5
|
||
|
||
else:
|
||
formal_date = [int(token_list[index - 1]), int(self.month_dict[token_list[index]]), int(token_list[index + 2])]# مثلا 27 تیر ماه سال 1368
|
||
start_date_index = index - 1
|
||
end_date_index = index + 2
|
||
#formal_date = [int(token_list[index - 1]), int(self.month_dict[token_list[index]]), int(token_list[index + 2])] # مثلا 27 تیر ماه 1368
|
||
|
||
elif(token_list[index + 1] == 'سال' and (not(token_list[index + 2]).isdigit())):
|
||
|
||
formal_date = [int(token_list[index - 1]), int(self.month_dict[token_list[index]]), int(token_list[index + 2])] # مثلا 27 تیر سال 1368
|
||
start_date_index = index - 1
|
||
end_date_index = index + 2
|
||
else:
|
||
if(token_list[index + 1] == 'سال' and str(token_list[index + 2]).isdigit()):
|
||
|
||
if(int(token_list[index + 2])==1000):
|
||
|
||
# در این حالت، امکان دارد روز مربوط به این تاریخ هم به صورت حروف در متن قانون نوشته شده باشد
|
||
# به همین دلیل ، توکن های قبل از ماه را نیز کنترل می کنیم
|
||
start_date_index = index - 1
|
||
day = int(token_list[index - 1])
|
||
if(token_list[index - 2]=='و' and token_list[index - 3].isdigit()):
|
||
day += int(token_list[index - 3])# رقم دهگان روز
|
||
start_date_index = index - 3
|
||
year = 1000
|
||
if(len(token_list)>= index + 4):
|
||
if(token_list[index + 3]=='و' and token_list[index + 4].isdigit()):
|
||
year += int(token_list[index + 4])# رقم صدگان سال
|
||
end_date_index = index + 4
|
||
if(len(token_list)>= index + 6):
|
||
if(token_list[index + 5]=='و' and token_list[index + 6].isdigit()):
|
||
year += int(token_list[index + 6])# # رقم دهگان سال !!! برای تاریخ بین 1399 تا 1410 هم همین روال درست بر می گرداند، هرچند منطق غلطی دارد چون مثلا سال 1402 رقم صدگان ندارد
|
||
end_date_index = index + 6
|
||
if(len(token_list)>= index + 8):
|
||
if((len(token_list)>= index + 7 and token_list[index + 7]=='و') and (len(token_list)>= index + 8 and token_list[index + 8].isdigit())):
|
||
year += int(token_list[index + 8])# رقم یکان سال
|
||
end_date_index = index + 8
|
||
|
||
formal_date = [day, int(self.month_dict[token_list[index]]), year]# مثلا 20 و 8 تیر ماه سال 1000 و 300 و 20 و 5
|
||
|
||
else:
|
||
formal_date = [int(token_list[index - 1]), int(self.month_dict[token_list[index]]), int(token_list[index + 2])]# مثلا 27 تیر سال 1368
|
||
start_date_index = index - 1
|
||
end_date_index = index + 2
|
||
|
||
elif(str(token_list[index + 1]).isdigit()):
|
||
if(int(token_list[index + 1])==1000):
|
||
# در این حالت، امکان دارد روز مربوط به این تاریخ هم به صورت حروف در متن قانون نوشته شده باشد
|
||
# به همین دلیل ، توکن های قبل از ماه را نیز کنترل می کنیم
|
||
start_date_index = index - 1
|
||
day = int(token_list[index - 1])
|
||
if(token_list[index - 2]=='و' and token_list[index - 3].isdigit()):
|
||
day += int(token_list[index - 3])# رقم دهگان روز
|
||
start_date_index = index - 3
|
||
year = 1000
|
||
if(len(token_list)>= index + 3):
|
||
if(token_list[index + 2]=='و' and token_list[index + 3].isdigit()):
|
||
year += int(token_list[index + 3])# رقم صدگان سال
|
||
end_date_index = index + 3
|
||
if(len(token_list)>= index + 5):
|
||
if(token_list[index + 4]=='و' and token_list[index + 5].isdigit()):
|
||
year += int(token_list[index + 5])# رقم دهگان سال !!! برای تاریخ بین 1399 تا 1410 هم همین روال درست بر می گرداند، هرچند منطق غلطی دارد چون مثلا سال 1402 رقم صدگان ندارد
|
||
end_date_index = index + 5
|
||
if(len(token_list)>= index + 7):
|
||
if(token_list[index + 6]=='و' and token_list[index + 7].isdigit()):
|
||
year += int(token_list[index + 7])# رقم یکان سال
|
||
end_date_index = index + 7
|
||
formal_date = [day, int(self.month_dict[token_list[index]]), year]# مثلا 20 و 7 تیر ماه 1000 و 300 و 20 و 5
|
||
else:
|
||
formal_date = [int(token_list[index - 1]), int(self.month_dict[token_list[index]]), int(token_list[index + 1])]# مثلا 27 تیر 1320
|
||
start_date_index = index - 1
|
||
end_date_index = index + 1
|
||
|
||
else:
|
||
formal_date = [int(token_list[index - 1]), int(self.month_dict[token_list[index]]), int(token_list[index + 1])]# مثلا 27 تیر 1365
|
||
start_date_index = index - 1
|
||
end_date_index = index + 1
|
||
formal_date = "y" + str(formal_date[2]) + "m" + str(formal_date[1]) + "d" + str(formal_date[0])
|
||
if token_list[index - 1] and token_list[index + 1]:
|
||
return formal_date, start_date_index, end_date_index, start_date_index
|
||
|
||
except Exception as e:
|
||
error = e.args[0]
|
||
try:
|
||
formal_date = [int(token_list[index - 1]), int(self.month_dict[token_list[index]]), 0]
|
||
formal_date = "y" + str(formal_date[2]) + "m" + str(formal_date[1]) + "d" + str(formal_date[0])#مثلا y1358m12d0
|
||
return formal_date, index-1, index, index-1
|
||
except:
|
||
try:
|
||
# مثلا سال 1400
|
||
if token_list[index] == "سال":
|
||
formal_date = [int(token_list[index + 1]),0, 0]
|
||
formal_date = "y" + str(formal_date[0]) + "m" + str(formal_date[1]) + "d" + str(formal_date[2])# y1358m0d0
|
||
return formal_date, index, index+1, index
|
||
elif token_list[index+1] == "ماه" and index + 1 < len(token_list):
|
||
if index + 2 < len(token_list) and token_list[index + 2].isdigit() and \
|
||
int(token_list[index-2]) < 1450:
|
||
formal_date = [0,int(self.month_dict[token_list[index]]),int(token_list[index+2])]
|
||
formal_date = "y" + str(formal_date[2]) + "m" + str(formal_date[1]) + "d" + str(formal_date[0]) # y0m12d5
|
||
return formal_date, index, index+2, index
|
||
else:
|
||
formal_date = [0,int(self.month_dict[token_list[index]]),0]
|
||
formal_date = "y" + str(formal_date[2]) + "m" + str(formal_date[1]) + "d" + str(formal_date[0]) #y0m12d0
|
||
return formal_date, index, index+1, index
|
||
elif index + 1 < len(token_list) and token_list[index + 1].isdigit() and int(token_list[index-2]) < 1450:
|
||
formal_date = [0,int(self.month_dict[token_list[index]]),int(token_list[index+1])]
|
||
formal_date = "y" + str(formal_date[2]) + "m" + str(formal_date[1]) + "d" + str(formal_date[0]) # y0m12d5
|
||
return formal_date, index, index+1, index
|
||
elif index-2 >= 0 and index+2 < len(token_list) and \
|
||
token_list[index - 1] == "/" and token_list[index+1] == "/" and \
|
||
token_list[index - 2].isdigit() and int(token_list[index-2]) < 32 and \
|
||
token_list[index + 2].isdigit() and int(token_list[index+2]) < 1450:
|
||
formal_date = [int(token_list[index-2]),int(self.month_dict[token_list[index]]),int(token_list[index+2])]
|
||
formal_date = "y" + str(formal_date[2]) + "m" + str(formal_date[1]) + "d" + str(formal_date[0])
|
||
return formal_date, index-2, index+2, index-2
|
||
elif index + 2 < len(token_list) and token_list[index + 1] == 'سال' and \
|
||
token_list[index + 2].isdigit() and int(token_list[index-2]) < 1450 :
|
||
formal_date = [0,int(self.month_dict[token_list[index]]),int(token_list[index+2])]
|
||
formal_date = "y" + str(formal_date[2]) + "m" + str(formal_date[1]) + "d" + str(formal_date[0])
|
||
return formal_date, index, index+1, index
|
||
#else:
|
||
# print("Name : %s -> after1: %s -> after2: %s -> after3: %s" % (token_list[index], token_list[index+1], token_list[index+2], token_list[index+3]))
|
||
except:
|
||
pass
|
||
|
||
def general_normalize_date(self,normalized_string, additional_token_index_array):
|
||
# 24 /12 /1401 جهت بررسی الگوی تاریخ
|
||
normalized_string, recognized_dates = DateNormalizer.separated_date_format_finder(normalized_string)
|
||
normalized_string_list = normalized_string.strip().split()
|
||
# جهت یافتن فرمت های مختلف تاریخ غیر از فرمت بررسی شده در بالا
|
||
normalized_string, dates, recognized_dates_2 = \
|
||
self.normalize_dates(normalized_string_list, additional_token_index_array,
|
||
token_list_len = len(normalized_string_list), previous_slice_index_array=[0,])
|
||
# تجمیع همه تاریخ ها
|
||
for item in recognized_dates_2:
|
||
recognized_dates.append(item)
|
||
return normalized_string, dates, recognized_dates
|
||
|
||
# 24 /12 /1401 متد بررسی الگوی تاریخ
|
||
def separated_date_format_finder(normalized_string):
|
||
import re
|
||
date_pattern = r'\d{1,2} /\d{1,2} /\d{2,4}'
|
||
regex = re.compile(date_pattern)
|
||
match_dates = regex.finditer(normalized_string)
|
||
recognized_dates = []
|
||
for date_item in match_dates:
|
||
position = date_item.span()
|
||
founded_item = date_item.group()
|
||
start_index = date_item.start() + 1
|
||
end_index = date_item.end() - 1
|
||
current_date = founded_item.replace(' ', '')
|
||
date_parts = current_date.split('/')
|
||
formal_date = "y" + str(date_parts[2]) + "m" + str(date_parts[1]) + "d" + str(date_parts[0])
|
||
pattern_tokens_state = gf.token_state_finder(normalized_string, start_index, end_index)
|
||
recognized_dates.append(
|
||
{
|
||
"original_date" : founded_item,
|
||
"date" : formal_date,
|
||
"start_index" : start_index,
|
||
"end_index" : end_index,
|
||
"date_token_index" : pattern_tokens_state["start_token_state"],
|
||
"start_date_token_index": pattern_tokens_state["start_token_state"],
|
||
"end_date_token_index" : pattern_tokens_state["end_token_state"],
|
||
})
|
||
normalized_string_list = normalized_string.strip().split()
|
||
for date_item in recognized_dates:
|
||
normalized_string_list[int(date_item['date_token_index'])] = date_item['date']
|
||
normalized_string_list[int(date_item['start_date_token_index'])+1] = 'tttt'
|
||
normalized_string_list[int(date_item['end_date_token_index'])] = 'tttt'
|
||
normalized_string_temp = ''
|
||
for token in normalized_string_list:
|
||
normalized_string_temp = normalized_string_temp + ' ' + token
|
||
return normalized_string_temp.strip(), recognized_dates
|
||
|
||
def normalize_dates(self, token_list, additional_token_index_array, token_list_len, previous_slice_index_array= []):
|
||
try:
|
||
finded = self.find_date_part(token_list)
|
||
except Exception as e:
|
||
finded = None
|
||
gf.save_error(0, e)
|
||
|
||
recognized_dates = []
|
||
if finded != None:
|
||
date_part = finded[0]
|
||
start_date_token_index = finded[1]
|
||
end_date_token_index = finded[2]
|
||
date_token_index = finded[3]
|
||
befor_date_part = " ".join(x for x in token_list[:start_date_token_index])
|
||
after_date_part = [x for x in token_list[end_date_token_index + 1:]]
|
||
previous_slice_index = token_list_len - len(after_date_part)
|
||
previous_slice_index_array.append(previous_slice_index)
|
||
after_normalized, after_dates, recognized_dates = self.normalize_dates(after_date_part, additional_token_index_array, token_list_len, previous_slice_index_array)
|
||
if after_dates == '':
|
||
after_dates = []
|
||
if recognized_dates == '':
|
||
recognized_dates = []
|
||
after_dates.insert(0, date_part)
|
||
previous_slice_index = previous_slice_index_array.pop(len(previous_slice_index_array)-2)
|
||
recognized_dates.append(
|
||
{
|
||
"date" : date_part,
|
||
"date_token_index" : date_token_index + previous_slice_index,
|
||
"start_date_token_index": start_date_token_index + previous_slice_index,
|
||
"end_date_token_index" : end_date_token_index + previous_slice_index
|
||
})
|
||
|
||
i = 0
|
||
while((date_token_index - start_date_token_index) > i ):
|
||
befor_date_part = ''.join([befor_date_part," tttt"]) # به عنوان توکنی که از جنس تاریخ بوده t
|
||
i += 1
|
||
i = 0
|
||
while((end_date_token_index - date_token_index) > i ):
|
||
date_part = ''.join([date_part," tttt"]) # به عنوان توکنی که از جنس تاریخ بوده t
|
||
i += 1
|
||
|
||
return befor_date_part + " " + date_part + " " + after_normalized, after_dates, recognized_dates
|
||
else:
|
||
return " ".join(x for x in token_list), '',''
|
||
|
||
def list2num(self, numerical_section_list):
|
||
value = 1
|
||
l = len(numerical_section_list)>3
|
||
if l :
|
||
value = 0
|
||
for index, el in enumerate(numerical_section_list):
|
||
if self.is_number(el):
|
||
value = self.num_dict[el]
|
||
elif el == '000':
|
||
#value *= 1000
|
||
pass
|
||
elif l == True:
|
||
value += float(el)
|
||
else:
|
||
value *= float(el)
|
||
return value
|
||
|
||
def convert2num(self, numerical_section_list):
|
||
value = 0
|
||
tmp_section_list = []
|
||
for index, el in enumerate(numerical_section_list):
|
||
if self.is_number(el) or (el.replace('.', '', 1).isdigit()):
|
||
tmp_section_list.append(el)
|
||
elif el == "و":
|
||
value += self.list2num(tmp_section_list)
|
||
tmp_section_list[:] = []
|
||
if len(tmp_section_list) > 0:
|
||
value += self.list2num(tmp_section_list)
|
||
tmp_section_list[:] = []
|
||
try:
|
||
if (value-int(value) == 0):
|
||
return int(value)
|
||
else:
|
||
return value
|
||
except:
|
||
return 0
|
||
|
||
|
||
def is_number(self, word):
|
||
return word in self.num_dict
|
||
|
||
def find_number_location(self, token_list, addWithVaa = False):
|
||
start_index = 0
|
||
number_section =[]
|
||
for i , el in enumerate(token_list):
|
||
if self.is_number(el) or (el.replace('.', '', 1).isdigit()):
|
||
start_index = i
|
||
number_section.append(start_index)
|
||
break
|
||
|
||
i = start_index+1
|
||
while(i < len(token_list)):
|
||
if token_list[i] == "و" and (i+1)<len(token_list) and addWithVaa:
|
||
if self.is_number(token_list[i+1]) or (token_list[i+1].replace('.', '', 1).isdigit()):
|
||
number_section.append(i)
|
||
number_section.append(i+1)
|
||
i += 2
|
||
else:
|
||
break
|
||
elif self.is_number(token_list[i]) or (token_list[i].replace('.', '', 1).isdigit()):
|
||
number_section.append(i)
|
||
i += 1
|
||
elif token_list[i] == "/" and (i+1)<len(token_list) and token_list[i+1] == "000":
|
||
number_section.append(i)
|
||
number_section.append(i+1)
|
||
i += 2
|
||
else:
|
||
break
|
||
return number_section
|
||
|
||
def normalize_numbers(self, token_list, converted=""):
|
||
for i, el in enumerate(token_list):
|
||
if el.endswith("ین") and self.is_number(el[:-2]):
|
||
token_list[i] = el[:-2]
|
||
finded = self.find_number_location(token_list)
|
||
if len(finded) == 0:
|
||
rest_of_string = " ".join(t for t in token_list)
|
||
return converted + " " + rest_of_string
|
||
else:
|
||
numerical_subsection = [token_list[x] for x in finded]
|
||
numerical_subsection = self.convert2num(numerical_subsection)
|
||
|
||
converted = converted + " " + " ".join(x for x in token_list[:finded[0]]) + " " + str(numerical_subsection)
|
||
|
||
new_index = finded[-1] + 1
|
||
return self.normalize_numbers(token_list[new_index:], converted)
|
||
|
||
# این متد برای تبدیل اعدادی حروفی به معادل رقمی ایجاد شده است
|
||
def normalize_numbers2(self, token_list, converted=""):
|
||
additional_token_index_array = [] # آرایه ای از توکن هایی که اضافه بر اصل متن ممکن است در این متد اضافه شوند
|
||
for index, token in enumerate(token_list):
|
||
|
||
if token in self.num_dict:
|
||
if token.startswith('و'): # برای حالتی مانند وسیصد که بین واو و سیصد، فاصله ای وجود ندارد
|
||
temp_token = token[1:]
|
||
if temp_token in self.num_dict:
|
||
# در متن، واو را از عدد جدا می کنیم
|
||
# در این حالت یک توکن به متن اصلی اضافه می شود که باید کنترل شود
|
||
converted = converted + " " + "و" + " " + str(int(self.num_dict[token]))
|
||
additional_token_index_array.append(index)
|
||
else:
|
||
converted = converted + " " + str(int(self.num_dict[token]))
|
||
else:
|
||
converted = converted + " " + token
|
||
return converted, additional_token_index_array
|
||
|
||
# این متد برای ضرب اعداد متوالی با جدا کننده اسپیس ایجاد شده
|
||
def multiply_continuous_numbers(self, normalized_string):
|
||
token_list = normalized_string.strip().split()
|
||
converted_string = ''
|
||
for index,token in enumerate(token_list):
|
||
num_array = []
|
||
if token.isdigit():
|
||
#if (token_list[index+1]).isdigit():
|
||
# اگر عدد مورد نظر با فرمت بالا نبود، حالت اعداد بدون فاصله کنار هم که باید در هم ضرب شوند را بررسی می کنیم
|
||
num_array.clear()
|
||
num_array.append(int(token))
|
||
step = 1
|
||
deletting_indexes = []
|
||
num_array_sum = 1
|
||
while True:
|
||
if (token_list[index+step]).isdigit() :
|
||
num_array.append(int(token_list[index+step]))
|
||
deletting_indexes.append(index+step)
|
||
step += 1
|
||
continue
|
||
else:
|
||
break
|
||
|
||
for index in deletting_indexes:
|
||
# بازای توکن هایی که عدد هستند و به دلیل ضرب در هم شدن باید حذف شوند، رشته بی معنی زیر را جایگزین کن
|
||
token_list[index] = 'nnnn' # به معنای توکنی که از جنس عدد بوده number
|
||
for number in num_array: # ،عدادی که پشت سرهم بوده اند، بدون فاصله و در مراحل قبل پردازش نشده اند و در آرایه ذخیره شده را ضرب می کند و در یک عدد، یک کاسه می کند، مثلا 2 1000 1000000000 تومان را
|
||
num_array_sum *= number
|
||
converted_string = converted_string + " " + str(num_array_sum)
|
||
|
||
else:
|
||
converted_string = converted_string + " " + token
|
||
return converted_string
|
||
|
||
# این متد برای جمع اعداد متوالی با جدا کننده واو ایجاد شده
|
||
def sum_continuous_numbers(self, normalized_string):
|
||
token_list = normalized_string.strip().split()
|
||
converted_string = ''
|
||
operand = '+'
|
||
for index,token in enumerate(token_list):
|
||
num_array = []
|
||
if token.isdigit():
|
||
# این بخش، متن را بررسی می کند و اعداد دو یا سه رقمی و بیشتر که با واو از هم جدا شده را با هم جمع و یک کاسه می کند
|
||
if token_list[index+1]=='و': # 2 , 50 , 600 :مانند
|
||
|
||
if(int(token) % 10 != 0): # اگر عدد دو یا سه یا چهار یا ... رقمی باشد، رقم دهگاه، صدگان، هزارگان و ... باید باقیمانده شان بر 2 برابر با صفر باشد، اگر نبود، ادامه نده
|
||
converted_string = converted_string + " " + token
|
||
else:
|
||
num_array.append(int(token))
|
||
step = 1
|
||
deletting_indexes = []
|
||
num_array_sum = 0
|
||
while True:
|
||
if token_list[index+step] == 'و' :
|
||
# اگر یکی از شرط های زیر را داشت، اعدادی که با واو جدا شده اند، مربوط به تاریخ هستند و نباید جمع عددی انجام شود
|
||
if (token_list[index+step+1] == 'tttt' or token_list[index+step+1].startswith('y')):
|
||
deletting_indexes.clear()
|
||
num_array.clear()
|
||
num_array_sum = int(token)
|
||
break
|
||
elif token_list[index+step+1].isdigit() and token_list[index+step+2]=='nnnn' :
|
||
operand = '*'
|
||
num_array_sum = 1
|
||
num_array.append(int(token_list[index+step+1]))
|
||
# ذخیره کردن ایندکس هایی که جمع شده و باید به جای آن یک توکن خنثی بگذاریم
|
||
deletting_indexes.append(index+step)
|
||
deletting_indexes.append(index+step+1)
|
||
step += 3
|
||
continue
|
||
elif token_list[index+step+1].isdigit() :
|
||
num_array.append(int(token_list[index+step+1]))
|
||
# ذخیره کردن ایندکس هایی که جمع شده و باید به جای آن یک توکن خنثی بگذاریم
|
||
deletting_indexes.append(index+step)
|
||
deletting_indexes.append(index+step+1)
|
||
step += 2
|
||
continue
|
||
else:
|
||
break
|
||
|
||
for index in deletting_indexes:
|
||
# بازای توکن هایی که عدد یا واو هستند و باید حذف شوند، رشته بی معنی زیر را جایگزین کن
|
||
token_list[index] = 'nnnn' # به معنای توکنی که از جنس عدد بوده number
|
||
|
||
for number in num_array: # اعدادی که با واو پشت سرهم بوده اند و در آرایه ذخیره شده را جمع می کند و در یک عدد، یک کاسه می کند
|
||
if operand == '+':
|
||
num_array_sum += number
|
||
elif operand == '*':
|
||
num_array_sum *= number
|
||
converted_string = converted_string + " " + str(num_array_sum)
|
||
|
||
else:
|
||
converted_string = converted_string + " " + token
|
||
return converted_string
|
||
|
||
# این متد اعداد پشت سر هم که با اسپیس یا واو از هم جدا شده اند و باید تبدیل به یک عدد به صورت یک کاسه شوند را هندل می کند
|
||
def handle_continuous_numbers(self, normalized_string):
|
||
token_list = normalized_string.strip().split()
|
||
converted_string = ''
|
||
number_parts_array = []
|
||
start_token_index = 0
|
||
end_token_index = 0
|
||
recognized_numbers = []
|
||
flag = True
|
||
is_tabsare_numbers = False
|
||
is_mavad_numbers = False
|
||
is_madde_numbers = False
|
||
for token_index,token in enumerate(token_list):
|
||
if token.isdigit() :
|
||
# if token == '61' :
|
||
# print(len(token_list))
|
||
if token_index - 2 >= 0:
|
||
# تشخیص اینکه یک سلسله از اعداد که با واو از هم جدا شده اند تبصره های مربوط به یک ماده نباشند
|
||
is_tabsare_numbers = (token_list[token_index-2] + ' ' + token_list[token_index-1]=='تبصره های')
|
||
if token_index - 1 >= 0:
|
||
# تشخیص اینکه یک سلسله از اعداد که با واو از هم جدا شده اند مواد یک قانون نباشند
|
||
is_mavad_numbers = (token_list[token_index-1]=='مواد')
|
||
if token_index - 1 >= 0:
|
||
# تشخیص اینکه یک سلسله از اعداد که با واو از هم جدا شده اند ماده های یک قانون نباشند
|
||
is_madde_numbers = (token_list[token_index-1]=='ماده')
|
||
if is_tabsare_numbers or is_mavad_numbers or is_madde_numbers:
|
||
flag = False
|
||
start_token_index = end_token_index = token_index
|
||
number_parts_array.clear()
|
||
current_token_index = token_index
|
||
number_parts_array.append(token)
|
||
if current_token_index + 1 < len(token_list):
|
||
while ((flag) and (token_list[current_token_index+1] == 'و' or token_list[current_token_index+1].isdigit())):
|
||
number_parts_array.append(token_list[current_token_index+1])
|
||
current_token_index += 1
|
||
end_token_index = current_token_index
|
||
if not (current_token_index + 1 < len(token_list)):
|
||
break
|
||
|
||
final_number = number_completter(number_parts_array)
|
||
token_list[token_index] = str(final_number)
|
||
recognized_numbers.append({
|
||
'number_value' : final_number,
|
||
'number_token_list': number_parts_array,
|
||
'start_token_index': start_token_index,
|
||
'end_token_index' : end_token_index
|
||
})
|
||
# جایگذاری مقدار رشته بی ارزش به جای توکن های مربوط به عدد جاری
|
||
# به منظور اینکه متن اصلی از نظر تعداد توکن تغییر نکند
|
||
for i in range(token_index + 1 , len(number_parts_array) + token_index):
|
||
token_list[i] = 'nnnn'
|
||
converted_string = converted_string + ' ' + token_list[token_index]
|
||
if token_index + 1 < len(token_list):
|
||
if flag == False and (token_list[token_index+1]=='و'):
|
||
flag = False
|
||
else:
|
||
flag = True
|
||
else:
|
||
converted_string = converted_string + ' ' + token
|
||
|
||
return converted_string, recognized_numbers
|
||
|
||
|
||
|
||
|
||
def remove_additional_tokens(self,token_list,additional_token_index_array):
|
||
converted_string = ''
|
||
for index in additional_token_index_array:
|
||
del token_list[index]
|
||
|
||
for token in token_list:
|
||
converted_string = converted_string + ' ' + token
|
||
return converted_string
|
||
|
||
class PinglishNormalizer():
|
||
def __init__(self):
|
||
# self.data_helper = DataHelper()
|
||
self.file_dir = os.path.dirname(os.path.realpath(__file__)) + "/"
|
||
|
||
self.en_dict_filename = self.file_dir + "resource/tokenizer/enDict"
|
||
# self.en_dict = self.data_helper.load_var(self.en_dict_filename)
|
||
|
||
self.fa_dict_filename = self.file_dir + "resource/tokenizer/faDict"
|
||
# self.fa_dict = self.data_helper.load_var(self.fa_dict_filename)
|
||
|
||
|
||
def pingilish2persian(self, pinglish_words_list):
|
||
|
||
for i, word in enumerate(pinglish_words_list):
|
||
if word in self.en_dict:
|
||
pinglish_words_list[i] = self.en_dict[word]#.decode("utf-8")
|
||
#inp = inp.replace(word, enDict[word], 1)
|
||
else:
|
||
ch = self.characterize(word)
|
||
pr = self.map_char(ch)
|
||
amir = self.make_word(pr)
|
||
for wd in amir:
|
||
am = self.escalation(wd)
|
||
asd = ''.join(am)
|
||
if asd in self.fa_dict:
|
||
pinglish_words_list[i] = asd#.decode("utf-8")
|
||
#inp = inp.replace(word, asd, 1)
|
||
inp = " ".join(x for x in pinglish_words_list)
|
||
return inp
|
||
|
||
def characterize(self, word):
|
||
list_of_char = []
|
||
i = 0
|
||
while i < len(word):
|
||
char = word[i]
|
||
sw_out = self.switcher(char)
|
||
if (sw_out == None):
|
||
esp_out = None
|
||
if(i < len(word) - 1):
|
||
esp_out = self.esp_check(word[i], word[i + 1])
|
||
if(esp_out == None):
|
||
list_of_char.append(word[i])
|
||
else:
|
||
list_of_char.append(esp_out)
|
||
i += 1
|
||
else:
|
||
list_of_char.append(sw_out)
|
||
i += 1
|
||
return list_of_char
|
||
|
||
def switcher(self, ch):
|
||
switcher = {
|
||
"c": None,
|
||
"k": None,
|
||
"z": None,
|
||
"s": None,
|
||
"g": None,
|
||
"a": None,
|
||
"u": None,
|
||
"e": None,
|
||
"o": None
|
||
}
|
||
return switcher.get(ch, ch)
|
||
|
||
def esp_check(self, char1, char2):
|
||
st = char1 + char2
|
||
if (st == "ch"):
|
||
return "ch"
|
||
elif (st == "kh"):
|
||
return "kh"
|
||
elif (st == "zh"):
|
||
return "zh"
|
||
elif (st == "sh"):
|
||
return "sh"
|
||
elif (st == "gh"):
|
||
return "gh"
|
||
elif (st == "aa"):
|
||
return "aa"
|
||
elif (st == "ee"):
|
||
return "ee"
|
||
elif (st == "oo"):
|
||
return "oo"
|
||
elif (st == "ou"):
|
||
return "ou"
|
||
else:
|
||
return None
|
||
|
||
def map_char(self, word):
|
||
listm = []
|
||
sw_out = self.map_switcher(word[0])
|
||
i = 0
|
||
if (sw_out == None):
|
||
listm.append(["ا"])
|
||
i += 1
|
||
if (word[0] == "oo"):
|
||
listm.append(["او"])
|
||
i += 1
|
||
while i < len(word):
|
||
listm.append(self.char_switcher(word[i]))
|
||
i += 1
|
||
if word[len(word) - 1] == "e":
|
||
listm.append(["ه"])
|
||
elif word[len(word) - 1] == "a":
|
||
listm.append(["ا"])
|
||
elif word[len(word) - 1] == "o":
|
||
listm.append(["و"])
|
||
elif word[len(word) - 1] == "u":
|
||
listm.append(["و"])
|
||
|
||
return listm
|
||
|
||
def map_switcher(self, ch):
|
||
switcher = {
|
||
"a": None,
|
||
"e": None,
|
||
"o": None,
|
||
"u": None,
|
||
"ee": None,
|
||
|
||
"ou": None
|
||
}
|
||
return switcher.get(ch, ch)
|
||
|
||
def make_word(self, chp):
|
||
word_list = [[]]
|
||
for char in chp:
|
||
word_list_temp = []
|
||
for tmp_word_list in word_list:
|
||
for chch in char:
|
||
tmp = copy.deepcopy(tmp_word_list)
|
||
tmp.append(chch)
|
||
word_list_temp.append(tmp)
|
||
word_list = word_list_temp
|
||
return word_list
|
||
|
||
def escalation(self, word):
|
||
tmp = []
|
||
i = 0
|
||
t = len(word)
|
||
while i < t - 1:
|
||
tmp.append(word[i])
|
||
if word[i] == word[i + 1]:
|
||
i += 1
|
||
i += 1
|
||
if i != t:
|
||
tmp.append(word[i])
|
||
return tmp
|
||
|
||
def char_switcher(self, ch):
|
||
switcher = {
|
||
'a': ["", "ا"],
|
||
'c': ["ث", "ص", "ص"],
|
||
'h': ["ه", "ح"],
|
||
'b': ["ب"],
|
||
'p': ["پ"],
|
||
't': ["ت", "ط"],
|
||
's': ["س", "ص", "ث"],
|
||
'j': ["ج"],
|
||
'ch': ["چ"],
|
||
'kh': ["خ"],
|
||
'q': ["ق", "غ"],
|
||
'd': ["د"],
|
||
'z': ["ز", "ذ", "ض", "ظ"],
|
||
'r': ["ر"],
|
||
'zh': ["ژ"],
|
||
'sh': ["ش"],
|
||
'gh': [",ق", "غ"],
|
||
'f': ["ف"],
|
||
'k': ["ک"],
|
||
'g': ["گ"],
|
||
'l': ["ل"],
|
||
'm': ["م"],
|
||
'n': ["ن"],
|
||
'v': ["و"],
|
||
'aa': ["ا"],
|
||
'ee': ["ی"],
|
||
'oo': ["و"],
|
||
'ou': ["و"],
|
||
'i': ["ی"],
|
||
'y': ["ی"],
|
||
' ': [""],
|
||
'w': ["و"],
|
||
'e': ["", "ه"],
|
||
'o': ["", "و"]
|
||
}
|
||
return switcher.get(ch, "")
|
||
|
||
# این روال جهت جمع و ضرب کردن بخش های مختلف از صدگان و هزارگان و بالاتر از یک عدد که با حروف در متن وجود دارد کار می کند
|
||
def number_completter2(number_parts_array):
|
||
zarb_value = 0
|
||
temp_number_array = []
|
||
sum_number_parts = 0
|
||
final_number = 0
|
||
for index,item in enumerate(number_parts_array):
|
||
if item.isdigit():
|
||
temp_number_array.append(int(item))
|
||
if index + 1 >= len(number_parts_array):
|
||
for item3 in temp_number_array:
|
||
final_number += int(item3)
|
||
return final_number
|
||
current_value = number_parts_array[index+1]
|
||
if (current_value.isdigit() and (int(current_value) == 1000 or int(current_value) == 1000000 or int(current_value) == 1000000000)):# or int(current_value) == 1000000
|
||
zarb_value = int(number_parts_array[index+1])
|
||
for num_item in temp_number_array:
|
||
sum_number_parts += num_item
|
||
final_number = sum_number_parts * zarb_value
|
||
temp_array2 = []
|
||
x = index + 2
|
||
while x < len(number_parts_array):
|
||
# for x in range(index+2,len(number_parts_array)):
|
||
temp_array2.append(number_parts_array[x])
|
||
if x + 1 < len(number_parts_array):
|
||
if number_parts_array[x+1].isdigit() and (int(number_parts_array[x+1]) == 1000 or int(number_parts_array[x+1]) == 1000000 or int(number_parts_array[x+1]) == 1000000000):
|
||
if int(number_parts_array[x+1]) > zarb_value: # 1000000>1000
|
||
zarb_value = int(number_parts_array[x+1])
|
||
# تابع بازگشتی برای محاسبه عدد نهایی
|
||
final_number += number_completter2(temp_array2)
|
||
final_number *= zarb_value
|
||
temp_array2.clear()
|
||
zarb_value = 0
|
||
x += 2 # به این دلیل که مقدار ضرب را در آرایه تمپ ذخیره نکند
|
||
else: # 1000!>1000000
|
||
zarb_value = int(number_parts_array[x+1])
|
||
temp_num = 0
|
||
if (zarb_value == 1000 or zarb_value == 1000000) and len(number_parts_array) > x + 1:
|
||
num_array = number_parts_array[x+2:len(number_parts_array)]
|
||
temp_num = number_completter(num_array)
|
||
if temp_num == None:
|
||
temp_num = 0
|
||
|
||
'''for i in range(x+2,len(number_parts_array)):
|
||
if(number_parts_array[i].isdigit()):
|
||
temp_num += int(number_parts_array[i])
|
||
i+=1'''
|
||
temp_num2 = 1
|
||
for num_item2 in temp_array2:
|
||
if(num_item2.isdigit()):
|
||
temp_num2 += int(num_item2)
|
||
|
||
temp_num2 *= zarb_value
|
||
final_number += temp_num + temp_num2
|
||
break
|
||
else:
|
||
x += 1 #
|
||
else: # اگر از رنج آرایه خارج شدیم
|
||
temp_num = 0
|
||
# مقادیر موجود در آرایه تمپ را جمع کن
|
||
for num_item3 in temp_array2:
|
||
if(num_item3.isdigit()):
|
||
temp_num += int(num_item3)
|
||
# حاصل جمع اعداد موجود در آرایه ذخیره را در عدد نهایی که قبلا داشته ایم ضرب کن و از حلقه خارج شو
|
||
final_number *= temp_num
|
||
#final_number += temp_num
|
||
break
|
||
return final_number
|
||
|
||
# این روال جهت جمع و ضرب کردن بخش های مختلف از صدگان و هزارگان و بالاتر از یک عدد که با حروف در متن وجود دارد کار می کند
|
||
def number_completter(number_parts_array):
|
||
zarb_value = 0
|
||
previous_zarb_value = 0
|
||
previous_number_parts_sum = 0
|
||
temp_number_array = []
|
||
number_parts_sum = 0
|
||
final_number = 0
|
||
current_number_part = 0
|
||
for index,item in enumerate(number_parts_array):
|
||
if item.isdigit():
|
||
if (not(int(item) == 1000 or int(item) == 1000000 or int(item) == 1000000000)):
|
||
temp_number_array.append(item)
|
||
continue
|
||
elif((int(item) == 1000 or int(item) == 1000000 or int(item) == 1000000000)):
|
||
zarb_value = int(item)
|
||
for num_item in temp_number_array:
|
||
number_parts_sum += int(num_item)
|
||
if number_parts_sum == 0 and previous_number_parts_sum == 0:
|
||
number_parts_sum = 1
|
||
temp_number_array.clear()
|
||
|
||
else:# for example 952
|
||
zarb_value = 1
|
||
for num_item in temp_number_array:
|
||
number_parts_sum += int(num_item)
|
||
current_number_part = number_parts_sum + previous_number_parts_sum
|
||
continue
|
||
if previous_zarb_value < zarb_value:# for example 1000 < 1000000000
|
||
current_number_part = previous_number_parts_sum + number_parts_sum
|
||
current_number_part = zarb_value * current_number_part
|
||
else:# previous_zarb_value > zarb_value
|
||
if number_parts_sum == 0:
|
||
number_parts_sum = 1
|
||
current_number_part = zarb_value * number_parts_sum
|
||
current_number_part += previous_number_parts_sum
|
||
|
||
previous_number_parts_sum = current_number_part
|
||
current_number_part = 0
|
||
previous_zarb_value = zarb_value
|
||
number_parts_sum = 0
|
||
if len(temp_number_array) != 0:
|
||
remained_parts_sum = 0
|
||
for num_item in temp_number_array:
|
||
remained_parts_sum += int(num_item)
|
||
final_number = previous_number_parts_sum + remained_parts_sum
|
||
return final_number
|
||
|
||
final_number = previous_number_parts_sum
|
||
return final_number
|
||
|
||
|
||
def cleanhtml(raw_html):
|
||
cleanr = re.compile('<.*?>')
|
||
cleantext = re.sub(cleanr, '', raw_html)
|
||
return cleantext
|
||
|
||
# normalizer = hazm.Normalizer()
|
||
wierd_pattern = re.compile("["
|
||
u"\U0001F600-\U0001F64F" # emoticons
|
||
u"\U0001F300-\U0001F5FF" # symbols & pictographs
|
||
u"\U0001F680-\U0001F6FF" # transport & map symbols
|
||
u"\U0001F1E0-\U0001F1FF" # flags (iOS)
|
||
u"\U00002702-\U000027B0"
|
||
u"\U000024C2-\U0001F251"
|
||
u"\U0001f926-\U0001f937"
|
||
u'\U00010000-\U0010ffff'
|
||
u"\u200d"
|
||
u"\u2640-\u2642"
|
||
u"\u2600-\u2B55"
|
||
u"\u23cf"
|
||
u"\u23e9"
|
||
u"\u231a"
|
||
u"\u3030"
|
||
u"\ufe0f"
|
||
u"\u2069"
|
||
u"\u2066"
|
||
u"\u200c"
|
||
u"\u2068"
|
||
u"\u2067"
|
||
"]+", flags=re.UNICODE)
|
||
|
||
def cleaning(text):
|
||
text = text.strip()
|
||
text = clean(text,
|
||
extra_spaces = True,
|
||
lowercase = True
|
||
)
|
||
|
||
# cleaning htmls
|
||
text = cleanhtml(text)
|
||
|
||
# normalizing
|
||
text = normalizer.normalize(text)
|
||
|
||
# removing wierd patterns
|
||
text = wierd_pattern.sub(r'', text)
|
||
|
||
# removing extra spaces, hashtags
|
||
text = re.sub("#", "", text)
|
||
text = re.sub("\s+", " ", text)
|
||
|
||
return text
|
||
|