apppublic/aidocs/textsplit.md
2025-10-05 11:23:33 +08:00

6.4 KiB
Raw Permalink Blame History

文本句子分割工具技术文档

本模块提供两个核心函数,用于智能地将一段包含中英文混合内容的文本按句子进行分割,同时保留对话部分不被错误切分。适用于自然语言处理、文本预处理等场景。


📌 模块功能概览

函数名 功能描述
split_english_sentences(text) 分割纯英文文本为句子列表,避免在缩写词处误切分
split_text_with_dialog_preserved(text) 分割中英文混合文本,并完整保留引号内的对话内容

1. split_english_sentences(text)

功能说明

该函数用于将英文文本正确分割为独立句子,特别处理了以下常见问题:

  • 句子结尾标点后缺少空格(如 "Hello.World""Hello. World"
  • 避免在常见缩写词(如 Dr., U.S.A.)处错误断句
  • 支持 ., !, ? 作为句子结束符

参数

参数 类型 说明
text str 待分割的英文文本字符串

返回值

List[str]: 分割后的句子列表,每个元素为一个独立句子(已去除首尾空白)

实现逻辑详解

步骤 1修复紧连句点

text = re.sub(r'([a-zA-Z])\\.([A-Z])', r'\\1. \\2', text)
  • 目的:修复形如 Hello.World 的情况,在句点后添加空格。
  • 正则解释
    • ([a-zA-Z]):匹配前一个字母
    • \\.:匹配句点 .
    • ([A-Z]):匹配后一个大写字母(新句子开头)
  • 示例:"It is cold.Today it will snow.""It is cold. Today it will snow."

步骤 2保护缩写词中的句点

abbreviations = r"(Mr|Mrs|Ms|Dr|St|Jr|Sr|vs|i\\.e|e\\.g|U\\.S\\.A|U\\.K)\\."
text = re.sub(abbreviations, lambda m: m.group(0).replace('.', '<DOT>'), text)
  • 目的:防止在 Dr.U.S.A. 等缩写处分割。
  • 使用 <DOT> 临时替换缩写中的句点,避免被当作句子结束。
  • 支持的缩写包括:
    • Mr., Mrs., Ms., Dr., St., Jr., Sr., vs.
    • i.e., e.g., U.S.A., U.K.

步骤 3正则分割句子

sentences = re.split(r'(?<=[.!?])\\s+', text.strip())
  • 利用正向后视断言 (?<=...)., !, ? 后面的空白处分割。
  • 确保只在句子结束符后的空格处分割,而非所有空格。

步骤 4还原缩写中的句点

sentences = [s.replace('<DOT>', '.') for s in sentences if s.strip()]
  • 将之前替换成 <DOT> 的句点恢复为正常句点。
  • 过滤掉空字符串或仅空白的内容。

示例调用

text = "Dr. Smith went to the U.S.A. He said, 'Hello world!' How are you?"
result = split_english_sentences(text)
print(result)
# 输出:
# ['Dr. Smith went to the U.S.A.', "He said, 'Hello world!'", 'How are you?']

2. split_text_with_dialog_preserved(text)

功能说明

此函数用于处理中英文混合文本,并确保双引号或中文引号包裹的对话内容整体保留,不会在内部被切断。

特别适用于小说、剧本、访谈记录等含大量对话的文本。

参数

参数 类型 说明
text str 包含中英文和可能对话的原始文本

返回值

List[str]: 分割后的文本片段列表,每项是一个句子或完整的对话块。

实现逻辑详解

步骤 1清理换行与回车

text = ''.join(text.split('\r'))
text = ' '.join(text.split('\n'))
  • 移除 \r 回车符
  • 将所有 \n 替换为空格,避免跨行断裂影响匹配

步骤 2定义对话匹配模式

dialog_pattern = r'([“\"](.*?)[”\"])'
  • 匹配使用中文左/右引号 “” 或英文双引号 "" 包裹的内容
  • (.*?) 非贪婪捕获中间内容
  • flags=re.DOTALL 允许匹配跨行对话

步骤 3逐段提取并处理非对话 + 对话部分

通过 re.finditer() 遍历所有对话块:

a. 提取当前对话前的非对话文本
non_dialog = text[last_idx:start]
b. 尝试用中文规则分割(优先中文句末标点)
sentences = re.findall(r'[^。!?!?]*[。!?!?]', non_dialog, re.MULTILINE)
  • 匹配以 , , , !, ? 结尾的中文/英文句子
  • 若无结果,则调用 split_english_sentences() 处理纯英文段落
c. 添加已分割的句子到结果
parts.extend([s.strip() for s in sentences if s.strip()])
d. 完整保留整个对话块(不分割)
parts.append(match.group(1).strip())  # 如:“你好!”
e. 更新索引位置
last_idx = end  # 下一次从对话结束后开始

步骤 4处理最后一个对话之后的剩余文本

重复上述非对话处理流程,完成收尾。

示例调用

text = '''
张三说:“你今天过得怎么样?”
李四回答“还不错我刚从U.S.A回来。”
然后他笑了笑。
'''

result = split_text_with_dialog_preserved(text)
for i, part in enumerate(result):
    print(f"{i+1}. {part}")

输出示例

1. 张三说:“你今天过得怎么样?”
2. “还不错我刚从U.S.A回来。”
3. 然后他笑了笑。

注意:对话内容作为一个整体保留,其中 U.S.A 不会被错误切开。


⚠️ 注意事项与限制

项目 说明
缩写支持有限 当前硬编码了常用缩写,若需扩展可修改 abbreviations 正则
仅支持双引号对话 单引号(如 'hello')不会被视为对话块
不支持嵌套引号 “他说:‘你好’” 可能导致匹配异常
性能建议 对超长文本建议分段处理,避免正则效率下降

🧪 测试建议

推荐对以下类型文本进行测试验证:

  • 含缩写的英文句子(如 Dr. John works in the U.S.A.
  • 中英混合带对话(如 小明说“I'm fine!”
  • 多行对话结构
  • 特殊符号与标点组合

📦 总结

本工具包提供了稳健的句子分割能力,尤其适合需要保留语义完整性(特别是对话)的 NLP 前处理任务。结合正则表达式与临时标记机制,有效解决了缩写误切与对话破坏的问题。

推荐用于:文本清洗、对话系统预处理、文学作品分析等场景。


📌 作者: 开发者
📅 最后更新: 2025年4月5日