Как разделить текст на предложения в питоне
Перейти к содержимому

Как разделить текст на предложения в питоне

  • автор:

Как разделить текст на предложения на Python?

В Питоне я полный новичок, поэтому прошу помочь и не ругаться.

На входе имеется файл с текстом в котором могут быть абзацы, переносы строк, несколько пробелов, троеточие, и собственно предложения текста.

Как бы мне грамотно поделить текст на предложения и получить их в массив?

Прошу не ругаться а дать пример кода, который работает, примеры которые я нагуглил работают некорректно, оставляя в некоторых элементах массива по 2-3 предложения вместо одного.

  • Вопрос задан более трёх лет назад
  • 15817 просмотров

Оценить 4 комментария

  • Facebook
  • Вконтакте
  • Twitter

gim0

iwqn

gim0: я кинул ссылку выше — я пробую разделить на предложения текст книги

Предложения могут заканчиваться троеточием, восклицательным и вопросительным знаком а не только точкой

iwqn

Вот пример текста который тестировался:

Открылась тяжёлая дверь, и перед глазами изумлённого мальчика предстал удивительный мир.

Прямо перед ним два бурых медвежонка схватились в обнимку. Их старший братишка-нянька не спускал глаз с озорников, а медведица-мать развалилась на пригорке и дремлет.

А там, немножко дальше, два тигра — один на скале, другой внизу — оскалили зубы, — сейчас кинутся друг на друга… Мальчик, крадучись, прошёл мимо них. В страхе оглянулся. А вдруг кинутся? Нет, не кидаются, — так и остались…

Вот высоко в воздухе застыл без движения орёл. Вот взлетевшая утка замерла над гнездом; в гнезде — яйца. Мальчик быстро протянул руку за ними — и пальцы больно ударились о что-то крепкое, холодное…

Стекло. Все звери и птицы за стеклом!

Неужели они не живые? Тогда, наверно, они заколдованы, как в сказке. Узнать бы такое волшебное слово, чтобы разом всех оживить. Кто научит его этому слову?

Мальчик попал в Зоологический музей Академии наук. Здесь работал его отец — русский учёный-естествоиспытатель. В доме напротив родился в 1894 году мальчик — будущий писатель Виталий Валентинович Бианки.

С природой его познакомил отец. Он брал сына с собой на охоту и на прогулки. Называл ему каждую травку, каждую птицу и зверюшку. Научил его узнавать птиц по полёту, зверя — по следу и — самое главное — научил сына записывать свои наблюдения.

К двадцати семи годам жизни у Виталия Валентиновича Бианки накопились целые тома дневников. И опять, как в детстве, ему захотелось найти то волшебное слово, которое заставило бы ожить всех этих птиц и зверей.

Таким словом и стало художественное слово рассказчика-писателя.

Первая В. В. Бианки для детей — «Лесные домишки» — вышла в 1923 году. За двадцать пять лет своей литературной работы Бианки написал около двухсот сказок, рассказов, повестей. Юным читателям хорошо известны его сборники: «Сказки», «Лесная газета», «По следам», «Где раки зимуют», «Рассказы об охоте», «Последний выстрел» и многие другие.

На двадцати восьми языках народов нашей Родины издавались его произведения. На многие иностранные языки переведены его книги.

Прекрасно зная и горячо любя родную природу, большую часть своей жизни Бианки проводит в лесу с ружьём, биноклем, записной книжкой. И его рассказы, сказки, повести раскрывают перед юными читателями картины живой природы. В самом обыкновенном он умеет показать новое, незамеченное нами.

Бианки ведёт юного читателя по охотничьим тропам Алтая, поднимается с ним без дорог по горам Кавказа, бродит по тайге, тундре, степи…

Но больше всего Бианки любит рассказывать о тех животных и растениях, которых всякий может встретить у себя в саду, на берегу соседней речки, в лесах и полях северной и среднерусской полосы нашей Родины.

Писатель раскрывает своему юному читателю глаза на окружающий мир, отвечает на его вопросы.

Много загадок природы уже раскрыто нашими учёными. Ещё больше надо изучить, разгадать, понять.

И книги Бианки зовут юного читателя наблюдать, сравнивать, думать, быть хорошим следопытом, исследователем. Бианки не только показывает, — он учит юного читателя раскрывать тайны леса, разгадывать маленькие и большие загадки из жизни зверей и птиц.

Ведь только тот, кто хорошо знает природу, может ею управлять, обращая её богатства на пользу Родине.

