テキストファイルがあります。文のリストを取得する必要があります。
これはどのように実装できますか?略語にドットが使用されているなど、多くの微妙な点があります。
私の古い正規表現はうまく機能しません:
re.compile('(\. |^|!|\?)([A-Z][^;↑\.<>@\^&/\[\]]*(\.|!|\?) )',re.M)
テキストファイルがあります。文のリストを取得する必要があります。
これはどのように実装できますか?略語にドットが使用されているなど、多くの微妙な点があります。
私の古い正規表現はうまく機能しません:
re.compile('(\. |^|!|\?)([A-Z][^;↑\.<>@\^&/\[\]]*(\.|!|\?) )',re.M)
回答:
自然言語ツールキット(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秒で文に分割でき、たとえば「ジョンジョンソンジュニア氏は米国で生まれたが博士号を取得しました。 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)
幸運、マリーナ。
NLTKがこの目的に最も適していることは間違いありません。しかし、NLTKの使用を開始するのは非常に困難です(しかし、一度インストールすると、報酬を得るだけです)。
だからここにhttp://pythonicprose.blogspot.com/2009/09/python-split-paragraph-into-sentences.htmlで利用可能な簡単な再ベースのコードがあります
# 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;
ああ!上手。私のコンテンツはスペイン語だったので、「スミスさん」などの問題はなかったことがわかりました。
これがラテン語、中国語、アラビア語のテキストに役立つことを願っています
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/