Skip to main content

This is a CHINESE sentence cutting tool.

Project description

sentence-spliter

[toc]

1. 介绍

sentence-spliter 句子切分工具,将一个长的句子,切分为短句的 List 。支持自然切分,最长句切分,最短句合并。

目前支持语言:中文

2. 项目结构

 └── sentence_spliter
     ├── __init__.py
     ├── automata          
        ├── __init__.py       # 存放切句的基本单元
        ├── abc.py            # 定义状态机与图的基本单元
        ├── condition.py      # 切句条件
        ├── operation.py      # 切句操作
        ├── sequence.py    	 # 封装状态传递的数据
        ├── state_machine.py  # 状态机
        └── symbols.py        # 保存标点符号
     ├── logic_graph.py        # 逻辑图
     └── spliter.py            # 主要函数,调用切句     

3. Setup

PYPI 安装

pip install sentence-spliter

4. Demo

4.1. Simple Demo

from sentence_spliter.spliter import cut_to_sentences

# -- demo 1 -- #
paragraph = "在很久很久以前......。。... 有座山,山里有座庙啊!!!!!!!庙里竟然有个老和尚!?。。。。"
result =  spliter.cut_to_sentences(paragraph)
print(result)
['在很久很久以前......。。...', ' 有座山,山里有座庙啊!!!!!!!', '庙里竟然有个老和尚!?。。。。']

# -- demo 2 -- #
paragraph = "求月票啊!求月票啊!求月票啊!~~~  重要的事情说三遍!"
result = spliter.cut_to_sentences(paragraph)
print(result)
['求月票啊!', '求月票啊!', '求月票啊!~~~ ', ' 重要的事情说三遍!']

# -- demo 3 -- #
paragraph = "《啊!啊!啊!》是本耐人寻味的读物。"
result = spliter.cut_to_sentences(paragraph)
print(result)
['《啊!啊!啊!》是本耐人寻味的读物。']

切句支持以整片文章为输入。

如果输入太长,终端会自动显示百分比process cutting 87.5%

4.2. Demo in detail

切句工具默认有两种种逻辑

4.2.1. 自然切分

基本逻辑:

  • 遇到断句标点(。?!)准备切句:
    • 如果短句标点出现在引号括号书名号不执行切句
    • 其他情况下执行切句

自然切分可以通过调用cut_to_sentences使用 (是cut_to_sentences默认配置)

from sentence_spliter.spliter import cut_to_sentences

paragraph = "在很久很久以前......。。... 有座山,山里有座庙啊!!!!!!!庙里竟然有个老和尚!?。。。。"
result =  spliter.cut_to_sentences(paragraph) 
print(result)
['在很久很久以前......。。...', ' 有座山,山里有座庙啊!!!!!!!', '庙里竟然有个老和尚!?。。。。']

自然切分也可以通过调用logic_graphstate_machine

  • 优点,用户可以自己配置如何创建state_machine的实例
#导入逻辑
from sentence_spliter.logic_graph import simple_cuter   
#导入状态机
from sentence_spliter.automata.state_machine import StateMachine
#导入序列,str 需要封装成StrSquence 喂给状态机
from sentence_spliter.automata.sequence import StrSequence

# -- 初始化 状态机器 -- #
cuter = StateMachine(simple_cuter())

# -- 处理句子 -- #
paragraph = "“我和你讨论的不是一个东西,死亡率与死亡比例是不同的”“你知道么?CNN你们总是制造假新闻。。。”"
sequence = cuter.run(StrSequence(paragraph))
out = sequence.sentence_list()

# -- 展示结果 -- #
print(out)
['“我和你讨论的不是一个东西,死亡率与死亡比例是不同的”', '“你知道么?CNN你们总是制造假新闻。。。”']

4.2.2. 长短处理切句

基本逻辑:

  • 如果是短句:则该句子与右边句子合并
  • 如果是长句:
    • 优先基于断句标点做二次切句
    • 再基于逗号做二次切句

