Bir metin dosyam var. Bir cümle listesi almam gerekiyor.
Bu nasıl uygulanabilir? Kısaltmalarda kullanılan nokta gibi pek çok incelik vardır.
Eski normal ifadem kötü çalışıyor:
re.compile('(\. |^|!|\?)([A-Z][^;↑\.<>@\^&/\[\]]*(\.|!|\?) )',re.M)
Bir metin dosyam var. Bir cümle listesi almam gerekiyor.
Bu nasıl uygulanabilir? Kısaltmalarda kullanılan nokta gibi pek çok incelik vardır.
Eski normal ifadem kötü çalışıyor:
re.compile('(\. |^|!|\?)([A-Z][^;↑\.<>@\^&/\[\]]*(\.|!|\?) )',re.M)
Yanıtlar:
Natural Language Toolkit ( nltk.org ) ihtiyacınız olan şeylere sahiptir. Bu grup gönderimi bunu yaptığını gösterir:
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))
(Ben denemedim!)
nltk .tokenize.punkt.PunktSentenceTokenizer
.
nltk.download()
ve modelleri indirmeniz gerekebilir ->punkt
'This fails on cases with ending quotation marks. If we have a sentence that ends like "this." This is another sentence.'
ve benim çıkış olduğunu ['This fails on cases with ending quotation marks.', 'If we have a sentence that ends like "this."', 'This is another sentence.']
benim için doğru görünüyor.
Bu işlev, Huckleberry Finn'in tüm metnini yaklaşık 0,1 saniyede cümlelere ayırabilir ve cümle ayrıştırmayı önemsiz hale getiren daha acı verici uç vakaların çoğunu ele alır, örneğin " Bay John Johnson Jr. ABD'de doğdu, ancak doktorasını kazandı. Bir mühendis olarak Nike Inc.'e katılmadan önce İsrail'de D.. Ayrıca craigslist.org'da iş analisti olarak çalıştı. "
# -*- 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)"
, veif "..." in text: text = text.replace("...","<prd><prd><prd>")
Metni cümlelere ayırmak için normal ifade kullanmak yerine, nltk kitaplığını da kullanabilirsiniz.
>>> 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)
Normal ifade yerine Spacy kullanmayı deneyebilirsiniz . Ben kullanıyorum ve işi yapıyor.
import spacy
nlp = spacy.load('en')
text = '''Your text here'''
tokens = nlp(text)
for sent in tokens.sents:
print(sent.string.strip())
Burada herhangi bir dış kütüphaneye dayanmayan yolun ortası yaklaşımı var. Kısaltmalar ve sonlandırıcılar arasındaki çakışmaları ve sonlandırmalardaki varyasyonlar arasındaki çakışmaları hariç tutmak için liste anlamayı kullanıyorum, örneğin: '.' vs. '."'
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)
Bu girişten Karl'ın find_all işlevini kullandım: Python'da bir alt dizenin tüm oluşumlarını bulun
...
ve ?!
.
Basit durumlarda (cümlelerin normal olarak sonlandırıldığı durumlarda), bu işe yaramalıdır:
import re
text = ''.join(open('somefile.txt').readlines())
sentences = re.split(r' *[\.\?!][\'"\)\]]* *', text)
Regex olan *\. +
sol ve 1 veya daha fazla sağa 0 veya daha fazla boşluklarla çevrili bir dönemi eşleşen, (re.split dönem gibi bir şey cümlede bir değişiklik olarak sayılmasına önlemek için).
Açıkçası, en sağlam çözüm değil, ancak çoğu durumda iyi olacak. Bunun kapsamayacağı tek durum kısaltmalardır (belki cümleler listesini gözden geçirin ve her dizenin sentences
büyük harfle başlayıp başlamadığını kontrol edin ?)
SyntaxError: EOL while scanning string literal
kapanış parantezini (sonra text
) işaret ediyor . Ayrıca, metninizde referans verdiğiniz normal ifade kod örneğinizde mevcut değildir.
r' *[\.\?!][\'"\)\]]* +'
NLTK'da cümle belirtme işlevini de kullanabilirsiniz:
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,
Selam! Bu işlevi kullanarak Rusça (ve diğer bazı diller) için yeni bir belirteç oluşturabilirsiniz:
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
ve sonra şu şekilde arayın:
text = 'вы выполняете поиск, используя Google SSL;'
tokens = russianTokenizer(text)
İyi şanslar Marilena.
Hiç şüphe yok ki, NLTK amaca en uygun olanıdır. Ancak NLTK ile başlamak oldukça acı verici (Ama bir kez kurduğunuzda - sadece ödülleri alırsınız)
İşte, http://pythonicprose.blogspot.com/2009/09/python-split-paragraph-into-sentences.html adresinde bulunan basit yeniden tabanlı kod.
# 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
Altyazı dosyalarını okuyup cümlelere bölmem gerekiyordu. Ön işlemden sonra (.srt dosyalarındaki zaman bilgisinin kaldırılması vb. Gibi), fullFile değişkeni altyazı dosyasının tam metnini içeriyordu. Aşağıdaki kaba yol onları düzgünce cümlelere ayırır. Muhtemelen, cümlelerin her zaman (doğru) boşlukla bittiği için şanslıydım. Önce bunu deneyin ve herhangi bir istisnası varsa, daha fazla kontrol ve bakiye ekleyin.
# 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;
Oh! iyi. Şimdi anlıyorum ki içeriğim İspanyolca olduğu için, "Bay Smith" ile uğraşmak gibi sorunlar yaşamadım. Yine de, birisi hızlı ve kirli bir ayrıştırıcı isterse ...
umarım bu sana latin, çince, arapça metinlerde yardımcı olur
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()]
Benzer bir görev üzerinde çalışıyordu ve birkaç bağlantıyı izleyerek ve nltk için birkaç alıştırma üzerinde çalışarak bu sorguya rastladım, aşağıdaki kod benim için sihir gibi çalıştı.
from nltk.tokenize import sent_tokenize
text = "Hello everyone. Welcome to GeeksforGeeks. You are studying NLP article"
sent_tokenize(text)
çıktı:
['Hello everyone.',
'Welcome to GeeksforGeeks.',
'You are studying NLP article']
Kaynak: https://www.geeksforgeeks.org/nlp-how-tokenizing-text-sentence-words-works/