senyukhin/annotator
0
1from yargy import (2 Parser,3 rule,4 and_, or_5)6from yargy.interpretation import fact7from yargy.predicates import (8 eq, gte, lte, length_eq,9 dictionary, normalized,10)11import pandas as pd12 13 14DateRange = fact(15 'DateRange',16 ['start_day', 'start_month', 'start_year', 'stop_day', 'stop_month', 'stop_year']17)18class DateRange(DateRange):19 years_collection = [1900]20 21 @property22 def normalized(self):23 if self.start_year != None:24 self.years_collection.append(self.start_year)25 else:26 self.start_year = self.years_collection[-1]27 28 if self.start_day == None:29 self.start_day = 030 31 if self.start_month == None:32 self.start_month = 033 34 if self.stop_year == None:35 self.stop_year = self.start_year36 37 if self.stop_month == None:38 self.stop_month = self.start_month39 40 if self.stop_day == None:41 self.stop_day = self.start_day42 43 return self44 @property45 def get_start_date(self):46 return str(self.start_year) + '-' + str(self.start_month).zfill(2) + '-' + str(self.start_day).zfill(2)47 @property48 def get_stop_date(self):49 return str(self.stop_year) + '-' + str(self.stop_month).zfill(2) + '-' + str(self.stop_day).zfill(2)50 51MONTHS = {52 'январь': 1,53 'февраль': 2,54 'март': 3,55 'апрель': 4,56 'май': 5,57 'июнь': 6,58 'июль': 7,59 'август': 8,60 'сентябрь': 9,61 'октябрь': 10,62 'ноябрь': 11,63 'декабрь': 12,64}65 66 67MONTHS_LATIN = {68 'I': 1,69 'II': 2,70 'III': 3,71 'IV': 4,72 'V': 5,73 'VI': 6,74 'VII': 7,75 'VIII': 8,76 'IX': 9,77 'X': 10,78 'XI': 11,79 'XII': 1280}81 82DAY_START = and_(83 gte(1),84 lte(31)85).interpretation(86 DateRange.start_day.custom(int)87)88 89DAY_STOP = and_(90 gte(1),91 lte(31)92).interpretation(93 DateRange.stop_day.custom(int)94)95 96MONTH_NAME_START = dictionary(MONTHS).interpretation(97 DateRange.start_month.normalized().custom(MONTHS.__getitem__)98)99 100MONTH_NAME_STOP = dictionary(MONTHS).interpretation(101 DateRange.stop_month.normalized().custom(MONTHS.__getitem__)102)103 104MONTH_LATIN_NAME_START = dictionary(MONTHS_LATIN).interpretation(105 DateRange.start_month.custom(MONTHS_LATIN.__getitem__)106)107 108MONTH_LATIN_NAME_STOP = dictionary(MONTHS_LATIN).interpretation(109 DateRange.stop_month.custom(MONTHS_LATIN.__getitem__)110)111 112MONTH_START = and_(113 gte(1),114 lte(12)115).interpretation(116 DateRange.start_month.custom(int)117)118 119MONTH_STOP = and_(120 gte(1),121 lte(12)122).interpretation(123 DateRange.stop_month.custom(int)124)125 126 127YEAR_START = and_(128 gte(1800),129 lte(2100)130).interpretation(131 DateRange.start_year.custom(int)132)133 134YEAR_STOP = and_(135 gte(1800),136 lte(2100)137).interpretation(138 DateRange.stop_year.custom(int)139)140 141YEAR_SHORT_START = and_(142 length_eq(2),143 gte(0),144 lte(99)145).interpretation(146 DateRange.start_year.custom(lambda _: 1900 + int(_))147)148 149YEAR_SHORT_STOP = and_(150 length_eq(2),151 gte(0),152 lte(99)153).interpretation(154 DateRange.stop_year.custom(lambda _: 1900 + int(_))155)156 157YEAR_WORD = or_(158 rule('г', eq('.').optional()),159 rule(normalized('год'))160)161 162PUNCT_DIVISION_DATES = or_(163 rule('-'), # дефис164 rule('—'), # короткое тире165 rule('—') # длинное тире166)167 168PUNCT = or_(169 rule('.'),170 rule('/')171)172 173DATE_RANGE = or_(174 # 1-2 января 1900175 rule(176 DAY_START,177 PUNCT_DIVISION_DATES,178 DAY_STOP,179 PUNCT.optional(),180 or_(181 MONTH_NAME_START,182 MONTH_START,183 MONTH_LATIN_NAME_START184 ),185 PUNCT.optional(),186 or_(187 YEAR_START,188 YEAR_SHORT_START189 ).optional(),190 YEAR_WORD.optional()191 ),192 # 1 января - 2 февраля 1900193 rule(194 DAY_START,195 PUNCT.optional(),196 or_(197 MONTH_NAME_START,198 MONTH_START,199 MONTH_LATIN_NAME_START200 ),201 PUNCT_DIVISION_DATES,202 DAY_STOP,203 PUNCT.optional(),204 or_(205 MONTH_NAME_STOP,206 MONTH_STOP,207 MONTH_LATIN_NAME_STOP208 ),209 PUNCT.optional(),210 or_(211 YEAR_START,212 YEAR_SHORT_START213 ).optional(),214 YEAR_WORD.optional()215 ),216 # 1 января 1900 - 2 февраля 1901217 rule(218 DAY_START,219 PUNCT.optional(),220 or_(221 MONTH_NAME_START,222 MONTH_START,223 MONTH_LATIN_NAME_START224 ),225 PUNCT.optional(),226 or_(227 YEAR_START,228 YEAR_SHORT_START229 ),230 PUNCT_DIVISION_DATES,231 DAY_STOP,232 PUNCT.optional(),233 or_(234 MONTH_NAME_STOP,235 MONTH_STOP,236 MONTH_LATIN_NAME_STOP237 ),238 PUNCT.optional(),239 or_(240 YEAR_STOP,241 YEAR_SHORT_STOP242 ),243 YEAR_WORD.optional()244 ),245 # 1/I-1900 - 2/II-1901246 rule(247 DAY_START,248 PUNCT,249 MONTH_LATIN_NAME_START,250 '-',251 or_(252 YEAR_START,253 YEAR_SHORT_START254 ),255 PUNCT_DIVISION_DATES,256 DAY_STOP,257 PUNCT,258 MONTH_LATIN_NAME_STOP,259 '-',260 or_(261 YEAR_STOP,262 YEAR_SHORT_STOP263 ),264 YEAR_WORD.optional()265 ),266 # 1.1.1900 / 1/II/1900 / 1 января267 rule(268 DAY_START,269 PUNCT.optional(),270 or_(271 MONTH_START,272 MONTH_NAME_START,273 MONTH_LATIN_NAME_START274 ),275 PUNCT.optional(),276 or_(277 YEAR_START,278 YEAR_SHORT_START279 ).optional(),280 YEAR_WORD.optional()281 ),282 # 1/II-1900283 rule(284 DAY_START,285 PUNCT,286 MONTH_LATIN_NAME_START,287 '-',288 or_(289 YEAR_START,290 YEAR_SHORT_START291 ),292 YEAR_WORD.optional()293 ),294 # 1900 год295 rule(296 YEAR_START,297 YEAR_WORD.optional()298 ),299 # январь 1900 года300 rule(301 MONTH_NAME_START,302 or_(303 YEAR_START,304 YEAR_SHORT_START305 ),306 YEAR_WORD.optional()307 ),308).interpretation(309 DateRange310)311 312 313def date_extractor_for_diary(text):314 res = {315 'date_start' : [],316 'date_stop' : [],317 'text' : []318 }319 entry = ''320 for paragraph in text.split('\n'):321 parser = Parser(DATE_RANGE)322 for match in parser.findall(paragraph):323 record = match.fact.normalized324 if record.spans[0].start in range (0, 3):325 start = record.get_start_date326 stop = record.get_stop_date327 res['date_start'].append(start)328 res['date_stop'].append(stop)329 if entry != '':330 res['text'].append(entry)331 entry = ''332 break333 entry += paragraph334 entry += '\n'335 if entry != '':336 res['text'].append(entry)337 338 return pd.DataFrame(res)339 340def normalize_dates(start, stop):341 if start == stop:342 return start343 else: 344 return f'{start} - {stop}'345 346######## USAGE ###########347 348# parser = Parser(DATE_RANGE)349 350# text = '''351# 1943352 353# 24 марта. Челябинск354 355# Сегодня кончается третья четверть. Потом каникулы до 1/IV — неделю. Говорили с Москвой. Папка может предет в апреле. Хорошо бы приехал.356# Я немного болел. Теперь выздоровел. От класса отстал не намного. За каникулы догоню. Во дворе у нас несколько ребят уехало. Г.Л. обещала написать письмо. Посмотрим.357# Сегодня мне сообщили что И[нна].Д[митриева]. в меня втрескалась[.] Чтоб ей лопнуть! Неужели без любви нельзя обойтись. У наших ребят какое-то странное понимание о дружбе. Если увидят что стоишь и разговариваешь с какой-нибудь девочкой. Сразу дразнить: влюбился, влюбился. А для того что-бы влюбиться по моему надо подрасти. А у нас во дворе нет таких что-бы не перелюбились. В половине этого случая не исключая и меня.358# В школе то-же. Какие-то идиоты кругом. Как дикари. Ну, а я то-же не лучше. Я могу влюбиться сердцем, умом никогда.359 360# 25 марта. «И в какой стороне я не буду по какой не пройду я тропе, друга я никогда незабуду если с ним подружился в Москве…» 361# Друга хорошего нельзя позыбыть не только если с ним подружишь в Москве.362# «В какой точке Союза не буду, и где не встречу мой друг я тебя, я тебя никогда не забуду, если ты не забудешь меня».363# «Я сейчас сижу в тюрьме и не светит364# Солнце мне, Кашмари, кашмари, кашмари[»].365# Эх! Не знаю что у меня на душе, что в животе я знаю там глисты, сегодня получил анализ кала.366# Чорт меня побрал! Что это на меня нашло такое настроение влюбленного. Ну, ка пошлю вон. Быть тебе только другом но…367# Опять!?368# Последнее время я не знаю что со мной творится, но примерно догадываюсь, [запись обрывается]369 370# 5 апреля. Началась последняя четверть. А там испытания. Кончу 6-й кл[асс]. наверно в Челябинске. В апреле в Москву конечно не поедем.371# В выходной ходил стрелять в тир. Сдал на «Юный ворошиловский стрелок» .372# Книга — лучший друг мой. Но такие книги что я читаю не могут заменить друга — человека. Друг. Как это слово звучит для меня непривычно. О нем я могу лишь мечтать. Дружба. Я так нуждаюсь в тебе.373 374# 26/VIII-38 г. Весь день приготовления. Завтра едем совсем в Гдов. Вообще весь день шаталась из угла в угол, но ничего хорошего не сделала. Кой-чего выстирала. Читала. Много брусники ела. Вечером были в бане с Валей Павловой в нашей. Идем в баню, а на реке Беляев, Ванька дядин Мишкин, потом пришел Петька. Долго с ними ругались, но они ушли и мы вымылись. К школе не пошла. Весь вечер читала. Слышу, пошли от школы. Беляев остановился над окном и кричит — Марготя!375# Я нисколько не изменила своего положения, только чуть улыбнулась. Он больше ничего не сказал. Я после читала очень долго. Вообще, я сказала, что сегодня спать не буду. Немного пописала дневник, но спать все же захотелось. Легла, а Ляля сидит. Велела ей разбудить как будет ложиться.376 377# 27/VIII-38 г. Через час как раз она пошла спать. Я встала. Опять читала. Валя начала плакать. С ней долго возилась. Начинает светлеть. Уже три. Еще в первом часу у меня были Валя Павлова с Тоней Ефремовой — она сегодня ночует у Вали и с нами вместе едет. Сговорились в четыре ехать. Разбудила маму. Быстро собрались, поехали. Павловы проспали, даже и тетя Настя. Ну поехали. До свиданье Заовражье! Сегодня все наши едут в Ленинград. За Рудном я захотела спать и легла, но спала не много, а только лежала. В Вейне остановились, по кушали немного. Конфет 300 гр. взяла. Поехали дальше. Всю дорогу хохотали. Ну Ефремова — это черт! Так и смешит. На поезд опоздали. За железной дорогой, не доезжая еще деревни Добручи, опять кормили лошадь и сами обедали. Я очень замаялась и спать хочу, но надо размаяться. За Добручи заехали, стало веселее. Дорога прямая. Только и отсчитываем верстовые столбы.378 379# 17 сентября (четверг), 1970 год380 381# 18 сентября (пятница), 1970 год382 383# Юрка, Юрка, ты не сдерживаешь свое слово384 385# 1-12.1. Рло386 387# 1/I - 2/II лоиывал388# '''389 390# for match in parser.findall(text):391# record = match.fact.normalized392# # print(record.spans)393# start = record.get_start_date394# stop = record.get_stop_date395# if start != stop:396# print(f'{start} - {stop}')397# else:398# print(start)