使用 Jieba 库进行 TF-IDF 关键词提取(以《红楼梦》为例)

在中文文本分析中,TF-IDF(Term Frequency - Inverse Document Frequency) 是最常用的关键词提取方法之一。它通过评估词在单个文档中的出现频率和在所有文档中的稀有程度,来衡量该词的重要性。

本文将以《红楼梦》分卷文本为例,演示如何使用 jieba 库完成分词、停用词过滤,并最终进行 TF-IDF 关键词提取


一、TF-IDF 的定义

TF-IDF(Term Frequency-Inverse Document Frequency,词频 - 逆文档频率)是文本挖掘领域中一种常用技术,其核心作用是评估某个词语在特定文档中的重要程度。该指标由两部分构成:

  • 词频(TF):指一个词语在当前文档中出现的频率。
  • 逆文档频率(IDF):用于衡量该词语在整个文档集合中的普遍重要性(即该词是否在多数文档中都频繁出现)。

通常来说,一个词语的 TF-IDF 值越高,就意味着它在当前文档中的重要性越高。

二、选择 jieba 库的原因

jieba 是一款优秀的中文分词工具库,其突出特点使其成为众多场景下的优选,包括:

  • 支持三种不同的分词模式,可适应多样化的分词需求。
  • 允许用户导入自定义词典,提升对特定领域词汇的分词准确性。
  • 具备高效的词性标注功能,能快速为词语标注所属词性。
  • 内置 TF-IDF 关键词提取功能,方便直接从文本中提取关键信息。
  • 整体设计轻量,且操作简单易懂,易于上手使用。

代码一:准备数据

我们将准备 ./红楼梦 文件夹,其中:

  • 红楼梦正文:红楼梦.txt

  • 用户自定义词典红楼梦词库.txt(保证人名、地名等专业词汇的分词准确性)

  • 中文停用词表StopwordsCN.txt(去除“的”“了”等无意义的高频词) 

  • 空文件夹./红楼梦/分卷:用于存放代码产生分卷


《红楼梦》按卷分割文本代码详解

import os# 打开整本红楼梦文本
file = open('.\\红楼梦\\红楼梦.txt', encoding='utf-8')flag = 0  # 标记是否已打开分卷文件# 遍历整本小说每一行
for line in file:# 如果该行包含“卷 第”,表示这是卷的开头if '卷 第' in line:juan_name = line.strip() + '.txt'  # 用该行作为分卷文件名path = os.path.join('.\\红楼梦\\分卷', juan_name)print(path)if flag == 0:# 第一次遇到卷标题,打开分卷文件准备写入juan_file = open(path, 'w', encoding='utf-8')flag = 1else:# 遇到新的卷标题时,先关闭之前的分卷文件,再打开新的juan_file.close()juan_file = open(path, 'w', encoding='utf-8')continue# 过滤空行和广告信息(如“手机电子书·大学生小说网”)if line.strip() != "" and "手机电子书·大学生小说网" not in line:juan_file.write(line)  # 写入当前分卷文件# 最后关闭最后一个分卷文件及整本书文件
juan_file.close()
file.close()

代码流程说明

  1. 打开整本《红楼梦》文本文件

    • 使用 open 以 utf-8 编码打开 .\\红楼梦\\红楼梦.txt 文件,准备逐行读取。

  2. 初始化标记变量 flag

    • flag = 0 表示还没有打开分卷文件。

  3. 逐行读取整本小说内容

    • 使用 for line in file: 依次处理每一行文本。

  4. 判断是否遇到新分卷开头

    • 通过判断字符串 '卷 第' 是否在当前行中,识别分卷标题行。

    • 例如“卷 第1卷”,代表这是一个新的分卷开始。

  5. 新卷文件的创建与切换

    • 如果是第一次遇到分卷标题(flag == 0),则新建一个对应的分卷文件,准备写入。

    • 如果之前已经打开了分卷文件,先关闭旧文件,再打开新分卷文件。

    • 文件名以当前行内容加 .txt 后缀命名,并保存在 .\\红楼梦\\分卷 目录下。

  6. 非分卷标题行内容处理

    • 过滤空行(line.strip() != "")和广告信息(不包含 "手机电子书·大学生小说网")。

    • 合格的行写入当前打开的分卷文件中。

  7. 结束时关闭所有文件

    • 循环结束后,关闭当前分卷文件和整本小说文件。


