文本预处理基础:清洗、分词、词性标注

文本预处理,说白了就是给机器喂饭前,先把菜洗干净、切好。我刚开始做文献抽取的时候,觉得这步可有可无,总想直接上模型。结果呢?模型吃进去一堆乱码和特殊符号,吐出来的结果简直没法看。

后来我才明白:预处理的功夫,直接决定了你后续抽取的质量。今天就把这块的坑和经验都摊开来讲。

3.1 数据清洗——把脏数据洗干净

数据清洗是预处理的第一步。为什么这么重要?你想想看,PDF转出的文本里,常有不可见字符、全角半角混用、多余的换行符。不处理干净,分词和标注全都会跑偏。

我在项目中遇到过最典型的情况:一篇英文论文的摘要里,混着几个中文逗号和句号。分词器直接懵了,把那几个句子当成不同语言混着处理,最后抽取的关键词全是乱的。

常见的清洗操作

  • 去除非文本字符:控制字符、零宽空格、Unicode 特殊符号
  • 统一大小写:英文全部转小写(除非是专有名词)
  • 去除HTML标签:如果你从网页抓取的文献
  • 换行符处理:PDF中的硬换行要合并,段落之间保留空行
  • 全角/半角统一:数字、字母全部转半角,标点按需处理

我常用的清洗工具是 Python 的 re 和 unicodedata。给个简单的例子:

import re
import unicodedata

def clean_text(text):
    # 去除控制字符
    text = ''.join(c for c in text if unicodedata.category(c)[0] != 'C' or c == '\n')
    # 统一换行:连续2个以上换行视为段落分隔
    text = re.sub(r'\n{3,}', '\n\n', text)
    # 全角转半角(仅字母数字)
    text = unicodedata.normalize('NFKC', text)
    return text.strip()
我曾经踩过的坑:把中文逗号也转成半角了。结果是分词器把"你好,世界"里的逗号当成英文标点处理,导致分句出错。所以我的建议是:数字和字母转半角,中文标点保持全角。

3.2 中文分词——把句子切成词

中文分词,本质就是判断哪些字可以组成一个有意义的词。相比英文天然有空格分隔,中文得靠算法猜。你想想看,"南京市长江大桥"该怎么切?这正是分词的难点。

主流分词工具对比

工具 特点 适用场景 速度
Jieba 基于词典+统计,支持自定义词典 通用场景,入门首选 快
HanLP 基于感知机/CRF,准确率高 学术文献、专业术语多的场景 中
THULAC 由清华大学开发,兼顾速度和效果 大规模文本处理 快
PaddleNLP 基于预训练模型(ERNIE) 高精度场景,但对硬件有要求 慢

我个人习惯用 Jieba 入门。它有个精妙的设计:先根据词典生成有向无环图(DAG),再用动态规划找最大概率路径。核心代码其实很简单:

import jieba

text = "文献抽取中的文本预处理非常重要"
# 精确模式(推荐)
words = jieba.lcut(text)
# ['文献', '抽取', '中', '的', '文本', '预处理', '非常', '重要']

# 添加自定义词典
jieba.add_word('文本预处理')
words = jieba.lcut(text)
# ['文献', '抽取', '中', '的', '文本预处理', '非常', '重要']
小建议:做文献抽取时,一定要加专业领域词典。我记得有次处理医学文献,"间充质干细胞"被拆成"间充"、"质"、"干"、"细胞",加上词典后一次搞定。

Jieba 的分词模式对比

模式 描述 特点
精确模式 最精确的分词,无冗余 适合文本分析任务
全模式 把所有可能的词都列出来 冗余多,但不容易漏词
搜索引擎模式 在精确模式基础上,对长词再切分 适合搜索场景

3.3 词性标注——给每个词打上标签

分词完,接着给每个词标上词性:名词、动词、形容词……为什么要做?你想想看,"学习"这个词,当动词和当名词时的抽取策略完全不同。

词性标注常用 HMM(隐马尔可夫模型)来做。简单说,就是根据上下文推测最可能的词性序列。Jieba 自带标注功能,咱们直接看:

import jieba.posseg as pseg

text = "深度学习在文献抽取中应用广泛"
words = pseg.lcut(text)
for word, flag in words:
    print(f"{word}({flag})", end=' ')
# 深度(n) 学习(vn) 在(p) 文献(n) 抽取(vn) 中(f) 应用(vn) 广泛(a)
词性标记 含义 举例
n 普通名词 文献、模型
v 动词 学习、处理
vn 动名词 抽取、分析
a 形容词 广泛、重要
p 介词 在、对

标注完成后,你就可以根据词性做过滤了。比如我只保留名词和动名词(因为它们最可能表达领域概念):

def extract_keywords(text):
    words = pseg.lcut(text)
    keep_flags = ['n', 'vn', 'nz', 'ns']
    return [w.word for w in words if w.flag in keep_flags]
关键经验:词性标注不是100%准确的。科技文献里常有新单词或缩写,标注器可能会标错。我的做法是保留原始标注结果,同时做一份基于规则的兜底处理。

本章知识结构

下面这张图总结了文本预处理的完整流程和关键环节:

文本预处理流程概览 原始文本 ① 数据清洗 ② 中文分词 ③ 词性标注 预处理结果 常见清洗内容 去除HTML · 统一大小写 全半角转换 · 换行合并 分词难点 未登录词 · 领域词汇 专业词典是必备的 标注作用 过滤无关词性 辅助抽取规则制定
我曾经踩过的一个坑:把清洗和分词的顺序搞反了。有次先分词后清洗,结果特殊符号被当成词的一部分,生成了很多奇怪的词。后来我固定了两条原则:清洗永远先做,分词后接着词性标注。

其实文本预处理没有太多花哨的东西,核心就是三个步骤走扎实:清洗干净、切词准确、标注到位。每一步都有很多细节,但只要你把上面这些基础操作都掌握了,文献抽取的下游工作会顺畅不少。