-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtokenizer.py
126 lines (112 loc) · 4.96 KB
/
tokenizer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
""" Токенизатор текста """
from typing import List
PARAGRAPH_SEPARATOR = '\n'
def tokenize_sentences(text: str) -> List[str]:
"""
Конвертация текста в предложения
:public
:remark Делим нестандартно (без промежуточных абзацев),
т.к. нужно сохранить знаки пунктуации и некоторые специальные выражения
:see MarkupProtector
"""
marked_text = __markup_sentences(text)
sentences = __tokenize_by_marks(marked_text)
filtered_sentences = list(filter(lambda s: s != '', sentences))
return filtered_sentences
def __markup_sentences(text: str) -> str:
"""
Разметка предложений внутри текста
:private
:remark Нужна для сохранения знаков пунктуации
:see MarkupProtector
"""
# FIXME: fixtures: redux-toolkit, covid2019
# FIXME: invalid paragraphs? (lit-fixture)
# FIXME: index.js
text = text.strip()
# protect special patterns
text = MarkupProtector.protect(text)
# markup logic
SPLIT_CHARS = [".", "!", "?"]
for pattern in SPLIT_CHARS:
# помечаем подходящие случае разделителем абзацев
text = text \
.replace(pattern + " ", pattern + PARAGRAPH_SEPARATOR) \
.replace(pattern + "", pattern + PARAGRAPH_SEPARATOR)
# reset special patterns
text = MarkupProtector.unprotect(text)
return text
def __tokenize_by_marks(text: str) -> List[str]:
"""
Разделение текста по отметкам
:private
"""
sentences = text.split(PARAGRAPH_SEPARATOR)
return sentences
# FIXME: Вынести в отдельный файл, когда будут дособраны модуля
class MarkupProtector:
"""
Служебный класс для "защиты" от разметки особенных выражений в текстах
:todo ProtectDiary?
"""
PROTECTED_PATTERNS = {
'@@PROTECTED__THREE_DOTS@@': "...",
'@@PROTECTED__THAT_IS@@': "i.e.",
'@@PROTECTED__ET_CETERA@@': "etc.",
'@@PROTECTED__EXCLAMATION_BRACKET_ROUND@@': "!)",
'@@PROTECTED__EXCLAMATION_BRACKET_SQUARE@@': "!]",
'@@PROTECTED__QUESTION_BRACKET_ROUND@@': "?)",
'@@PROTECTED__QUESTION_BRACKET_SQUARE@@': "?]",
'@@PROTECTED__DOT_BRACKET_ROUND@@': ".)",
'@@PROTECTED__DOT_BRACKET_SQUARE@@': ".]",
'@@PROTECTED__EXCLAMATION_SPEECH_DOUBLE@@': "!\"",
'@@PROTECTED__EXCLAMATION_SPEECH_EXTENDED@@': "!»",
'@@PROTECTED__QUESTION_SPEECH_DOUBLE@@': "?\"",
'@@PROTECTED__QUESTION_SPEECH_EXTENDED@@': "?»",
'@@PROTECTED__DOT_SPEECH_DOUBLE@@': ".\"",
'@@PROTECTED__DOT_SPEECH_EXTENDED@@': ".»",
}
PROTECTED_RULES = {
'@@PROTECTED__DATE@@': {
'test': r'\d+\.\d+\.\d+'
},
'@@PROTECTED__ABBREVIATION@@': {
'test': r'(([A-Za-z]\.){2,})',
'get': lambda result: [] if not result else [result[0][0]]
},
'@@PROTECTED__FLOAT@@': {
'test': r'\d+\.\d+'
},
}
PROTECTED_RULE_TMPL = '@@PROTECTED_RULE_CASE__'
temp = []
@staticmethod
def protect(text):
import re
cls = MarkupProtector
# пробегаемся по простым выражениям
for key, pattern in cls.PROTECTED_PATTERNS.items():
text = text.replace(pattern, key)
# пробегаемся по особым правилам
for key, rule in cls.PROTECTED_RULES.items():
test, get = rule['test'], rule.get('get', lambda x: x)
# получаем все результаты по вхождениям и используем кастомный getter, если имеется
results = get(re.findall(test, text))
if results:
# Пробегаемся по результатам, заменяя их в тексте и добавляя в временное хранилище
for term in results:
i = len(cls.temp)
cls.temp.append(term)
text = text.replace(term, "{mark}{i}@@".format(mark=cls.PROTECTED_RULE_TMPL, i=i), 1)
return text
@staticmethod
def unprotect(text):
cls = MarkupProtector
# пробегаемся по простым выражениям
for key, pattern in cls.PROTECTED_PATTERNS.items():
text = text.replace(key, pattern)
# пробегаемся по особым правилам
for i, rule_term in enumerate(cls.temp):
# возвращаем старые текстовые значения из временного хранилища
text = text.replace("{mark}{i}@@".format(mark=cls.PROTECTED_RULE_TMPL, i=i), rule_term)
return text