需要参数:

  • hard_max (默认300): 最大可接受长度,要保证所有句子(除了最后一句)<= hard_max
  • max_len (默认128): 长句判断条件,如果句子大于 max_len则为长句
    • max_len 可以等于 hard_max
  • min_len (默认15): 短句判断条件,如果句子小于min_len则为短句

同样长短句处理切分可以通过调用cut_to_sentences使用 (但是长短句参数均为默认且不可调整)

from sentence_spliter import spliter

# -- 使用长短句切句 -- #
paragraph = "求月票啊!求月票啊!求月票啊!~~~  重要的事情说三遍!"
result = spliter.cut_to_sentences(paragraph, long_short=True)
print(result)
['求月票啊!求月票啊!求月票啊!~~~ ', ' 重要的事情说三遍!']


# -- 不使用长短句切句 -- #
paragraph = "求月票啊!求月票啊!求月票啊!~~~  重要的事情说三遍!"
result = spliter.cut_to_sentences(paragraph, long_short=False)
print(result)
['求月票啊!', '求月票啊!', '求月票啊!~~~ ', ' 重要的事情说三遍!']

长短句切分也可以通过调用logic_graphstate_machine

  • 优点
    • 用户可以自己配置如何创建state_machine的实例
    • 用户可以自定义参数
from sentence_spliter.logic_graph import long_short_cuter
from automata.state_machine import StateMachine
from automata.sequence import StrSequence

# -- 初始化 状态机器 -- #
cuter = StateMachine(long_short_cuter(hard_max = 128, max_len= 128, min_len = 15))

# -- 处理句子 -- #
paragraph = "在很久很久以前1.2.3......。。... 有座山。山里有座庙啊!!!!!!!庙里竟然有个老和尚!?。。。。www.baidu.com"
sequence = cuter.run(StrSequence(paragraph))
out = sequence.sentence_list()

# -- 展示结果 -- #
print(out)
['在很久很久以前1.2.3......。。...', ' 有座山。山里有座庙啊!!!!!!!', '庙里竟然有个老和尚!?。。。。', 'www.baidu.com']
from sentence_spliter.logic_graph import long_short_cuter
from automata.state_machine import StateMachine
from automata.sequence import StrSequence

# -- 初始化 状态机器 -- #
cuter = StateMachine(long_short_cuter(hard_max = 2, max_len= 2, min_len = 1))

# -- 处理句子 -- #
paragraph = "在很久很久以前1.2.3......。。... 有座山。山里有座庙啊!!!!!!!庙里竟然有个老和尚!?。。。。www.baidu.com"
sequence = cuter.run(StrSequence(paragraph))
out = sequence.sentence_list()

# -- 展示结果 -- #
print(out)
['在很', '久很', '久以', '前1', '.2', '.3', '..', '..', '..', '。。', '..', '.', ' 有', '座山', '。', '山里', '有座', '庙啊', '!!', '!!', '!!', '!', '庙里', '竟然', '有个', '老和', '尚!', '?。', '。。', '。', 'ww', 'w.', 'ba', 'id', 'u.', 'com']

5. 自定义规则

切句规则都是基于图来实现的,其中

  • automata/condition.py 存放图的边
  • automata/operation.py 存放节点

5.1. 定义一个简单的切句规则

规则如下:

  • 如果遇到断句标点 执行切句

代码:

from automata import condition, operation
from automata.state_machine import StateMachine
from automata.sequence import StrSequence

# step 1: 初始所以需要的边和节点

edges = {
    'is_end_symbol': condition.IsEndSymbol(),
    'is_end_state': condition.IsEndState(),
}

nodes = {
    'init': operation.Indolent(),
    'do_cut': operation.Normal(),
    'end': operation.EndState()
}

# step 2: 构建图

simple_logic = {
    nodes['init']: [
        {'edge': edges['is_end_state'],
         'node': nodes['end']},

        {'edge': edges['is_end_symbol'],
         'node': nodes['do_cut']}
    ],
    nodes['do_cut']: [
        {'edge': edges['is_end_state'],
         'node': nodes['end']},

        {'edge': None,
         'node': nodes['init']}  # else 状态

    ],
}

# step 3: 初始化状态机
machine = StateMachine(simple_logic)

