Python-用于将文本拆分为句子的正则表达式(句子标记化)

2024-04-25 22:56:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我想把一个字符串中的句子列出来,然后打印出来。我不想用NLTK来做这个。因此,它需要在句子末尾的句号上进行拆分,而不是在小数、缩写或名称的标题上,或者如果句子有一个.com,这是在regex上的尝试,但不起作用。

import re

text = """\
Mr. Smith bought cheapsite.com for 1.5 million dollars, i.e. he paid a lot for it. Did he mind? Adam Jones Jr. thinks he didn't. In any case, this isn't true... Well, with a probability of .9 it isn't.
"""
sentences = re.split(r' *[\.\?!][\'"\)\]]* *', text)

for stuff in sentences:
        print(stuff)    

它应该是什么样子的示例输出

Mr. Smith bought cheapsite.com for 1.5 million dollars, i.e. he paid a lot for it. 
Did he mind?
Adam Jones Jr. thinks he didn't.
In any case, this isn't true...
Well, with a probability of .9 it isn't.

Tags: textrecomforit句子hesmith
3条回答

好的,所以我用regex、nltk、CoreNLP详细介绍了句子标记器。你最终会自己写,这取决于你的申请。这些东西是棘手和有价值的,人们不只是把他们的标记器代码泄露出去。(归根结底,标记化不是一个确定性的过程,它是概率的,而且在很大程度上取决于你的语料库或领域,例如,社交媒体帖子vs Yelp评论vs…)

一般来说,不能只依赖一个伟大的白色无误正则表达式,必须编写一个使用多个正则表达式(正反两种)的函数;还要编写一个缩写字典,以及一些基本的语言解析,这些函数知道英语中的“I”、“USA”、“FCC”、“TARP”是大写的。

为了说明这很容易变得非常复杂,让我们试着编写一个确定性标记赋予器的函数规范来决定是单句点还是多句点('.'/'…')表示句子结束,还是其他:

function isEndOfSentence(leftContext, rightContext)

  1. 对于数字或货币中的小数,例如1.23,$1.23,“这只是我的$0.02”返回False,还要考虑1.2.3节引用,2014年7月9日的欧洲日期格式,192.168.1.1的IP地址,MAC地址。。。
  2. 对于已知的缩写词,返回False(不要标记成单个字母),例如“美国股市正在下跌”;这需要一个已知缩写词的字典。除非你添加代码来检测诸如A.B.C.之类的未知缩写并将其添加到列表中,否则任何超出词典范围的内容都会出错。
  3. 句子末尾的省略号“…”是终止符,但句子中间的省略号不是。这并不像你想象的那么简单:你需要看一下左上下文和右上下文,特别是右上下文是大写的,再考虑一下大写的单词,比如“I”和缩写。这里有一个例子证明了她的模棱两可:她让我留下来。。。一小时后我离开了。(这是一句话还是两句话?无法确定)
  4. 您可能还需要编写一些模式来检测和拒绝标点符号的各种非句子结尾用法:表情符号:-)、ASCII艺术、空格省略号。还有其他东西,特别是推特。(使这种适应变得更加困难)。我们如何判断@midnight是Twitter用户、show on Comedy Central、文本速记,还是不需要的/垃圾/打字标点?非常重要。
  5. 在你处理完所有这些否定的情况后,你可以任意地说任何一个单独的句号后面跟空白都可能是句子的结尾。(最终,如果你真的想购买额外的准确性,你最终会编写自己的使用权重的概率句子标记器,并在特定的语料库(例如,法律文本、广播媒体、StackOverflow、Twitter、论坛评论等)上对其进行训练),然后你必须手动查看示例和训练错误。参见曼宁和朱拉夫斯基的书或Coursera课程[a]。 最终你得到的正确性和你准备付出的一样多。
  6. 以上所有内容都明确针对英语/缩写、美国号码/时间/日期格式。如果你想让它独立于国家和语言,这是一个更大的提议,你需要语料库,说母语的人来标记和质量保证,等等
  7. 以上所有内容仍然只是ASCII。允许输入为Unicode,事情会变得更加困难(而且训练集必须大得多或稀疏得多)

在简单的(确定性的)情况下,function isEndOfSentence(leftContext, rightContext)将返回布尔值,但在更一般的意义上,它是概率的:它返回一个浮点0.0-1.0(特定的“.”是一个句子结尾的置信水平)。

参考文献:[a]Coursera视频:“基本文本处理2-5-句子分段-斯坦福NLP-丹·朱拉夫斯基教授和克里斯·曼宁”[UPDATE: an unofficial version used to be on YouTube, was taken down]

(?<!\w\.\w.)(?<![A-Z][a-z]\.)(?<=\.|\?)\s

试试这个。把你的线分开。你也可以检查演示。

http://regex101.com/r/nG1gU7/27

尝试根据空格而不是点或?拆分输入,如果这样做,则最终结果中将不会打印点或?

>>> import re
>>> s = """Mr. Smith bought cheapsite.com for 1.5 million dollars, i.e. he paid a lot for it. Did he mind? Adam Jones Jr. thinks he didn't. In any case, this isn't true... Well, with a probability of .9 it isn't."""
>>> m = re.split(r'(?<=[^A-Z].[.?]) +(?=[A-Z])', s)
>>> for i in m:
...     print i
... 
Mr. Smith bought cheapsite.com for 1.5 million dollars, i.e. he paid a lot for it.
Did he mind?
Adam Jones Jr. thinks he didn't.
In any case, this isn't true...
Well, with a probability of .9 it isn't.

相关问题 更多 >