multiple - Python divide el texto en oraciones
split python 3 (9)
Tengo un archivo de texto. Necesito una lista de oraciones.
¿Cómo se puede implementar esto? Hay muchas sutilezas, como el punto que se usa en las abreviaturas.
Mi vieja expresión regular funciona mal.
re.compile(''(/. |^|!|/?)([A-Z][^;↑/.<>@/^&//[/]]*(/.|!|/?) )'',re.M)
@Artyom,
¡Hola! Puede hacer un nuevo tokenizador para ruso (y algunos otros idiomas) usando esta función:
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
y luego llámalo de esta manera:
text = ''вы выполняете поиск, используя Google SSL;''
tokens = russianTokenizer(text)
Buena suerte, Marilena.
En lugar de usar regex para dividir el texto en oraciones, también puede usar la biblioteca 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.'']
ref: https://.com/a/9474645/2877052
Esta función puede dividir el texto completo de Huckleberry Finn en oraciones en aproximadamente 0.1 segundos y maneja muchos de los casos más dolorosos que hacen que el análisis sintáctico no sea trivial, por ejemplo, "El señor John Johnson Jr. nació en los Estados Unidos pero obtuvo su Ph. D. en Israel antes de unirse a Nike Inc. como ingeniero. También trabajó en craigslist.org como analista de negocios " .
# -*- coding: utf-8 -*-
import re
caps = "([A-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" + caps + "[.] "," //1<prd> ",text)
text = re.sub(acronyms+" "+starters,"//1<stop> //2",text)
text = re.sub(caps + "[.]" + caps + "[.]" + caps + "[.]","//1<prd>//2<prd>//3<prd>",text)
text = re.sub(caps + "[.]" + caps + "[.]","//1<prd>//2<prd>",text)
text = re.sub(" "+suffixes+"[.] "+starters," //1<stop> //2",text)
text = re.sub(" "+suffixes+"[.]"," //1<prd>",text)
text = re.sub(" " + caps + "[.]"," //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
Este es un enfoque intermedio que no depende de ninguna biblioteca externa. Uso la comprensión de listas para excluir superposiciones entre abreviaturas y terminadores, así como para excluir superposiciones entre variaciones en las terminaciones, por ejemplo: ''.'' 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)
Utilicé la función find_all de Karl desde esta entrada: encuentre todas las apariciones de una subcadena en Python
Para casos simples (donde las oraciones se terminan normalmente), esto debería funcionar:
import re
text = ''''.join(open(''somefile.txt'').readlines())
sentences = re.split(r'' *[/./?!][/'"/)/]]* *'', text)
La expresión regular es */. +
*/. +
, que coincide con un período rodeado por 0 o más espacios a la izquierda y 1 o más a la derecha (para evitar que algo como el período en re.split se cuente como un cambio en la oración).
Obviamente, no es la solución más robusta, pero funcionará bien en la mayoría de los casos. El único caso que esto no cubrirá son las abreviaturas (tal vez se ejecute a través de la lista de oraciones y verifique que cada cadena en las sentences
comience con una letra mayúscula).
Puede intentar usar Spacy lugar de regex. Lo uso y hace el trabajo.
import spacy
nlp = spacy.load(''en'')
text = ''''''Your text here''''''
tokens = nlp(text)
for sent in tokens.sents:
print(sent.string.strip())
Sin duda, NLTK es el más adecuado para este propósito. Pero comenzar con NLTK es bastante doloroso (pero una vez que lo instales, solo cosechas las recompensas)
Así que aquí está el código simple basado en re disponible en 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
The Natural Language Toolkit ( nltk.org ) tiene lo que necesita. Esta publicación de grupo indica que esto lo hace:
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))
(¡No lo he probado!)
Tuve que leer archivos de subtítulos y dividirlos en oraciones. Después del preprocesamiento (como la eliminación de información de tiempo, etc. en los archivos .srt), la variable fullFile contenía el texto completo del archivo de subtítulos. La manera cruda a continuación los dividió en oraciones. Probablemente tuve suerte de que las oraciones siempre terminaran (correctamente) con un espacio. Pruebe esto primero y, si tiene alguna excepción, agregue más controles y equilibrios.
# 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! bien. Ahora me doy cuenta de que, dado que mi contenido era español, no tenía problemas para tratar con "el Sr. Smith", etc. Aún así, si alguien quiere un analizador rápido y sucio ...