# step 4: 切句测试
sentences = '万壑树参天,千山响杜鹃。山中一夜雨,树杪百重泉。汉女输橦布,巴人讼芋田。文翁翻教授,不敢倚先贤。'

out = machine.run(StrSequence(sentences))

print('\n'.join(out.sentence_list()))

输出:

万壑树参天,千山响杜鹃。
山中一夜雨,树杪百重泉。
汉女输橦布,巴人讼芋田。
文翁翻教授,不敢倚先贤。

注意:

  • machine 是从 Indolent状态开始便利,遍历顺序从上倒下
  • 每个状态必须先有end_state条件否则报错

5.2. 多条边都指向一个节点

考虑以下两个规则:

规则一

  • 如果遇到切句标点同时出现在书名号外面,则切句

规则二

  • 如果遇到切句标点或者 右引号,则切句

我们可以在边中使用list方法来实现andor

from sentence_spliter.automata import condition, operation
from sentence_spliter.automata.state_machine import StateMachine
from sentence_spliter.automata.sequence import StrSequence

# step 1: 初始所以需要的边和节点

edges = {
    'is_end_symbol': condition.IsEndSymbol(),
    'is_end_state': condition.IsEndState(),
    'is_book_symbol': condition.IsBookClose(),
    'is_left_quota': condition.IsLeftQuota()
}

nodes = {
    'init': operation.Indolent(),
    'do_cut': operation.Normal(),
    'end': operation.EndState()
}

# step 2: 构建图

simple_logic = {
    nodes['init']: [
        {'edge': edges['is_end_state'],
         'node': nodes['end']},

        {'edge': [edges['is_end_symbol'],
                  edges['is_book_symbol']],
         'args': all,           # 我们使用arg 来填 or 或者 and
         'node': nodes['do_cut']}
    ],
    nodes['do_cut']: [
        {'edge': edges['is_end_state'],
         'node': nodes['end']},

        {'edge': None,
         'node': nodes['init']}  # else 状态

    ],
}

# step 3: 初始化状态机
machine = StateMachine(simple_logic)

# step 4: 切句测试
sentences = '《啊!啊!啊!》是本耐人寻味的读物。'

out = machine.run(StrSequence(sentences))

print('\n'.join(out.sentence_list()))

输出

《啊!啊!啊!》是本耐人寻味的读物。

表示or

from sentence_spliter.automata import condition, operation
from sentence_spliter.automata.state_machine import StateMachine
from sentence_spliter.automata.sequence import StrSequence

# step 1: 初始所以需要的边和节点

edges = {
    'is_end_symbol': condition.IsEndSymbol(),
    'is_end_state': condition.IsEndState(),
    'is_book_symbol': condition.IsBookClose(),
    'is_right_quota': condition.IsRightQuota()
}

nodes = {
    'init': operation.Indolent(),
    'do_cut': operation.Normal(),
    'end': operation.EndState()
}

# step 2: 构建图

simple_logic = {
    nodes['init']: [
        {'edge': edges['is_end_state'],
         'node': nodes['end']},

        {'edge': [edges['is_end_symbol'],
                  edges['is_right_quota']],
         'args': any,
         'node': nodes['do_cut']}
    ],
    nodes['do_cut']: [
        {'edge': edges['is_end_state'],
         'node': nodes['end']},

        {'edge': None,
         'node': nodes['init']}  # else 状态

    ],
}

# step 3: 初始化状态机
machine = StateMachine(simple_logic)

# step 4: 切句测试
sentences = '“时代变了~”,小明感叹道。'

out = machine.run(StrSequence(sentences))

print('\n'.join(out.sentence_list()))

输出

“时代变了~”
,小明感叹道。

5.3. 自定义节点和边

  • 节点要保证输入和输出都是 sequece.StrSequence就可以放在状态机中运行
  • 边要保证输入是 sequece.StrSequence输出是bool就可以放在状态机中运行

这里不再做演示

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sentence-spliter-1.0.4.tar.gz (15.7 kB view hashes)

Uploaded Source

Built Distribution

sentence_spliter-1.0.4-py3-none-any.whl (19.7 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page