NLP 分词实战:用 Python 和 jieba 做中文分词(原理、实战与代码全解析)
一、前言:从“我爱自然语言处理”说起
在学习 NLP 的过程中,很多人一开始都会有一个困惑:
“英文文本分析好像挺简单,直接用空格分词就行,为什么中文要搞一个‘分词’这么麻烦的步骤?”
我们先看两句话:
- 英文:
I love natural language processing. - 中文:
我爱自然语言处理。
在英文中,天然就有空格:
I / love / natural / language / processing / .
而在中文中,没有显式的分隔符,计算机看到的是:
我爱自然语言处理。
如果不做分词,后面的所有分析基本无法顺利进行。
- 做文本分类:不知道“自然语言处理”是一个整体,很容易丢失关键信息
- 做搜索引擎:用户搜“自然语言处理”,而你的文档里刚好是“自然语言处理和大模型”,如果没有分词,很难召回
- 做推荐/标签:提取关键词就无从谈起
所以:中文 NLP 的第 0 步,几乎永远是——分词。
二、中文分词的核心挑战与常见方法
1. 为什么中文分词比你想象的难?
中文分词有两个核心难点:
-
词边界不明显:
“研究生命起源”到底是研究 / 生命 / 起源
还是研究生 / 命 / 起源?
机器需要根据语境、词典、统计信息等综合判断。
-
新词层出不穷:
互联网热词、行业术语、公司产品名……一大堆在传统词典中都没有。
比如:大模型、知识蒸馏、对话机器人、知识图谱等,这些词出现之前,老词典根本不认识。
2. 常见的中文分词思路(简要了解一下)
在工业界,常见分词方法大致有几类(这里不展开算法细节,只做概念级介绍):
-
基于规则和词典:
维护一个大词典,从左到右/从右到左扫描,进行最大匹配。
优点:简单直观,速度快。
缺点:完全依赖词典,新词识别差。 -
基于统计的模型:
利用大规模语料,统计“某个切分方式”出现的概率,选最可能的一种。
典型方法:HMM、CRF、双向 LSTM 等序列标注模型。 -
基于深度学习/预训练模型:
把分词看成序列标注或者序列到序列问题,结合 BERT、GPT 等大模型来做。
效果好,但训练、部署成本较高,一般用于大型系统。
jieba 的实现是一个**“词典 + 统计 + HMM”混合方案**:既能利用词典的效率,又能通过统计和 HMM 做一定程度的新词识别,对大多数应用场景来说已经足够好用。
三、jieba 快速上手:安装与最小可运行示例
1. 安装
pip install jieba
如果网络有问题,可以加镜像源,例如(以清华为例):
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple jieba
2. 最小示例(10 行搞定分词)
import jieba
if __name__ == "__main__":
text = "我爱自然语言处理,也喜欢用Python做文本挖掘。"
words = jieba.lcut(text) # 默认为精确模式
print(words)
运行后你会看到类似输出:
['我', '爱', '自然语言', '处理', ',', '也', '喜欢', '用', 'Python', '做', '文本', '挖掘', '。']
这就是你第一个中文分词程序 🎉(虽然你不让我用 emoji,我口头庆祝一下)。
四、三种分词模式:精确、全模式、搜索引擎模式详解
我们用统一的例子来说明差异:
import jieba
text = "小明硕士毕业于中国科学院计算所,后来在日本京都大学深造。"
1. 精确模式(最常用)
words = jieba.lcut(text, cut_all=False)
print("精确模式:", "/".join(words))
可能结果:
精确模式: 小明/硕士/毕业/于/中国科学院/计算所/,/后来/在/日本京都大学/深造/。
特点:
- 对每一处歧义尽量给出最合理的切分
- 适合:文本分析、分类、聚类、主题建模、特征提取
2. 全模式(适合做索引)
words_full = jieba.lcut(text, cut_all=True)
print("全模式:", "/".join(words_full))
可能结果:
全模式: 小明/硕士/毕业/于/中国/中国科学院/科学/学院/科学院/计算/计算所/,/后来/在/日本/日本京都大学/京都/京都大学/大学/深造/。
特点:
- 把所有可能成为“词”的片段都切出来
- 好处:召回率高,检索时更不容易漏掉匹配
- 坏处:冗余较多,需要后续算法进一步筛选
3. 搜索引擎模式(精确 + 细粒度)
words_search = jieba.lcut_for_search(text)
print("搜索引擎模式:", "/".join(words_search))
输出类似:
搜索引擎模式: 小明/硕士/毕业/于/中国/中国科学院/科学院/计算/计算所/,/后来/在/日本/日本京都大学/京都/京都大学/大学/深造/。
理解:
- 在精确模式基础上,对长词再做细切分
- 比如
"中国科学院"会被切成"中国" / "科学院",这样搜索“中国”或“科学院”都能命中 - 非常适合在构建倒排索引时使用
五、工程实战(一):从文本文件到分词结果
实际项目中,我们经常会有一堆 .txt 文件,想批量分词。下面我们写一个可直接使用的小脚本。
1. 单文件分词脚本
import jieba
from pathlib import Path
def cut_file(input_path, output_path, mode="accurate"):
"""
对单个文本文件进行分词,并将结果写入新文件。
- mode: accurate / full / search
"""
input_path = Path(input_path)
output_path = Path(output_path)
if not input_path.exists():
raise FileNotFoundError(f"输入文件不存在:{input_path}")
text = input_path.read_text(encoding="utf-8", errors="ignore")
if mode == "accurate":
words = jieba.lcut(text)
elif mode == "full":
words = jieba.lcut(text, cut_all=True)
elif mode == "search":
words = jieba.lcut_for_search(text)
else:
raise ValueError("mode must be: 'accurate' | 'full' | 'search'")
# 这里使用空格连接,便于后续处理
result = " ".join(words)
output_path.write_text(result, encoding="utf-8")
print(f"[OK] 分词完成:{input_path} -> {output_path}(模式:{mode})")
if __name__ == "__main__":
cut_file("input.txt", "input_cut.txt", mode="accurate")
使用方式:
-
把你要分词的文本保存为
input.txt -
把脚本保存为
cut_text.py -
终端执行:
python cut_text.py
-
在同目录下会生成
input_cut.txt,其中就是用空格分隔的分词结果。
2. 批量处理目录下的所有 .txt 文件
import jieba
from pathlib import Path
def batch_cut(input_dir, output_dir, mode="accurate"):
input_dir = Path(input_dir)
output_dir = Path(output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
for txt_file in input_dir.glob("*.txt"):
output_file = output_dir / f"{txt_file.stem}_cut.txt"
text = txt_file.read_text(encoding="utf-8", errors="ignore")
if mode == "accurate":
words = jieba.lcut(text)
elif mode == "full":
words = jieba.lcut(text, cut_all=True)
elif mode == "search":
words = jieba.lcut_for_search(text)
else:
raise ValueError("mode must be: 'accurate' | 'full' | 'search'")
output_file.write_text(" ".join(words), encoding="utf-8")
print(f"[OK] {txt_file.name} -> {output_file.name}")
if __name__ == "__main__":
batch_cut("raw_texts", "cut_texts", mode="accurate")
raw_texts:原始文本目录cut_texts:分词后保存的目录
这个脚本经常可以直接用在文本预处理阶段,非常实用。
六、工程实战(二):自定义词典与新词识别
1. 动态添加词语(适合小项目)
import jieba
# 动态增加几个词
jieba.add_word("知识蒸馏", freq=10, tag="n")
jieba.add_word("大模型", freq=20, tag="n")
jieba.add_word("自然语言处理", freq=30, tag="n")
text = "我最近在研究自然语言处理和大模型相关的知识蒸馏技术。"
print("默认分词:", "/".join(jieba.lcut(text)))
你可以试试有无 add_word 的效果对比,直观感受差别。
2. 外部用户词典(更推荐的方式)
创建 user_dict.txt:
自然语言处理 50 n
大模型 40 n
知识蒸馏 30 n
知识图谱 30 n
文本挖掘 20 n
代码中加载:
import jieba
jieba.load_userdict("user_dict.txt")
text = "自然语言处理和大模型是当前人工智能中非常热门的方向,例如知识图谱和知识蒸馏等技术都依赖大量文本数据。"
print("/".join(jieba.lcut(text)))
你会发现像 "自然语言处理"、"大模型"、"知识图谱"、"知识蒸馏" 等词都被正确识别了。
3. 新词发现(简单示意)
jieba 内部用到了 HMM 对一些新词进行识别,你可以通过观察词频统计和左右熵进一步做新词挖掘,不过这已经超出基础教程范畴,这里只给一个简单的统计脚本示例,帮助你从语料中找高频词。
import jieba
from collections import Counter
from pathlib import Path
def find_top_words(path, top_k=50):
text = Path(path).read_text(encoding="utf-8", errors="ignore")
words = jieba.lcut(text)
counter = Counter(words)
# 简单过滤掉太短的“词”
for w in list(counter):
if len(w.strip()) <= 1:
del counter[w]
for word, freq in counter.most_common(top_k):
print(word, freq)
if __name__ == "__main__":
find_top_words("large_corpus.txt", top_k=100)
把高频词人工筛一遍,就能发现不少需要加入词典的领域专有词。
七、工程实战(三):停用词、词频统计与可视化
做 NLP 时,如果你直接使用所有分词结果,会遇到一个问题:
“的、了、是、在、和、一个、我们、你们……” 这些功能词频率特别高,但几乎没什么语义贡献。
因此我们常常需要一个停用词表。
1. 准备停用词表
网上有很多开源的停用词表,你可以搜 中文停用词表,下载一个 stopwords.txt,大致形式如下:
的
了
在
是
和
一个
我们
你们
他们
……
2. 分词 + 去停用词 + 词频统计
import jieba
from collections import Counter
from pathlib import Path
def load_stopwords(path):
stopwords = set()
with open(path, "r", encoding="utf-8") as f:
for line in f:
w = line.strip()
if not w:
continue
stopwords.add(w)
return stopwords
def word_frequency(text_path, stopwords_path=None, top_k=50):
text = Path(text_path).read_text(encoding="utf-8", errors="ignore")
words = jieba.lcut(text)
if stopwords_path:
stopwords = load_stopwords(stopwords_path)
words = [w for w in words if w not in stopwords and w.strip()]
counter = Counter(words)
for word, freq in counter.most_common(top_k):
print(word, freq)
if __name__ == "__main__":
word_frequency("large_corpus.txt", stopwords_path="stopwords.txt", top_k=50)
这样你就可以快速看到文本中真正重要的词。
3. 可视化:简单词云图(可选)
如果你愿意用一个第三方库 wordcloud,还可以把词频显示成词云图。
pip install wordcloud matplotlib
import jieba
from wordcloud import WordCloud
import matplotlib.pyplot as plt
from pathlib import Path
def generate_wordcloud(text_path, font_path, output="wordcloud.png"):
text = Path(text_path).read_text(encoding="utf-8", errors="ignore")
words = jieba.lcut(text)
content = " ".join(words)
wc = WordCloud(
font_path=font_path, # 例如 C:\Windows\Fonts\simhei.ttf
width=800,
height=600,
background_color="white",
max_words=200
)
wc.generate(content)
wc.to_file(output)
plt.imshow(wc, interpolation="bilinear")
plt.axis("off")
plt.show()
if __name__ == "__main__":
generate_wordcloud("large_corpus.txt", font_path=r"C:\Windows\Fonts\simhei.ttf")
这在写博客、做 PPT 时非常有视觉冲击力。
八、关键词提取:TF-IDF 与 TextRank 在 jieba 中的用法
jieba 内置了两种关键词提取算法:
- TF-IDF:基于词频和逆文档频率
- TextRank:基于图排序,类似 PageRank
1. TF-IDF 关键词提取
import jieba.analyse
text = """
自然语言处理(NLP)是人工智能和语言学领域的一个重要分支。
它研究如何处理和理解由人类使用的自然语言。
近年来,随着大模型和深度学习的发展,NLP 在搜索、对话系统、机器翻译等领域得到了广泛应用。
# 提取前 10 个关键词
keywords = jieba.analyse.extract_tags(text, topK=10, withWeight=True, allowPOS=())
print("TF-IDF 关键词:")
for word, weight in keywords:
print(f"{word}\t{weight:.4f}")
topK:返回前 K 个关键词withWeight:是否返回权重allowPOS:允许的词性,不填就不过滤
2. TextRank 关键词提取
import jieba.analyse
keywords = jieba.analyse.textrank(text, topK=10, withWeight=True, allowPOS=('ns', 'n', 'vn', 'v'))
print("TextRank 关键词:")
for word, weight in keywords:
print(f"{word}\t{weight:.4f}")
- TextRank 更依赖词之间的共现关系,对长文更友好
allowPOS常用于过滤,只保留名词、动词等
你可以把这两种方法的结果放在一起对比,感受差异。
九、微型搜索引擎:从分词到简单“搜索结果排序”
在前面的小例子里,我们只是用“出现次数”的简单和来打分。下面我们稍微升级一下评分方式,引入一个简化的 TF-IDF 思路。
1. 准备文档
import jieba
from collections import Counter, defaultdict
import math
docs = [
"我爱自然语言处理和文本挖掘。",
"Python 是一门非常适合做数据分析的语言。",
"最近大模型在 NLP 领域非常火。",
"很多公司开始招聘有自然语言处理经验的工程师。",
"搜索引擎会用到分词、倒排索引和相关性排序。",
]
# 对每篇文档分词
cut_docs = [jieba.lcut(doc) for doc in docs]
2. 计算 IDF(逆文档频率)
def compute_idf(cut_docs):
根据分词后的文档列表计算每个词的 IDF
N = len(cut_docs)
df = defaultdict(int)
for words in cut_docs:
unique_words = set(words)
for w in unique_words:
df[w] += 1
idf = {}
for w, df_w in df.items():
idf[w] = math.log(N / (1 + df_w)) + 1 # +1 防止除零
return idf
idf_dict = compute_idf(cut_docs)
3. 用简化版 TF-IDF 打分
def search(query, top_k=3):
query_words = jieba.lcut(query)
scores = []
for idx, words in enumerate(cut_docs):
tf = Counter(words)
score = 0.0
for qw in query_words:
score += tf[qw] * idf_dict.get(qw, 0.0)
scores.append((score, idx))
scores.sort(reverse=True)
results = []
for score, idx in scores[:top_k]:
if score <= 0:
continue
results.append((score, docs[idx]))
return results
if __name__ == "__main__":
q = "自然语言处理"
for s, d in search(q):
print(f"得分: {s:.4f}\t文档: {d}")
虽然这个“搜索引擎”非常简化,但完整体现了一个典型流程:
分词 → 统计 TF → 计算 IDF → 计算 TF-IDF → 排序
这是很多经典信息检索课程中最核心的一套思路。
十、jieba 词性标注(POS Tagging)简介
分词之后,我们可以进一步对每个词打上词性标记,例如:名词、动词、形容词等。
jieba 提供了 posseg 模块来完成这件事。
import jieba.posseg as pseg
text = "小明硕士毕业于中国科学院计算所。"
words = pseg.cut(text)
for w, flag in words:
print(w, flag)
你会看到类似输出:
小明 nr
硕士 n
毕业 v
于 p
中国科学院 nt
计算所 n
。 x
nr:人名n:名词v:动词p:介词nt:机构团体名x:其它符号
词性标注在很多任务中很有用,比如:
- 抽取名词短语作为候选关键词
- 过滤掉大量虚词,只保留名词、动词做特征
- 做**实体识别(NER)**的前置特征
十一、实践中的常见坑与经验总结
1. 编码问题
- 统一使用
utf-8编码是最省心的方案 - 读文件时:
encoding="utf-8", errors="ignore"可以避免程序直接崩溃 - Windows 路径要注意
\和转义问题,建议用r"C:\path\to\file"或Path对象
2. 性能与内存
- 对大文本(比如几百 MB)做分词时,不要一次性读入内存,可以按行/按块处理
- 多次调用分词时,不要在循环里频繁
jieba.initialize(),直接在顶部导入一次,在整个进程中复用即可 - 若需要并行处理,可以使用
multiprocessing,每个进程独立加载 jieba
3. 分词粒度控制
- 如果你感觉“词太细了”,试试:
- 使用精确模式而不是全模式
- 适当增加停用词(过滤掉一些你不关心的短词)
- 如果你感觉“词太粗了”,可以:
- 使用
lcut_for_search的搜索模式 - 降低某些词在用户词典中的频次,或者干脆删除
- 使用
4. 词典更新策略
- 对固定领域项目(比如电商、医疗、金融),建议:
- 先基于一定规模的语料做词频统计
- 人工挑选高频新词加入用户词典
- 对快速变化的文本(比如微博、公众号、新闻热点),可定期重新统计词频,迭代用户词典
十二、写在最后:从“用会 jieba”到“理解中文 NLP 的第一步”
通过这一篇文章,你应该已经掌握:
-
概念层面
- 为什么中文必须进行分词
- 中文分词相对英文分词困难在哪里
- 词典、统计、HMM、大模型在分词中的角色
-
工具层面
- 如何安装与快速使用 jieba
- 精确模式 / 全模式 / 搜索模式 的适用场景
- 如何对文件/目录进行批量分词
- 如何使用用户词典和停用词表优化效果
- 如何用 jieba 做关键词提取(TF-IDF / TextRank)
- 如何做初级词频统计、绘制词云
- 如何基于分词结果实现一个“迷你搜索功能”
-
工程实践层面
- 如何处理编码与性能问题
- 如何利用统计信息不断迭代用户词典
- 如何把分词结果用于后续的分类、聚类、推荐、搜索等任务
从实践的角度来说,会用好 jieba,基本就已经具备了处理中文文本数据的“入门资格”:
你可以把任何一段中文文本,变成可计算、可学习的结构化数据。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)