首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从python中的段落中提取句子的正则表达式

从python中的段落中提取句子的正则表达式
EN

Stack Overflow用户
提问于 2011-12-11 15:59:57
回答 3查看 8.9K关注 0票数 3

我试图使用python中的正则表达式从段落中提取一个句子。

通常,我测试的代码正确地提取了句子,但是在下面的段落中,句子没有被正确地提取。

该段:

“但在疟疾感染和脓毒症的情况下,整个身体的树突状细胞都集中在提醒免疫系统,这阻止了他们发现和应对任何新的感染。一种新型疫苗?

守则:

代码语言:javascript
复制
def splitParagraphIntoSentences(paragraph):

import re

sentenceEnders = re.compile('[.!?][\s]{1,2}(?=[A-Z])')
sentenceList = sentenceEnders.split(paragraph)
return sentenceList
if __name__ == '__main__':
    f = open("bs.txt", 'r')
    text = f.read()
    mylist = []
    sentences = splitParagraphIntoSentences(text)
    for s in sentences:
        mylist.append(s.strip())
        for i in mylist:
            print i

当用上面的段落进行测试时,它给出的输出与输入段落完全一样,但是输出应该如下所示-

但是在疟疾感染和脓毒症的情况下,整个身体的树突状细胞都集中在提醒免疫系统,这阻止了他们对任何新的感染进行检测和反应。

一种新型疫苗

正则表达式有什么问题吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-12-11 16:39:07

作为一个例子,你贴出的这个段落的第一句包含在双引号"中,结尾引号紧跟在句号“感染”之后。

您的regexp [.!?]\s{1,2}正在寻找一个句点,一个或两个空格作为句子结束符,所以它不会捕获它。

它可以通过允许可选的收尾引号来适应这种情况:

代码语言:javascript
复制
sentenceEnders = re.compile(r'''[.!?]['"]?\s{1,2}(?=[A-Z])''')

但是,使用上面的regexp,您将从句子中删除末尾引号。保留它要稍微复杂一些,并且可以通过一个回顾性断言来完成:

代码语言:javascript
复制
sentenceEnders = re.compile(r'''(?<=[.!?]['"\s])\s*(?=[A-Z])''')

但是,请注意,在许多情况下,基于regexp的拆分器失败,例如:

  • Abbreviations:“在A. B. Givental博士的作品中.”和“B”(你可以调整单字母的大小写,但除非你硬编码,否则你不能检测缩写)
  • 在句子中间使用感叹号:“.瞧,瞧!M. Deshayes本人是多引号和嵌套引号的
  • ,等等,

票数 2
EN

Stack Overflow用户

发布于 2011-12-11 19:21:44

里卡多·穆里的回答是正确的,但我想我会在这个问题上讲得更清楚一些。

对于PHP有一个类似的问题:php sentence boundaries detection。我对这个问题的回答包括处理“先生”、“夫人”等例外情况。还有“小”。我已经对这个正则表达式进行了调整,使其能够与Python一起工作(这对lookbehinds设置了更多的限制)。下面是一个经过修改和测试的脚本版本,它使用这个新的regex:

代码语言:javascript
复制
def splitParagraphIntoSentences(paragraph):
    import re
    sentenceEnders = re.compile(r"""
        # Split sentences on whitespace between them.
        (?:               # Group for two positive lookbehinds.
          (?<=[.!?])      # Either an end of sentence punct,
        | (?<=[.!?]['"])  # or end of sentence punct and quote.
        )                 # End group of two positive lookbehinds.
        (?<!  Mr\.   )    # Don't end sentence on "Mr."
        (?<!  Mrs\.  )    # Don't end sentence on "Mrs."
        (?<!  Jr\.   )    # Don't end sentence on "Jr."
        (?<!  Dr\.   )    # Don't end sentence on "Dr."
        (?<!  Prof\. )    # Don't end sentence on "Prof."
        (?<!  Sr\.   )    # Don't end sentence on "Sr."
        \s+               # Split on whitespace between sentences.
        """, 
        re.IGNORECASE | re.VERBOSE)
    sentenceList = sentenceEnders.split(paragraph)
    return sentenceList

if __name__ == '__main__':
    f = open("bs.txt", 'r')
    text = f.read()
    mylist = []
    sentences = splitParagraphIntoSentences(text)
    for s in sentences:
        mylist.append(s.strip())
    for i in mylist:
        print i

您可以看到它如何处理特殊情况,并且很容易根据需要添加或删除它们。它正确地分析了你的示例段落。它还正确地分析了以下测试段落(其中包括更多的特殊情况):

这是第一句。第二句!第三句?第四句。第五句!第六句?句子“七”第八句!琼斯博士说:“史密斯太太,你有一个可爱的女儿!”

但请注意,还有其他例外可能失败,Riccardo已经正确地指出。

票数 7
EN

Stack Overflow用户

发布于 2011-12-11 16:37:39

是的,出了点问题。你只考虑分隔符后面有一两个空格,然后是大写字母,那么“新型疫苗”的结尾是什么?例如,句子不会匹配。

我对空格也不会有太大的限制,除非它是一种意图(案文可能没有很好的格式),因为。“你好,幸运儿!你今天好吗?”不会分裂的。

我也不明白你的例子,为什么只有第一句是附在“?

总之:

代码语言:javascript
复制
>>> Text="""But in the case of malaria infections, dendritic cells and stuff.
            A new type of vaccine? My uncle!
         """
>>> Sentences = re.split('[?!.][\s]*',Text)
>>> Sentences
    ['But in the case of malaria infections, dendritic cells and stuff',
     'A new type of vaccine',
     'My uncle',
     '']

您还可以过滤空句子:

代码语言:javascript
复制
>>> NonemptyS = [ s for s in Senteces if s ]
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8465335

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档