运行效果

  • 红楼梦.txt按照“卷 第X卷”的行作为分界点,生成多个如“卷 第1卷.txt”、“卷 第2卷.txt”等文件,分别保存在 红楼梦\分卷 文件夹中。

  • 每个分卷文件包含对应的章节内容,便于后续的分词和关键词分析。


代码二:对每个分卷提取词典

1. 导入必要库

import pandas as pd
import os
import jieba
  • pandas 用于创建和操作结构化数据(DataFrame),方便后续处理。

  • os 用于遍历文件夹,获取分卷文件路径。

  • jieba 是一个常用的中文分词库,用于将连续文本切分成词语。


2. 读取分卷文本

filePaths = []
fileContents = []
for root, dirs, files in os.walk(r"./红楼梦/分卷"):for name in files:filePath = os.path.join(root, name)  # 获取每个分卷的完整路径print(filePath)filePaths.append(filePath)  # 记录该路径到filePaths列表f = open(filePath, 'r', encoding='utf-8')fileContent = f.read()  # 读取整个文件内容为字符串f.close()fileContents.append(fileContent)  # 把内容加入列表
  • 使用 os.walk 递归遍历 ./红楼梦/分卷 文件夹,获取所有分卷文本文件路径和名称。

  • 将每个分卷文件的路径和对应的文本内容分别存储到 filePathsfileContents 两个列表中。

  • 读取文件时用 UTF-8 编码,保证中文字符正确读取。


3. 构建 pandas DataFrame

corpos = pd.DataFrame({'filePath': filePaths,'fileContent': fileContents
})
  • 将分卷的路径和内容以字典形式传入,生成一个二维表格结构的 DataFrame。

  • 每一行对应一个分卷文件,包含:

    • filePath:该分卷的文件路径

    • fileContent:该分卷对应的文本内容(字符串)

这样方便后续批量处理。


4. 加载用户自定义词典和停用词表

jieba.load_userdict(r"./红楼梦/红楼梦词库.txt")
stopwords = pd.read_csv(r"./红楼梦/StopwordsCN.txt",encoding='utf-8', engine='python', index_col=False)
  • jieba.load_userdict() 用来加载用户定义的词典,解决默认词库中可能没有的专有名词、人名地名、书中特殊词汇的分词准确度问题。

  • stopwords 读取停用词文件,一般是高频无实际含义的词(如“的”、“了”、“在”等),需要过滤掉,避免影响后续分析。

stopwords是一个 DataFrame,其中一列(假设列名为stopword)包含所有停用词。


5. 创建分词输出文件

file_to_jieba = open(r"./红楼梦/分词后汇总.txt", 'w', encoding='utf-8')
  • 打开一个新的文本文件,用来存储所有分卷的分词结果。

  • 使用写入模式,每个分卷分词结果写入一行,方便后续分析。


6. 对每个分卷逐条处理

for index, row in corpos.iterrows():juan_ci = ''filePath = row['filePath']fileContent = row['fileContent']segs = jieba.cut(fileContent)  # 对该卷内容进行分词,返回一个生成器for seg in segs:# 如果分词结果不是停用词且不是空字符串if seg not in stopwords.stopword.values and len(seg.strip()) > 0:juan_ci += seg + ' '  # 词语之间用空格分开file_to_jieba.write(juan_ci + '\n')  # 写入该卷分词结果,换行区分不同卷
  • corpos.iterrows() 按行遍历 DataFrame,每行对应一个分卷。

  • 取出文本内容后,用 jieba.cut() 对文本分词,得到一个可迭代的词语序列。

  • 对每个词:

    • 判断它是否为停用词(通过停用词列表过滤)

    • 判断是否为空白(防止多余空格或特殊符号)

  • 过滤后的词汇拼接成字符串,用空格分隔,形成分词后的“句子”。

  • 每个分卷的分词结果写入一行,方便后续按行读取、TF-IDF等分析。


7. 关闭文件

file_to_jieba.close()
  • 关闭分词结果文件,保证写入完整。


