【问题标题】:How to get the first N sentences from text?如何从文本中获取前 N 个句子?
【发布时间】:2013-06-15 13:56:40
【问题描述】:

我需要从文本中获取前 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])

但它会从结果中删除分隔符。我对正则表达式或基本字符串操作持开放态度。

【问题讨论】:

  • 你会如何处理:例如,现在是凌晨 5 点。早上在这里和我的 C.D.不是很好,等等等等;你还好吗。这个??
  • @Ben 是的,有“特殊情况”,结果是可以接受的。它不一定是完美的。

标签: python regex string


【解决方案1】:
>>> 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 想要的)。
  • @bsdnoobz 第一个拆分在标点符号前面的空格上,它实际上只是对您的代码的修复。第二个简单地使用非捕获组 (?:...) 找到一个模式,该组由 1 个或多个非标点字母组成,后跟一个标点符号。该组重复4 次
  • 很好,但是当文本少于 4 个句子时会抛出异常
  • @igo 谢谢我现在已经删除了第二个会引发异常的解决方案。保留在那里的第一个解决方案不会引发任何异常
【解决方案2】:

所以,我知道这个问题是关于使用正则表达式来查找句子的,但是,出于同样的原因,正则表达式不是解析 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 了解更多信息。

【讨论】:

  • +1 用于使用nltk - 它并不完美,但它在检测句子结尾方面做得非常好。
【解决方案3】:

可以将re.finditer 与itertools.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 它可能会更慢 - 不能说我已经计时了。我只是认为如果没有捕获组和连接以及其他零碎的东西,它可以说更具可读性......(此外 - 你已经接受了那个答案:))
【解决方案4】:
import re
sentenceEnd = re.compile('[.!?][\s]{1,2}(?=[A-Z])')
sentenceLists = sentenceEnd.split(text, re.UNICODE)

可以使用上面的方法,它会查找一个句号,并确保其后的下一个字符是大写字母,并且句号和下一个字母之间有空格,这将采取处理 A.M. 等案件.文本基本上是您的原始文本所在的位置,它会确保它是未编码的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-21
    • 2016-04-25
    相关资源
    最近更新 更多