- PVSM.RU - https://www.pvsm.ru -
Test The Text [1] выделяет стоп-слова в тексте. Стоп-слова делают текст тяжелее, слабее, длиннее.
Стоп-слова делятся на несколько категорий:
— модальные глаголы;
— усиляющие и обобщенные определения и наречия;
— клише и канцеляризмы;
— гиперонимы;
— паразиты времени;
— отглагольные существительные;
— пассивный залог;
— наречия;
— причастные обороты.
Прототип выделял модальные глаголы, используя список «мочь», «долженствовать» и «нуждаться» во всех формах:
'modal': {
'can': u"""могу, мог, могла, можешь, может, могло, можем, можете, могли, могут,
смог, смогла, смогли, сможет, можно, нужен""",
'need': u'нуждаться, нуждается, нужно, нужна, нужны',
'should': u'должен, должна, должны, должно',
'other': u'стоит, обязан, следует, необходимо, требуется'
},
Текст разбивался на слова регулярным выражением (?:[s,.:]|A|Z), каждое слово сравнивалось со стоп-словами. Совпадения помечались в исходном тексте <span class=«класс стоп-слова»>, размеченный текст возвращался обратно и заменял текст на странице.
Прототип работал, список стоп-слов рос, но когда я добрался до клише, понял, что дальше перечислять стоп-слова во всех формах я не смогу. Каждое стоп-слово превращалось в 63. Три рода × три времени × семь падежей. Я подключил pystemmer [2].
Стеммер убирает окончание и суффикс слова, приводя его к нормальной форме.
нуждаться → нужда
инновационное → инновацион
высокий → высок
высокая → высок
высокую → высок
Pystemmer работает по алгоритму Snowball [3].
Теперь алгоритм пробегался по стоп словам, отбрасывая у них окончания и суффиксы, затем по словам текста. Начальные формы стоп-слов и слов в тексте сравнивались. Стоп-фразы, вроде, «сомнительное удовольствие», алгоритм разбирает на слова, стеммирует и собирает обратно. При поиске стоп-фразы в списке слов текста, берется проверяемое слово и несколько слов за ним.
К сожалению, через словари стоп-слов невозможно проверить наречия, пассивный залог и причастные обороты. Представляете себе список всех наречий русского языка? Пришло время подключать морфологический анализатор. Выбора для python, кроме pymorphy2 [4] от kmike [5] нет, поэтому останавливаюсь на нем.
Морфологический анализатор определяет для слова часть речи (существительное, глагол, прилагательное, ...), пол, единственное/множественное число, падеж, лицо, время, залог для глаголов. Полный список в исходниках [6]. Захватывающая статья [7] как устроен pymoprhy2.
[Parse(word=u'доставлен', tag=OpencorporaTag('PRTS,perf,past,pssv masc,sing'), normal_form=u'доставить', score=1.0, methods_stack=((<DictionaryAnalyzer>, u'доставлен', 745, 71),))]
[Parse(word=u'пищущие', tag=OpencorporaTag('ADJF plur,nomn'), normal_form=u'пищущий', score=0.212962962962963, methods_stack=((<DictionaryAnalyzer>, u'ищущие', 162, 20), (<UnknownPrefixAnalyzer>, u'п'))),
Parse(word=u'пищущие', tag=OpencorporaTag('ADJF inan,plur,accs'), normal_form=u'пищущий', score=0.212962962962963, methods_stack=((<DictionaryAnalyzer>, u'ищущие', 162, 24), (<UnknownPrefixAnalyzer>, u'п'))),
Parse(word=u'пищущие', tag=OpencorporaTag('PRTF,impf,tran,pres,actv plur,nomn'), normal_form=u'пискать', score=0.212962962962963, methods_stack=((<DictionaryAnalyzer>, u'ищущие', 1609, 33), (<UnknownPrefixAnalyzer>, u'п'))),
Parse(word=u'пищущие', tag=OpencorporaTag('PRTF,impf,tran,pres,actv inan,plur,accs'), normal_form=u'пискать', score=0.212962962962963, methods_stack=((<DictionaryAnalyzer>, u'ищущие', 1609, 37), (<UnknownPrefixAnalyzer>, u'п'))),
Parse(word=u'пищущие', tag=OpencorporaTag('PRTF,impf,intr,pres,actv plur,nomn'), normal_form=u'питать', score=0.03703703703703704, methods_stack=((<FakeDictionary>, u'пищущие', 1670, 33), (<KnownSuffixAnalyzer>, u'щущие'))),
Parse(word=u'пищущие', tag=OpencorporaTag('PRTF,impf,intr,pres,actv inan,plur,accs'), normal_form=u'питать', score=0.03703703703703704, methods_stack=((<FakeDictionary>, u'пищущие', 1670, 37), (<KnownSuffixAnalyzer>, u'щущие'))),
Parse(word=u'пищущие', tag=OpencorporaTag('PRTF,impf,tran,pres,actv plur,nomn'), normal_form=u'пистать', score=0.03703703703703704, methods_stack=((<FakeDictionary>, u'пищущие', 2631, 33), (<KnownSuffixAnalyzer>, u'щущие'))),
Parse(word=u'пищущие', tag=OpencorporaTag('PRTF,impf,tran,pres,actv inan,plur,accs'), normal_form=u'пистать', score=0.03703703703703704, methods_stack=((<FakeDictionary>, u'пищущие', 2631, 37), (<KnownSuffixAnalyzer>, u'щущие')))]
После подключения морфологического анализатора Test The Text выделяет наречия, страдательный залог, причастный оборот и, заодно, междометия.
Осталось разобраться с проблемами на клиенте. Я и не подозревал, что с простым полем ввода текста может быть столько проблем. Пришлось написать java-script очистки текста при вставке и код вставки <br> по нажатию enter. В новой версии я заменил свой код на Wysihtml5 [8]. Wysihtml5 это легковесный html-редактор. Нашел его, изучая как сделали редактор в Basecamp.
Кроме того, пришлось перенести разметку текста на клиент. Проверка текста происходит не мгновенно, пользователь мог ввести еще пару предложений перед ответом. А так как текст размечался на сервере, то все изменения пользователя стирались.
Вместо этого сервер стал возвращать список стоп-слов с их классом, начальной и конечной позицией. А разметка уже происходила на клиенте. Если слово на позиции не совпадает с ответом от сервера, слово не помечается. На тот случай, если пользователь поменял текст и позиция слова сместилась.
Планы по развитию:
— Выделение предложений больше 17 слов, их трудно читать.
— Выделение абзацев длиннее 8 строчек. Скорее всего такие абзацы нужно разбить.
— Слежение за «ритмом [9]» текста. В хорошем тексте длинные предложения чередуются со средними и короткими, текст становится не монотонным. Читатель не засыпает.
— Повторение слов в сосендних предложениях.
— Сослагательное наклонение.
— Публичное API.
Автор: TestTheText
Источник [12]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/python/50025
Ссылки в тексте:
[1] Test The Text: http://test-the-text.ru
[2] pystemmer: https://pypi.python.org/pypi/PyStemmer/1.0.1
[3] Snowball: http://snowball.tartarus.org/texts/introduction.html
[4] pymorphy2: https://github.com/kmike/pymorphy2
[5] kmike: http://habrahabr.ru/users/kmike/
[6] исходниках: https://github.com/kmike/pymorphy2/blob/master/pymorphy2/tagset.py
[7] Захватывающая статья: http://habrahabr.ru/post/176575/
[8] Wysihtml5: http://xing.github.io/wysihtml5/
[9] ритмом: http://lib.rus.ec/b/259930/read#t13
[10] Хабра-блог: http://habrahabr.ru/company/ttt/
[11] полезные письма: http://eepurl.com/Jntoz
[12] Источник: http://habrahabr.ru/post/204898/
Нажмите здесь для печати.