运行结果:


代码三:计算 TF-IDF

from sklearn.feature_extraction.text import TfidfVectorizer
import pandas as pd

1. 读取分词后的汇总文本

File = open(r".\红楼梦\分词后汇总.txt", 'r', encoding='utf-8')
corpus = File.readlines()  # 每行作为一个文档内容
  • 每行对应一卷(或一回)的分词结果。

  • corpus 是一个列表,corpus[i] 表示第 i 卷的文本。


2. 初始化并计算 TF-IDF

from sklearn.feature_extraction.text import TfidfVectorizer vectorizer = TfidfVectorizer()
tfidf = vectorizer.fit_transform(corpus)
wordlist = vectorizer.get_feature_names()
  • TfidfVectorizer() 自动执行:

    • 统计每个词的词频(TF)

    • 计算逆文档频率(IDF)

    • 得到每个词在每个文档中的 TF-IDF 值

  • wordlist 是词汇表(所有出现的词)。


3. 构建 DataFrame 存储结果

df = pd.DataFrame(tfidf.T.todense(), index=wordlist)
  • tfidf 是稀疏矩阵(需要 .todense() 转成稠密矩阵才能放进 DataFrame)。

  • 转置 .T 后:

    • 行(index)是词汇

    • 列是文档(每卷)


 可以打印出部分数据直观理解:

print(wordlist)
print(tfidf)
# print(tfidf.todense())
print(df.head(20))

wordlist:词汇表

tfidf:

(0,14385)即表示一个二维坐标

  • 0/119 → 这是文档编号(row index),表示这是第 1 篇文档(编号从 0 开始)。

  • 14385→ 这是词在词汇表(vocabulary)中的编号(column index),对应某个特定的单词,比如可能是 "machine""learning"(具体要看 vectorizer.get_feature_names_out() 对应表)。

  • 0.01659769526115283→ 这是这个单词在该文档中的 TF-IDF 权重,数值越大,说明这个单词在这篇文章中越重要(出现频率高,但在其他文档中不常见)。

df:

  • 行索引(index)_______txt一一 等是分词后的词语。

  • 列索引(0, 1, 2, ...):表示第几卷(文档),从 0 列到 119 列,说明总共有 120 卷/文档。

  • 单元格的数值:该词在该卷里的 TF-IDF 权重(越大表示该词在这卷中越重要)。


4. 提取每卷的 Top 10 关键词

for i in range(len(corpus)):top_keywords = df.iloc[:, i].sort_values(ascending=False).head(10)print(f'第{i+1}回的核心关键词:\n{top_keywords}')
  • 取第 i 列(即第 i 卷的所有词的 TF-IDF 值)

  • sort_values(ascending=False) 降序排列

  • head(10) 取权重最高的 10 个关键词

结果:


扩展:可视化每卷 Top 10 关键词

以第 1 卷为例,绘制柱状图:

import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False# [:, 0]取第1回,[:, 119]取第120回
top_keywords = df.iloc[:, 0].sort_values(ascending=False).head(10)plt.figure(figsize=(8,5))
plt.barh(top_keywords.index, top_keywords.values, color='skyblue')
plt.gca().invert_yaxis()  # 倒序
plt.title("第1回的TF-IDF关键词")
plt.xlabel("TF-IDF权重")
plt.show()


改进建议

  1. 自动去掉空行

    corpus = [line.strip() for line in corpus if line.strip()]
    

    避免空文档导致向量化器报错。

  2. 指定分隔符
    因为你的分词结果是用空格分隔的,可以告诉 TfidfVectorizer

    vectorizer = TfidfVectorizer(token_pattern=r"(?u)\b\w+\b")
    
  3. 保存结果
    直接把每卷关键词存到 CSV,便于后续分析:

    all_keywords = {}
    for i in range(len(corpus)):all_keywords[f"第{i+1}回"] = df.iloc[:, i].sort_values(ascending=False).head(10).index.tolist()
    pd.DataFrame.from_dict(all_keywords, orient='index').to_csv("红楼梦_TF-IDF关键词.csv", encoding="utf-8-sig")
    

总结

