如何从文本中获取前N个句子?

4

我需要从一段文本中获取前N个句子,这些句子的结尾可以是句号、冒号或分号。例如,给定以下文本:

Lorem ipsum, dolor sit amet. consectetur adipisicing elit; sed do eiusmod tempor.
incididunt ut labore: et dolore magna aliqua. Ut enim ad. minim veniam.

第一段有4个句子:
Lorem ipsum, dolor sit amet. consectetur adipisicing elit; sed do eiusmod tempor.
incididunt ut labore:

目前,我的代码正在使用.:;作为分隔符进行字符串拆分,然后再将结果连接起来。

import re
sentences = re.split('\. |: |;', text)
summary = ' '.join(sentences[:4])

但是这将从结果中删除分隔符。我可以使用正则表达式或基本字符串操作来解决。


1
你会如何处理这种情况:例如,现在是早上5点,我的CD播放器出了些问题等等,你能应对吗? - Ben
@Ben 是的,有一些“特殊情况”,结果是可以接受的。它不必完全完美。 - flowfree
4个回答

5
>>> import re
>>> text = "Lorem ipsum, dolor sit amet. consectetur adipisicing elit; sed do eiusmod tempor. incididunt ut labore: et dolore magna aliqua. Ut enim ad. minim veniam."
>>> ' '.join(re.split(r'(?<=[.:;])\s', text)[:4])
'Lorem ipsum, dolor sit amet. consectetur adipisicing elit; sed do eiusmod tempor. incididunt ut labore:'

这两个正则表达式并不相同。第一个仅在标点符号和空格处分割,而第二个在标点符号处分割(我相信这才是 OP 想要的)。 - Bakuriu
@bsdnoobz,第一个是在标点符号前面的空格上进行分割,这实际上只是对你代码的修复。第二个则是使用非捕获组 (?:...) 查找模式,该组由一个或多个非标点符号字母后跟一个标点符号组成。该组重复了 4 次。 - jamylak
很好,但是当文本少于4个句子时,这将抛出异常。 - igo
@igo 谢谢,我现在已经删除了第二个解决方案,因为它会引发异常。仍然存在的第一个解决方案不会引发任何异常。 - jamylak

3

因此,我知道这个问题是关于使用正则表达式查找句子的,但是,由于正则表达式不适合解析html(不同类别的语法),所以对于涉及自然语言的问题来说,正则表达式甚至更不适合。

如果你的目标是真正划分句子,你必须寻找其他工具。个人建议使用nltk提供的Punkt句子分词器。以下是一个示例,说明为什么这是比正则表达式更好的选择。

Punkt knows that the periods in Mr. Smith and Johann S. Bach do not mark 
sentence boundaries.  And sometimes sentences can start with non-capitalized 
words.  i is a good variable name.

请查看http://nltk.org/api/nltk.tokenize.html了解更多关于IT技术的信息。

使用nltk检测句子结尾并不完美,但它确实能够出乎意料地完成任务。加1分推荐使用。 - Aya

1

可以将re.finditeritertools.islice和字符串切片结合使用(避免连接回来并保留分隔符):

import re
from itertools import islice

delims = re.finditer('[.:;]', s)
try:
    print s[:next(islice(delims, 3, None)).end()]
except StopIteration:
    print s # whole string instead maybe as there's not enough delimiters

@jamylak 可能会慢一些 - 我没有计时。我只是认为这样阅读起来可能更清晰,而且不需要捕获组、连接和其他琐碎的东西... (此外 - 你已经回答了那个问题 :)) - Jon Clements

0
import re
sentenceEnd = re.compile('[.!?][\s]{1,2}(?=[A-Z])')
sentenceLists = sentenceEnd.split(text, re.UNICODE)

上述方法可以使用,它会查找句号,并确保句号后面的下一个字符是大写字母,并且在句号和下一个字母之间有一个空格,这将处理类似于 A.M. 的情况。文本基本上是您的原始文本,它将确保它是 Unicode 编码的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接