Советский человек — хозяин своих лесов, полей, рек, озёр и он должен хорошо знать своё хозяйство.

Юный читатель многое узнает, прочитав рассказы и сказки Бианки. Он научится наблюдать, он станет бережливым хозяином богатств родной природы, он полюбит её.

Python разбить текст на предложения

У меня есть текстовый файл. Мне нужен список предложений.

Как это можно реализовать? В аббревиатурах используется множество тонкостей, таких как точка.

Мой старый regexp работает плохо.

9 ответов

Инструмент Natural Language Toolkit (nltk.org) имеет то, что вам нужно. Эта публикация в группе указывает, что это делает:

Эта функция может разделить весь текст Гекльберри Финна на предложения примерно за 0,1 секунды и обрабатывать многие из более болезненных краевых случаев, которые делают предложение пессимизма нетривиальным, например: «Г-н Джон Джонсон-младший родился в США, но получил его Ph. D. в Израиле, прежде чем присоединиться к Nike Inc. в качестве инженера. Он также работал на Craigslist.org в качестве бизнес-аналитика «.

Вот средний подход к дороге, который не зависит от каких-либо внешних библиотек. Я использую понимание списков для исключения совпадений между сокращениями и терминаторами, а также исключения совпадений между вариантами прерываний, например: ‘.’ vs. ‘. «

Я использовал функцию Karl find_all из этой записи: Найти все вхождения подстроки в Python

Вместо использования регулярного выражения для разделения текста на предложения, вы также можете использовать библиотеку nltk.

Для простых случаев (когда предложения заканчиваются нормально), это должно работать:

Регулярное выражение *\. + , которое соответствует периоду, окруженному 0 или более пробелами влево, и 1 или более справа (чтобы исключить что-то вроде периода в re.split, считающегося изменением предложения).

Очевидно, что это не самое надежное решение, но в большинстве случаев это будет хорошо. Единственный случай, на который это не распространяется, — это сокращения (возможно, через список предложений и проверить, что каждая строка в sentences начинается с заглавной буквы?)

Вы можете попробовать использовать Spacy вместо regex. Я использую его, и он выполняет эту работу.

Несомненно, что NLTK является наиболее подходящим для этой цели. Но начать работу с NLTK довольно болезненно (но как только вы его устанавливаете — вы просто пожинаете плоды)

Привет! Вы можете создать новый токенизатор для русского (и некоторых других языков) с помощью этой функции:

а затем вызовите его следующим образом:

Мне пришлось читать файлы субтитров и разделить их на предложения. После предварительной обработки (например, удаления информации о времени и т.д. В файлах.srt) переменная fullFile содержала полный текст файла субтитров. Следующий грубый путь аккуратно разделил их на предложения. Вероятно, мне повезло, что предложения всегда заканчивались (правильно) пробелом. Попробуйте это первым, и если у него есть какие-то исключения, добавьте больше сдержек и противовесов.

Ой! Что ж. Теперь я понимаю, что, поскольку мой контент был испанский, у меня не было проблем с «мистером Смитом» и т.д. Тем не менее, если кто-то хочет быстрый и грязный парсер.

Razdel — сегментация русскоязычного текста на токены и предложения

Python-библиотека Razdel — часть проекта Natasha, делит русскоязычный текст на токены и предложения.

Скорость и качество сопоставимы или выше, чем у других открытых решений.

Ошибки на 1000 токенов Время обработки, секунды
Regexp-baseline 19 0.5
SpaCy 17 5.4
NLTK 130 3.1
MyStem 19 4.5
Moses 11 1.9
SegTok 12 2.1
SpaCy Russian Tokenizer 8 46.4
RuTokenizer 15 1.0
Razdel 7 2.6
Ошибки на 1000 предложений Время обработки, секунды
Regexp-baseline 76 0.7
SegTok 381 10.8
Moses 166 7.0
NLTK 57 7.1
DeepPavlov 41 8.5
Razdel 43 4.8

В чём сложность?

В русском языке предложения обычно заканчиваются точкой, вопросительным или восклицательным знаком. Просто разделим текст регулярным выражением [. ]\s+ . Такое решение даст 76 ошибок на 1000 предложений.

… любая площадка с аудиторией от 3 тыс.| |человек является блогером.

… над ними с конца XVII в.| |стоял бей;

… в Камерном музыкальном театре им.| |Б.А. Покровского.

В след за операми «Идоменей» В.А.| |Моцарта – Р.| |Штрауса …

2.| |думал будет в финское консульство красивая длинная очередь …

г.| |билеты на поезда российских железных дорог …