本文实现了从原始《红楼梦》文本关键词提取的完整流程:

  1. 对正文进行分卷

  2. 读取分卷内容

  3. 自定义词典 + 停用词过滤

  4. 分词并保存

  5. 使用 jieba.analyse.extract_tags 进行 TF-IDF 关键词提取

  6. TfidfVectorizer计算 TF-IDF

  7. 扩展:可视化权重排序

通过这种方式,我们不仅能提取整本书的主题关键词,还能按卷分析主题变化,为文本挖掘、主题建模、人物关系分析等工作打下基础。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/918594.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/918594.shtml
英文地址,请注明出处:http://en.pswp.cn/news/918594.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kotlin语法整理

Kotlin语法整理 Kotlin语法整理 一、基本数据类型 共8种 二、变量的声明三、条件 1. if…else if…else语句2. when 语句 四、循环 1. while 语句2. do…while 语句3. for 语句4. repeat 语句5. break 语句6. continue 语句 五、数组 1. 创建元素未初始化的数组2. 创建元素初始…

跨平台低延迟的RTMP推流播放在无纸化会议与智慧教室的技术设计和架构实践

✳️ 引言:让每一块屏幕“同频”的核心技术 无纸化会议与智慧教室,正在从“辅助工具”走向“核心基础设施”,成为政企数字化与教育信息化建设的标配。它们的核心诉求并不只是替代纸质文档或黑板,而是要在多终端、多地点、多网络环…

最优扩展大型语言模型测试时计算量可能比扩展模型参数更有效

摘要 通过增加测试时计算量使大型语言模型(LLMs)提升输出效果,是构建能基于开放自然语言自主改进的通用智能体的重要步骤。本文研究LLMs推理阶段计算量的扩展规律,重点回答以下问题:若允许LLM使用固定但可观的推理阶段…

GPT5评测对比与使用

经过长达一年的技术迭代,OpenAI正式推出GPT-5系列模型,包含GPT-5(标准版)、GPT-5-mini(轻量版)和GPT-5-nano(极简版)三个版本,定价策略保持统一。本次升级在性能、效率与…

Git与CI/CD相关知识点总结

Git与CI/CD相关知识点总结 1. Git对象模型与存储机制 1.1 Git对象类型 Commit对象:包含提交信息、作者、时间、父commit引用、树对象引用Tree对象:描述目录结构和文件引用Blob对象:实际的文件内容 1.2 存储机制特点 增量存储:每次…

CS2服务器是何方神圣

CS2服务器是何方神圣CS2「子刷新频率」深度拆解:从官方宣言到“吞子弹”真相00 先给结论01 官方原话到底说了什么02 一条时间线看懂「Sub-tick」03 技术解剖:Sub-tick 的实现细节3.1 输入包结构(Valve 公开源码节选)3.2 连续积分&…

Docker守护进程安全加固在香港VPS环境的操作标准

Docker守护进程安全加固在香港vps环境的操作标准随着云计算技术的普及,Docker守护进程安全加固已成为香港VPS环境中不可忽视的重要环节。本文将系统性地介绍如何通过配置优化、访问控制、网络隔离等维度,在香港虚拟私有服务器上建立符合企业级安全标准的…

Rust 项目编译故障排查:从 ‘onnxruntime‘ 链接失败到 ‘#![feature]‘ 工具链不兼容错误

Rust 项目编译故障排查报告:从原生库链接失败到工具链不兼容 场景: 编译一个本地 Rust 项目时遇到连续的编译错误。一、 故障现象概述 在对一个 Rust 项目执行 cargo build 命令时,先后遇到了两个不同性质的编译错误,导致编译流程中断。初始错…

K8s 1.32.6版本部署文档

主机配置 作用IP地址操作系统配置关键组件k8s-master172.16.1.30Rocky Linux release 94C/4G/50GBkube-apiserver, etcd,dockerk8s-node1172.16.1.31Rocky Linux release94C/4G/50GBkubelet, kube-proxy,dockerk8s-node2172.16.1.32Rocky Linux release 94C/4G/50GBkubelet, k…

第十六届蓝桥杯大赛青少组 C++ 省赛真题解析(2025年8月10日)

