机器学习实战篇--TF-IDF实战--名著红楼梦的文本数据处理
《红楼梦》文本分析实战:从分卷处理到关键词提取
在文本分析领域,经典文学作品是非常好的研究对象。本文以《红楼梦》为例,详细介绍从原始文本分卷、关键词提取到TF-IDF分析的完整流程,包含可直接运行的代码及原理说明,适合文本处理初学者参考。
一、数据分析:《红楼梦》文本分卷处理
1. 导入模块和初始设置
import os # 导入os模块,用于处理文件路径等操作系统相关功能
file = open('红楼梦.txt', encoding='utf-8') # 打开源文件,使用utf-8编码
flag = 0 # 标记是否已经创建过分卷文件,0表示未创建,1表示已创建
juan_file = None # 用于存储当前打开的分卷文件对象,初始化为None
i = 1 # 分卷编号,从1开始计数
2. 空白行处理标记
skip_blank_lines = False # 新增标记:是否正在跳过空白行,False表示不跳过
3. 主循环:逐行处理文本
for line in file: # 遍历源文件的每一行
stripped_line = line.strip() # 去除行首尾的空白字符(空格、换行符等),用于判断和匹配
# 处理需要跳过空白行的情况
if skip_blank_lines: # 如果处于跳过空白行状态
if stripped_line == '': # 当前行是空白行
continue # 跳过当前行,继续处理下一行
else: # 当前行不是空白行
skip_blank_lines = False # 关闭跳过空白行状态
# 过滤广告内容
if '手机电子书·大学生小说网' in stripped_line: # 如果当前行包含这个广告文本
skip_blank_lines = True # 开启跳过空白行模式,处理广告后的空白行
continue # 跳过当前广告行,不写入分卷文件
# 处理分卷标记行
if '卷 第' in stripped_line: # 如果当前行是分卷标记(如"卷 第一")
# 生成分卷文件名,格式为"01_卷 第一.txt",确保编号是两位数
juan_name = f"{i:02d}_{stripped_line}.txt"
i += 1 # 分卷编号自增1
# 创建分卷文件的完整路径,将分卷文件保存在"分卷"文件夹下
path = os.path.join('分卷', juan_name)
print(path) # 打印当前分卷文件的路径,方便查看进度
# 关闭上一个分卷文件(如果存在)
if flag == 1 and juan_file is not None: # 如果已经创建过分卷文件
juan_file.close() # 关闭上一个分卷文件
# 创建并打开当前分卷文件,用于写入内容
juan_file = open(path, 'w', encoding='utf-8')
flag = 1 # 更新标记,表示已经创建过分卷文件
continue # 跳过当前分卷标记行,不写入分卷文件(也可以根据需要决定是否写入)
# 写入内容到当前分卷文件
if juan_file is not None: # 如果当前有打开的分卷文件
juan_file.write(line) # 将当前行写入分卷文件(使用原始line而不是stripped_line,保留原始格式)
4. 清理工作:关闭文件
# 关闭最后一个分卷文件(如果存在)
if juan_file is not None:
juan_file.close()
# 关闭源文件
file.close()
二、关键词提取:基于分词的文本预处理
1. 导入必要的库
import pandas as pd # 用于数据处理和分析,构建DataFrame和处理停用词
import os # 用于文件和目录操作,遍历文件夹等
import jieba # 中文分词库,用于将中文文本分割成词语
2. 遍历文件夹收集文件路径和内容
# 初始化两个列表,分别存储文件路径和文件内容
filePaths = []
fileContents = []
# 遍历"./分卷"目录下的所有文件(包括子目录中的文件)
# os.walk()返回一个三元组:当前目录路径、当前目录下的子目录列表、当前目录下的文件列表
for root, dirs, files in os.walk(r"分卷"):
for name in files: # 遍历当前目录下的所有文件
# 拼接完整的文件路径(根目录+文件名)
filePath = os.path.join(root, name)
filePaths.append(filePath) # 将文件路径添加到列表
# 读取文件内容
f = open(filePath, 'r', encoding='utf-8') # 以只读模式打开文件,指定编码为utf-8
fileContent = f.read() # 读取整个文件内容
f.close() # 关闭文件
fileContents.append(fileContent) # 将文件内容添加到列表
3. 构建 DataFrame 存储数据
# 使用pandas构建一个数据框(类似表格),包含两列:filePath(文件路径)和fileContent(文件内容)
corpos = pd.DataFrame({
'filePath': filePaths,
'fileContent': fileContents
})
4. 加载自定义资源
# 加载《红楼梦》专属分词补充词库,让jieba更好地识别小说中的专有名词(如人名、地名等)
jieba.load_userdict("红楼梦词库.txt")
# 读取中文停用词表
# stopwordsCN.txt是包含中文停用词的文件(如"的"、"了"、"在"等无实际意义的词)
# encoding='utf8'指定编码,engine='python'避免编码相关的解析问题
# index_col=False表示不将任何一列作为索引
stopwords = pd.read_csv("stopwordsCN.txt", encoding='utf8', engine='python', index_col=False)
5. 分词处理与停用词过滤
# 打开一个文件用于写入分词结果
file_to_jieba = open('分词后汇总.txt', 'w', encoding='utf-8')
# 遍历corpos数据框中的每一行(即每一卷的内容)
for index, row in corpos.iterrows():
juan_ci = '' # 用于存储当前卷的分词结果
fileContent = row['fileContent'] # 获取当前行的文件内容
# 使用jieba进行分词,cut()方法返回一个可迭代的生成器
segs = jieba.cut(fileContent)
# 遍历每个分词结果
for seg in segs:
# 过滤条件:
# 1. 该词不在停用词表中(seg not in stopwords.stopword.values)
# 2. 去除空白字符后长度大于0(避免空字符串)
if seg not in stopwords.stopword.values and len(seg.strip()) > 0:
juan_ci += seg + ' ' # 将符合条件的词添加到结果字符串,并用空格分隔
# 将当前卷的分词结果写入文件,每行对应一卷的内容
file_to_jieba.write(juan_ci + '\n')
# 关闭文件,释放资源
file_to_jieba.close()
三、TF-IDF模拟:提取各卷核心关键词
1. 导入必要的库
import pandas as pd # 用于数据处理和分析,构建DataFrame展示结果
from sklearn.feature_extraction.text import TfidfVectorizer # 从scikit-learn库导入TF-IDF向量器
2. 读取分词后的文本数据
# 打开分词后的汇总文件,读取所有行内容
infile = open('分词后汇总.txt','r',encoding='utf-8')
corpus = infile.readlines() # 读取文件所有行,存储为列表,每个元素对应一卷的分词结果
3. 计算 TF-IDF 矩阵
# 初始化TF-IDF向量器
vectorizer = TfidfVectorizer()
# 对语料库进行拟合(学习词汇表)并转换为TF-IDF矩阵
tfidf = vectorizer.fit_transform(corpus)
# 获取词汇表(所有分词后的词语列表)
wordlist = vectorizer.get_feature_names() # 注意:较新的sklearn版本建议使用get_feature_names_out()
4. 构建 TF-IDF 数据框
# 将TF-IDF矩阵转置(词汇为行,文档为列),转换为稠密矩阵,再构建DataFrame
df = pd.DataFrame(tfidf.T.todense(), index=wordlist)
5. 定义提取 Top N 关键词的函数
def get_top_keywords(col, top_n=10):
# 过滤出当前文档(列)中TF-IDF值大于0的词语(即该词在文档中出现过)
non_zero = col[col > 0]
# 返回TF-IDF值最大的前top_n个词语及其值(按降序排列)
return non_zero.nlargest(top_n).items()
6. 应用函数提取所有文档的关键词
# 对DataFrame的每一列(每个文档)应用get_top_keywords函数,提取前10个关键词
top_keywords_result = df.apply(
lambda col: get_top_keywords(col, top_n=10),
axis=0) # axis=0表示按列应用函数
7. 打印结果
# 遍历结果,按文档编号(从1开始)打印每卷的核心关键词
for doc_idx, top_items in enumerate(top_keywords_result, start=1):
print(f"第{doc_idx}回的核心关键词:{list(top_items)[:10]}")
四、泛用性:代码的扩展与适配场景
一、代码核心逻辑与可修改点
原代码流程可概括为:
原始文本收集→分卷/分块处理→分词与过滤→TF-IDF关键词提取→结果输出
核心可修改点:
-
文本来源(输入文件/文件夹路径)
-
分块规则(按标记、长度、章节等)
-
分词补充词库(领域专属词汇)
-
停用词表(过滤无意义词汇)
-
关键词提取参数(Top N数量、算法调整)
二、简单修改后的可能作用
-
文本结构化处理
通过修改分块规则(如按"章节""段落""时间戳"等标记),可将长文本拆分为结构化子文本,方便按单元分析(如小说按"章节"拆分、报告按"小节"拆分)。
-
领域专属词汇提取
替换自定义词库(如"红楼梦词库.txt"改为"医学词库.txt""法律词库.txt")和停用词表,可精准识别领域内专业术语,过滤通用无意义词汇。
-
关键信息快速定位
调整TF-IDF参数(如修改
top_n数量、增加词语最小/最大出现频率限制),可提取每段文本的核心关键词,快速定位重点(如章节核心人物、报告核心观点)。 -
文本特征对比分析
通过输出各分块的关键词差异,可对比不同文本单元的内容侧重(如不同章节的主题变化、不同作者的写作风格差异)。
三、典型应用场景
-
文学/历史文本分析
-
修改点:分块规则按"回目""章节标题"拆分(如《三国演义》《史记》);补充词库添加古代人名、地名、官职(如"丞相""节度使")。
-
作用:提取每章节核心人物、事件关键词,分析情节发展脉络(如"某章节关键词以'战争''计谋'为主,反映军事主题")。
-
-
学术论文/报告整理
-
修改点:分块规则按"摘要""引言""实验部分"等标题拆分;停用词表添加学术通用虚词(如"研究表明""综上所述")。
-
作用:快速提取各部分核心术语(如实验方法、结论关键词),生成论文结构摘要。
-
-
企业文档/客服记录分析
-
修改点:文本来源读取"客服对话记录""会议纪要"文件夹;分块规则按"日期""对话ID"拆分单条记录;补充词库添加企业产品名、行业术语(如"APP闪退""退款流程")。
-
作用:提取高频问题关键词(如"登录失败""物流延迟"),定位客户需求或业务痛点。
-
-
社交媒体/舆情分析
-
修改点:文本来源读取"微博评论""论坛帖子"文本文件;停用词表添加网络流行虚词(如"哈哈哈""绝了")。
-
作用:按时间段或话题分块,提取热点关键词(如某事件的讨论焦点),辅助舆情监控。
-
总结
本文代码本质是一套"文本预处理+关键词提取"的通用工具,通过修改分块规则、词库和输入来源,可快速适配文学、学术、企业、舆情等多领域的文本分析需求,核心价值是降低长文本处理成本,实现关键信息的自动化提取与对比。
更多推荐
所有评论(0)