В конце предложения многоточие, смайлик.

Кто предложит способ избавления от минусов — тому спасибо :)| |Посмотрел, призадумался…| |Вот это уже более неприятно, поскольку содержательность нарушится.

Цитаты, прямая речь, в конце предложения кавычка.

— невесты у вас в городе есть?»| |«Кому и кобыла невеста».

«Как хорошо, что я не такой!»| |Сейчас при переводе сделал фрейдстскую ошибку:»идология».

Razdel учитывает эти нюансы, сокращает число ошибок до 43 на 1000 предложений.

С токенами аналогичная ситуация. Хорошее базовое решение даёт регулярное выражение [а-яё-]+|[0-9]+|[^а-яё0-9 ] , оно делает 19 ошибок на 1000 токенов.

… В конце 1980|-х — начале 1990|-х … БС-|3 можно отметить слегка меньшую массу (3|,|6 т) — да и умерла.|.|. Понял ли девку, сокол?|!

Razdel сокращает число ошибок до 7 на 1000 токенов.

Принцип работы

Система построена на правилах. Принцип сегментации на токены и предложения одинаковый.

Сбор кандидатов

Находим в тексте всех кандидатов на конец предложения: точки, многоточия, скобки, кавычки.

6.| |Наиболее частый и при этом высоко оцененный вариант ответов «я рада»| |(13 высказываний, 25 баллов)| |– ситуации получения одобрения и поощрения.| |7.| |Примечательно, что в ответе «я знаю»| |оценен как максимально стереотипный, но лишь раз встречается ответ «я женщина»|;| |присутствуют высказывания «один брак – это всё, что меня ждет в этой жизни»| |и «рано или поздно придется рожать»|.| |Составители: В.| |П.| |Головин, Ф.| |В.| |Заничев, А.| |Л.| |Расторгуев, Р.| |В.| |Савко, И.| |И.| |Тучков.

Для токенов дробим текст на атомы. Внутри атома точно не проходит граница токена.

В| |конце| |1980|-|х| |-| |начале| |1990|-|х| БС|-|3| |можно| |отметить| |слегка| |меньшую| |массу| |(|3|,|6| |т|)| |—| |да| |и| |умерла|.|.|.| |Понял| |ли| |девку|,| |сокол|?|!

Объединение

Последовательно обходим кандидатов на разделение, убираем лишние. Используем список эвристик.

Элемент списка. Разделитель — точка или скобка, слева число или буква.

6.| |Наиболее частый и при этом высоко оцененный вариант ответов «я рада» (13 высказываний, 25 баллов) – ситуации получения одобрения и поощрения. 7.| |Примечательно, что в ответе «я знаю» …

Инициалы. Разделитель — точка, слева одна заглавная буква.

… Составители: В.| |П.| |Головин, Ф.| |В.| |Заничев, А.| |Л.| |Расторгуев, Р.| |В.| |Савко, И.| |И.| |Тучков.

Справа от разделителя нет пробела.

… но лишь раз встречается ответ «я женщина»|; присутствуют высказывания «один брак – это всё, что меня ждет в этой жизни» и «рано или поздно придется рожать»|.

Перед закрывающей кавычкой или скобкой нет знака конца предложения, это не цитата и не прямая речь.

6. Наиболее частый и при этом высоко оцененный вариант ответов «я рада»| |(13 высказываний, 25 баллов)| |– ситуации получения одобрения и поощрения. … «один брак – это всё, что меня ждет в этой жизни»| |и «рано или поздно придется рожать».

В результате остаётся два разделителя, считаем их концами предложений.

6. Наиболее частый и при этом высоко оцененный вариант ответов «я рада» (13 высказываний, 25 баллов) – ситуации получения одобрения и поощрения.| |7. Примечательно, что в ответе «я знаю» оценен как максимально стереотипный, но лишь раз встречается ответ «я женщина»; присутствуют высказывания «один брак – это всё, что меня ждет в этой жизни» и «рано или поздно придется рожать».| |Составители: В. П. Головин, Ф. В. Заничев, А. Л. Расторгуев, Р. В. Савко, И. И. Тучков.

Для токенов процедура аналогичная, правила другие.

Дробь или рациональное число.

— да и умерла.|.|. Понял ли девку, сокол?|!

Вокруг дефиса нет пробелов, это не начало прямой речи.

В конце 1980|-|х — начале 1990|-|х БС|-|3 можно отметить …

Всё что осталось считаем границами токенов.