第一题 题目:运行以下程序,输出的结果是()。 #include<bits/stdc++.h> using namespace std; int func(int y) { y -= 5; cout << "x"; return 0; } int main() { int x = 10, y = 5; if (x > y || func(y)) cout &…

PID 控制算法 | stm32 直流电机控制

注&#xff1a;本文为 “PID 算法 | stm32 直流电机控制” 相关合辑。 图片清晰度受引文原图所限。 略作重排&#xff0c;未全校去重。 如有内容异常&#xff0c;请看原文。 STM32—PID 控制在直流电机中的应用 Aspirant-GQ 于 2020-04-28 23:23:39 发布 一、PID 控制算法 1…

高效的Python课表生成器

在日常的学校管理中,排课表是一项繁琐而又必须完成的工作。特别是对于那些没有自动化排课系统的学校来说,手动安排学生的课程不仅耗时,而且容易出错。最近,我接到了一项任务,需要为学校的学生安排非选修课的课程表。以下是我使用Python编写的解决方案,并结合了一些实际的…

深度学习-卷积神经网络-NIN

网络结构是卷积神经网络&#xff08;CNN&#xff09;发展的关键。其中&#xff0c;网络结构的改进至关重要。本文将介绍一种具有创新意义的卷积神经网络——NIN&#xff08;Network in Network&#xff09;。LeNet、AlexNet和VGG都有一个共同的设计模式&#xff1a;通过一系列的…

Java-96 深入浅出 MySQL 索引与排序机制详解与优化实践 Filesort

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; AI炼丹日志-31- 千呼万唤始出来 GPT-5 发布&#xff01;“快的…

MLAG双活网络妙招:BGP + 静态VRRP实现智能负载均衡

引言 在现代数据中心和企业网络架构中&#xff0c;高可用性和负载均衡是核心需求。MLAG&#xff08;Multi-Chassis Link Aggregation&#xff09;技术结合BGP和静态VRRP的解决方案&#xff0c;为网络工程师提供了一种高效实现双活网络负载均衡的妙招。本文将深入探讨这一技术组…

如何构建PHP表单页面及验证相关原理(PHP基础)

文章目录PHP表单 - 必需字段PHP - 必需字段PHP - 显示错误信息总结PHP表单 - 验证邮件和URLPHP - 验证名称PHP - 验证邮件验证URLPHP 完整表单实例 PHP表单 - 必需字段 该章内容将介绍如何设置表单必需字段及错误信息 PHP - 必需字段 我们首先给出一个表的验证规则&#xff0c;…

API如何集成Web搜索功能:原理、实践与最佳选型

API如何集成Web搜索功能&#xff1a;原理、实践与最佳选型 在现代智能应用开发中&#xff0c;模型生成结果往往需要融合最新的互联网信息。通过集成Web搜索工具&#xff0c;模型可以在生成响应前主动检索网络&#xff0c;获取实时数据。这一能力极大提升了智能系统的准确性和时…

Spring Boot项目中调用第三方接口

目录 步骤1: 添加依赖 步骤2: 配置HTTP客户端 配置RestTemplate 配置WebClient 步骤3: 在Service层调用接口 使用RestTemplate示例 使用WebClient示例 步骤4: 在Controller层调用Service 注意事项 总结 Spring Boot项目中调用第三方接口 在Spring Boot项目中调用第三…

关系型数据库:原理、演进与生态全景——从理论基石到云原生的深度巡礼

目录 一、引言&#xff1a;当“表”成为世界的通用语言 二、理论基石&#xff1a;关系模型与 ACID 三、引擎架构&#xff1a;一条 SQL 的奇幻漂流 四、存储机制&#xff1a;页、缓冲池与 WAL 五、并发控制&#xff1a;锁、MVCC 与隔离级别 六、SQL&#xff1a;声明式语言…

【软考架构】计算机网络中的IP地址表示和子网划分

在计算机网络中&#xff0c;IP地址用于唯一标识网络中的设备。IP地址的表示方式有两种&#xff1a;IPv4和IPv6。IPv4是当前使用最广泛的地址格式&#xff0c;而IPv6是为了解决IPv4地址耗尽问题而设计的。 1. IPv4地址 IPv4地址是一个32位的数字&#xff0c;通常用四个十进制数表…