텍스트 파일이 있습니다. 문장 목록이 필요합니다.
어떻게 구현할 수 있습니까? 약어에 점이 사용되는 등 미묘한 부분이 많이 있습니다.
내 이전 정규식이 잘못 작동합니다.
re.compile('(\. |^|!|\?)([A-Z][^;↑\.<>@\^&/\[\]]*(\.|!|\?) )',re.M)
텍스트 파일이 있습니다. 문장 목록이 필요합니다.
어떻게 구현할 수 있습니까? 약어에 점이 사용되는 등 미묘한 부분이 많이 있습니다.
내 이전 정규식이 잘못 작동합니다.
re.compile('(\. |^|!|\?)([A-Z][^;↑\.<>@\^&/\[\]]*(\.|!|\?) )',re.M)
답변:
Natural Language Toolkit ( nltk.org )에는 필요한 것이 있습니다. 이 그룹 게시물 은 다음을 수행함을 나타냅니다.
import nltk.data
tokenizer = nltk.data.load('tokenizers/punkt/english.pickle')
fp = open("test.txt")
data = fp.read()
print '\n-----\n'.join(tokenizer.tokenize(data))
(나는 그것을 시도하지 않았습니다!)
nltk .tokenize.punkt.PunktSentenceTokenizer
.
nltk.download()
먼저 다운로드 모델을 ->punkt
'This fails on cases with ending quotation marks. If we have a sentence that ends like "this." This is another sentence.'
내 출력은 ['This fails on cases with ending quotation marks.', 'If we have a sentence that ends like "this."', 'This is another sentence.']
나에게 맞는 것 같습니다.
이 기능은 약 0.1 초 만에 Huckleberry Finn의 전체 텍스트를 문장으로 분할 할 수 있으며 " Mr. John Johnson Jr.는 미국에서 태어 났지만 박사 학위를 취득했습니다. D.는 엔지니어로 Nike Inc.에 합류하기 전에 이스라엘에서 근무했으며 craigslist.org에서 비즈니스 분석가로 일했습니다. "
# -*- coding: utf-8 -*-
import re
alphabets= "([A-Za-z])"
prefixes = "(Mr|St|Mrs|Ms|Dr)[.]"
suffixes = "(Inc|Ltd|Jr|Sr|Co)"
starters = "(Mr|Mrs|Ms|Dr|He\s|She\s|It\s|They\s|Their\s|Our\s|We\s|But\s|However\s|That\s|This\s|Wherever)"
acronyms = "([A-Z][.][A-Z][.](?:[A-Z][.])?)"
websites = "[.](com|net|org|io|gov)"
def split_into_sentences(text):
text = " " + text + " "
text = text.replace("\n"," ")
text = re.sub(prefixes,"\\1<prd>",text)
text = re.sub(websites,"<prd>\\1",text)
if "Ph.D" in text: text = text.replace("Ph.D.","Ph<prd>D<prd>")
text = re.sub("\s" + alphabets + "[.] "," \\1<prd> ",text)
text = re.sub(acronyms+" "+starters,"\\1<stop> \\2",text)
text = re.sub(alphabets + "[.]" + alphabets + "[.]" + alphabets + "[.]","\\1<prd>\\2<prd>\\3<prd>",text)
text = re.sub(alphabets + "[.]" + alphabets + "[.]","\\1<prd>\\2<prd>",text)
text = re.sub(" "+suffixes+"[.] "+starters," \\1<stop> \\2",text)
text = re.sub(" "+suffixes+"[.]"," \\1<prd>",text)
text = re.sub(" " + alphabets + "[.]"," \\1<prd>",text)
if "”" in text: text = text.replace(".”","”.")
if "\"" in text: text = text.replace(".\"","\".")
if "!" in text: text = text.replace("!\"","\"!")
if "?" in text: text = text.replace("?\"","\"?")
text = text.replace(".",".<stop>")
text = text.replace("?","?<stop>")
text = text.replace("!","!<stop>")
text = text.replace("<prd>",".")
sentences = text.split("<stop>")
sentences = sentences[:-1]
sentences = [s.strip() for s in sentences]
return sentences
prefixes = "(Mr|St|Mrs|Ms|Dr|Prof|Capt|Cpt|Lt|Mt)[.]"
, websites = "[.](com|net|org|io|gov|me|edu)"
,와if "..." in text: text = text.replace("...","<prd><prd><prd>")
정규식을 사용하여 텍스트를 문장으로 분할하는 대신 nltk 라이브러리를 사용할 수도 있습니다.
>>> from nltk import tokenize
>>> p = "Good morning Dr. Adams. The patient is waiting for you in room number 3."
>>> tokenize.sent_tokenize(p)
['Good morning Dr. Adams.', 'The patient is waiting for you in room number 3.']
for sentence in tokenize.sent_tokenize(text): print(sentence)
정규식 대신 Spacy 를 사용해 볼 수 있습니다 . 나는 그것을 사용하고 그것은 일을한다.
import spacy
nlp = spacy.load('en')
text = '''Your text here'''
tokens = nlp(text)
for sent in tokens.sents:
print(sent.string.strip())
다음은 외부 라이브러리에 의존하지 않는 중간 접근 방식입니다. 목록 이해를 사용하여 약어와 종결 자 간의 겹침을 제외하고 종결에 대한 변형 간의 겹침을 제외합니다 (예 : '.'). 대 '. "'
abbreviations = {'dr.': 'doctor', 'mr.': 'mister', 'bro.': 'brother', 'bro': 'brother', 'mrs.': 'mistress', 'ms.': 'miss', 'jr.': 'junior', 'sr.': 'senior',
'i.e.': 'for example', 'e.g.': 'for example', 'vs.': 'versus'}
terminators = ['.', '!', '?']
wrappers = ['"', "'", ')', ']', '}']
def find_sentences(paragraph):
end = True
sentences = []
while end > -1:
end = find_sentence_end(paragraph)
if end > -1:
sentences.append(paragraph[end:].strip())
paragraph = paragraph[:end]
sentences.append(paragraph)
sentences.reverse()
return sentences
def find_sentence_end(paragraph):
[possible_endings, contraction_locations] = [[], []]
contractions = abbreviations.keys()
sentence_terminators = terminators + [terminator + wrapper for wrapper in wrappers for terminator in terminators]
for sentence_terminator in sentence_terminators:
t_indices = list(find_all(paragraph, sentence_terminator))
possible_endings.extend(([] if not len(t_indices) else [[i, len(sentence_terminator)] for i in t_indices]))
for contraction in contractions:
c_indices = list(find_all(paragraph, contraction))
contraction_locations.extend(([] if not len(c_indices) else [i + len(contraction) for i in c_indices]))
possible_endings = [pe for pe in possible_endings if pe[0] + pe[1] not in contraction_locations]
if len(paragraph) in [pe[0] + pe[1] for pe in possible_endings]:
max_end_start = max([pe[0] for pe in possible_endings])
possible_endings = [pe for pe in possible_endings if pe[0] != max_end_start]
possible_endings = [pe[0] + pe[1] for pe in possible_endings if sum(pe) > len(paragraph) or (sum(pe) < len(paragraph) and paragraph[sum(pe)] == ' ')]
end = (-1 if not len(possible_endings) else max(possible_endings))
return end
def find_all(a_str, sub):
start = 0
while True:
start = a_str.find(sub, start)
if start == -1:
return
yield start
start += len(sub)
이 항목에서 Karl의 find_all 함수를 사용 했습니다. Python에서 하위 문자열의 모든 항목 찾기
...
및 ?!
.
간단한 경우 (문장이 정상적으로 종료되는 경우)는 다음과 같이 작동합니다.
import re
text = ''.join(open('somefile.txt').readlines())
sentences = re.split(r' *[\.\?!][\'"\)\]]* *', text)
정규식은이며 *\. +
, 이는 왼쪽에 0 개 이상의 공백과 오른쪽에 1 개 이상의 공백으로 둘러싸인 마침표와 일치합니다 (re.split의 마침표와 같은 것이 문장의 변경으로 계산되는 것을 방지하기 위해).
분명히 가장 강력한 솔루션은 아니지만 대부분의 경우 잘 작동합니다. 여기에서 다루지 않는 유일한 경우는 약어입니다 (아마도 문장 목록을 살펴보고의 각 문자열 sentences
이 대문자 로 시작 하는지 확인 하시겠습니까?).
SyntaxError: EOL while scanning string literal
은 닫는 괄호 (뒤 text
)를 가리키는 오류를 제공합니다 . 또한 텍스트에서 참조하는 정규식이 코드 샘플에 존재하지 않습니다.
r' *[\.\?!][\'"\)\]]* +'
NLTK에서 문장 토큰 화 기능을 사용할 수도 있습니다.
from nltk.tokenize import sent_tokenize
sentence = "As the most quoted English writer Shakespeare has more than his share of famous quotes. Some Shakespare famous quotes are known for their beauty, some for their everyday truths and some for their wisdom. We often talk about Shakespeare’s quotes as things the wise Bard is saying to us but, we should remember that some of his wisest words are spoken by his biggest fools. For example, both ‘neither a borrower nor a lender be,’ and ‘to thine own self be true’ are from the foolish, garrulous and quite disreputable Polonius in Hamlet."
sent_tokenize(sentence)
@Artyom,
안녕하세요! 이 함수를 사용하여 러시아어 (및 일부 다른 언어) 용 새 토크 나이저를 만들 수 있습니다.
def russianTokenizer(text):
result = text
result = result.replace('.', ' . ')
result = result.replace(' . . . ', ' ... ')
result = result.replace(',', ' , ')
result = result.replace(':', ' : ')
result = result.replace(';', ' ; ')
result = result.replace('!', ' ! ')
result = result.replace('?', ' ? ')
result = result.replace('\"', ' \" ')
result = result.replace('\'', ' \' ')
result = result.replace('(', ' ( ')
result = result.replace(')', ' ) ')
result = result.replace(' ', ' ')
result = result.replace(' ', ' ')
result = result.replace(' ', ' ')
result = result.replace(' ', ' ')
result = result.strip()
result = result.split(' ')
return result
그런 다음 다음과 같이 호출하십시오.
text = 'вы выполняете поиск, используя Google SSL;'
tokens = russianTokenizer(text)
행운을 빕니다, Marilena.
NLTK가 목적에 가장 적합하다는 것은 의심 할 여지가 없습니다. 그러나 NLTK를 시작하는 것은 매우 고통 스럽습니다 (하지만 일단 설치하면 보상을받을 수 있습니다).
그래서 여기에 http://pythonicprose.blogspot.com/2009/09/python-split-paragraph-into-sentences.html 에서 사용할 수있는 간단한 re 기반 코드가 있습니다 .
# split up a paragraph into sentences
# using regular expressions
def splitParagraphIntoSentences(paragraph):
''' break a paragraph into sentences
and return a list '''
import re
# to split by multile characters
# regular expressions are easiest (and fastest)
sentenceEnders = re.compile('[.!?]')
sentenceList = sentenceEnders.split(paragraph)
return sentenceList
if __name__ == '__main__':
p = """This is a sentence. This is an excited sentence! And do you think this is a question?"""
sentences = splitParagraphIntoSentences(p)
for s in sentences:
print s.strip()
#output:
# This is a sentence
# This is an excited sentence
# And do you think this is a question
저는 자막 파일을 읽어서 문장으로 나누어야했습니다. 사전 처리 (.srt 파일에서 시간 정보 제거 등) 후 fullFile 변수에 자막 파일의 전체 텍스트가 포함되었습니다. 아래의 조잡한 방법은 깔끔하게 문장으로 나눕니다. 아마도 문장이 항상 공백으로 (올바르게) 끝나는 것이 운이 좋았을 것입니다. 먼저 이것을 시도하고 예외가 있으면 견제와 균형을 더 추가하십시오.
# Very approximate way to split the text into sentences - Break after ? . and !
fullFile = re.sub("(\!|\?|\.) ","\\1<BRK>",fullFile)
sentences = fullFile.split("<BRK>");
sentFile = open("./sentences.out", "w+");
for line in sentences:
sentFile.write (line);
sentFile.write ("\n");
sentFile.close;
오! 잘. 나는 지금 내 내용이 스페인어 였기 때문에 "Mr. Smith"등을 다루는 문제가 없었 음을 깨달았습니다. 그래도 누군가 빠르고 더러운 파서를 원한다면 ...
라틴어, 중국어, 아랍어 텍스트에 도움이 되길 바랍니다.
import re
punctuation = re.compile(r"([^\d+])(\.|!|\?|;|\n|。|!|?|;|…| |!|؟|؛)+")
lines = []
with open('myData.txt','r',encoding="utf-8") as myFile:
lines = punctuation.sub(r"\1\2<pad>", myFile.read())
lines = [line.strip() for line in lines.split("<pad>") if line.strip()]
유사한 작업을 수행하고 있었고 몇 개의 링크를 따르고 nltk에 대한 몇 가지 연습을 수행 함으로써이 쿼리를 발견했습니다. 아래 코드는 마술처럼 저에게 효과적이었습니다.
from nltk.tokenize import sent_tokenize
text = "Hello everyone. Welcome to GeeksforGeeks. You are studying NLP article"
sent_tokenize(text)
산출:
['Hello everyone.',
'Welcome to GeeksforGeeks.',
'You are studying NLP article']
출처 : https://www.geeksforgeeks.org/nlp-how-tokenizing-text-sentence-words-works/