В| |конце| |1980-х| |-| |начале| |1990-х| БС-3| |можно| |отметить| |слегка| |меньшую| |массу| |(|3,6| |т|)| |—| |да| |и| |умерла|. | |Понял| |ли| |девку|,| |сокол|?!

Ограничения

Правила в Razdel оптимизированы для аккуратно написанных текстов с правильной пунктуацией. Решение хорошо работает с новостными статьями, художественными текстами. На постах из социальных сетей, расшифровках телефонных разговоров качество ниже.

Если между предложениями нет пробела или в конце нет точки или предложение начинается с маленькой буквы, Razdel сделает ошибку.

Использование

natural_language_processing — чат пользователей, разработчиков проекта.

Александр Кукушкин

  • alex@alexkuk.ru
  • alexkuk
  • kuk

Лаборатория разрабатывает сервисы и коробочные продукты с использованием технологии Natasha, оказывает услуги анализа данных для российских компаний.

How can I split a text into sentences?

I have a text file. I need to get a list of sentences.

How can this be implemented? There are a lot of subtleties, such as a dot being used in abbreviations.

My old regular expression works badly:

Peter Mortensen's user avatar

20 Answers 20

The Natural Language Toolkit (nltk.org) has what you need. This group posting indicates this does it:

(I haven’t tried it!)

This function can split the entire text of Huckleberry Finn into sentences in about 0.1 seconds and handles many of the more painful edge cases that make sentence parsing non-trivial e.g. "Mr. John Johnson Jr. was born in the U.S.A but earned his Ph.D. in Israel before joining Nike Inc. as an engineer. He also worked at craigslist.org as a business analyst."

Instead of using regex for spliting the text into sentences, you can also use nltk library.

You can try using Spacy instead of regex. I use it and it does the job.

Here is a middle of the road approach that doesn’t rely on any external libraries. I use list comprehension to exclude overlaps between abbreviations and terminators as well as to exclude overlaps between variations on terminations, for example: ‘.’ vs. ‘.»‘

I used Karl’s find_all function from this entry: Find all occurrences of a substring in Python

TennisVisuals's user avatar

You can also use sentence tokenization function in NLTK:

For simple cases (where sentences are terminated normally), this should work:

The regex is *\. + , which matches a period surrounded by 0 or more spaces to the left and 1 or more to the right (to prevent something like the period in re.split being counted as a change in sentence).

Obviously, not the most robust solution, but it’ll do fine in most cases. The only case this won’t cover is abbreviations (perhaps run through the list of sentences and check that each string in sentences starts with a capital letter?)

mic's user avatar

I love spaCy to death, but I recently discovered two new approaches for sentence tokenization. One is BlingFire from Microsoft (incredibly fast), and the other is PySBD (supremely accurate).

I separated 20k sentences using five different methods. Here are the elapsed times:

  • spaCy Sentencizer: 1.16934s
  • spaCy Parse: 25.97063s
  • PySBD: 9.03505s
  • NLTK: 0.30512s
  • BlingFire: 0.07933s

mph's user avatar

If NLTK’s sent_tokenize is not a thing (e.g. needs a lot of GPU RAM on long text) and regex doesn’t work properly across languages, sentence splitter might be try worth.

TefoD's user avatar

Might as well throw this in, since this is the first post that showed up for sentence split by n sentences.

This works with a variable split length, which indicates the sentences that get joined together in the end.

Using Stanza a natural language processing library that works for many human languages.

Ram Six's user avatar

No doubt that NLTK is the most suitable for the purpose. But getting started with NLTK is quite painful (But once you install it — you just reap the rewards)

i hope this will help you on latin,chinese,arabic text

Was working on similar task and came across this query, by following few links and working on few exercises for nltk the below code worked for me like magic.

Mazeen Muhammed's user avatar

Also, be wary of additional top level domains that aren’t included in some of the answers above.

For example .info, .biz, .ru, .online will throw some sentence parsers but aren’t included above.

That could be addressed by editing the code above to read:

cogijl's user avatar

You could make a new tokenizer for Russian (and some other languages) using this function:

and then call it in this way:

bad_coder's user avatar

I had to read subtitles files and split them into sentences. After pre-processing (like removing time information etc in the .srt files), the variable fullFile contained the full text of the subtitle file. The below crude way neatly split them into sentences. Probably I was lucky that the sentences always ended (correctly) with a space. Try this first and if it has any exceptions, add more checks and balances.

Oh! well. I now realize that since my content was Spanish, I did not have the issues of dealing with «Mr. Smith» etc. Still, if someone wants a quick and dirty parser.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *