自然语言处理NLP03案例——提取小说红楼梦各卷关键词TOP10
- 手机
- 2025-08-25 14:51:01

如下图,是红楼梦的本文小说,现在我们要提取出红楼梦每卷排名前十的关键词
为了更顺利的完成要求,我们将任务拆解为以下四个节点
将这个文件中上下卷共120卷拆分开,每一卷内容保存为一个新的文本文件,文件名是相应卷名 ,所有卷放入文件夹 .\红楼梦
打印出每卷地址与内容
对每一卷进行分词
计算TF-IDF值,保存每卷TOP10关键词
(快速跳转)
拆分红楼梦120卷并另存
打印分卷地址与内容
对每一卷进行分词
计算TF-IDF值并保存每卷中top10关键词
拆分红楼梦120卷并另存
步骤:
按卷分割文件:
代码通过检测每一行是否包含 卷 第,来判断是否需要开始一个新的分卷文件。
每个分卷文件以卷名命名,并保存在 红楼梦分卷 目录下。
初始文件:
代码会先创建一个临时文件 红楼梦开头.txt,用于保存尚未分卷的内容。
如果发现 卷 第 后,会关闭临时文件,并开始按卷保存内容。
文件路径:
使用 os.path.join 生成分卷文件的完整路径,确保路径跨平台兼容。
文件操作:
使用 open() 打开文件,write() 写入文件,close() 关闭文件。
代码:
import os # 打开《红楼梦》的原始文本文件,指定编码为utf-8 file = open('红楼梦.txt', encoding='utf-8') # 设置一个标志变量flag,用于判断是否需要创建新的分卷文件 flag = 0 # 打开一个临时文件'红楼梦开头.txt',用于保存未分卷的内容 chapter_file = open('.\红楼梦开头.txt', 'w', encoding='utf-8') # 逐行读取《红楼梦》的原始文件 for line in file: # 检查当前行是否包含“卷 第”,这是分卷的标志 if '卷 第' in line: # 提取卷名,并去掉空白字符,生成分卷文件的名称 chapter_name = line.strip() + '.txt' # 生成分卷文件的完整路径,保存在`红楼梦分卷`目录下 path = os.path.join('.\\红楼梦分卷\\', chapter_name) print(path) # 打印分卷文件的路径 # 如果flag为0,表示这是第一个分卷,直接创建并写入文件 if flag == 0: chapter_file = open(path, 'w', encoding='utf-8') flag = 1 # 将flag置为1,表示已开始分卷 else: # 如果flag不为0,表示之前已经有分卷文件了,先关闭当前文件 chapter_file.close() # 再创建一个新的分卷文件 chapter_file = open(path, 'w', encoding='utf-8') # 跳过本行,不将分卷标志行写入分卷文件 continue # 将当前行写入分卷文件 chapter_file.write(line) # 循环结束后,关闭最后一个分卷文件 chapter_file.close()运行结果:
1)分卷
2)红楼梦未分卷的内容
打印分卷地址与内容步骤:
文件遍历:
使用 os.walk 遍历 .\红楼梦分卷 目录及其子目录下的所有文件。
对每个文件,获取其完整路径并打印。
文件读取:
打开文件并读取所有行。
跳过前两行(从第3行开始)拼接文件内容。
数据存储:
将文件路径和文件内容分别存储在列表 filePaths 和 fileContents 中。
创建 DataFrame:
使用 pandas 将文件路径和文件内容组合成一个 DataFrame。
输出结果:
打印 DataFrame,显示文件路径和文件内容的对应关系。
代码:
import pandas as pd import os # 初始化两个列表,分别用于存储文件路径和文件内容 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') lines = f.readlines() # 读取文件的所有行 fileContent = ''.join(lines[2:]) # 从第3行开始拼接文件内容(跳过前两行) f.close() # 关闭文件 fileContents.append(fileContent) # 将文件内容添加到列表中 # 使用 pandas 创建一个 DataFrame,包含文件路径和文件内容 corpos = pd.DataFrame({ 'filePath': filePaths, # 文件路径列 'fileContent': fileContents # 文件内容列 }) # 打印 DataFrame print(corpos)运行结果:
对每一卷进行分词步骤:
加载自定义词典:
使用 jieba.load_userdict 加载 红楼梦词库.txt,确保分词时能正确识别《红楼梦》中的专有词汇(例如人名、地名等)。
读取停用词表:
使用 pandas 读取停用词表 StopwordsCN.txt,停用词是分词后需要过滤掉的无意义词(例如“的”、“了”、“是”等)。
遍历文件内容:
通过 corpos.iterrows() 遍历 corpos DataFrame 中的每一行,获取文件路径和文件内容。
分词处理:
使用 jieba.cut 对文件内容进行分词。
遍历分词结果,过滤掉停用词和空白词(长度为 0 的词)。
保存分词结果:
将处理后的分词结果写入到 红楼梦分词后汇总.txt 文件中。
代码:
import jieba # 加载自定义词典,确保分词结果符合《红楼梦》的专有词汇 jieba.load_userdict(r'.\红楼梦词库.txt') # 读取停用词表,停用词是分词后需要过滤掉的常见无意义词 stopwords = pd.read_csv(r'./StopwordsCN.txt', encoding='utf8', engine='python', index_col=False) # 打开一个文件,用于保存分词后的汇总结果 file_to_jieba = open(r'.\红楼梦分词后汇总.txt', 'w', encoding='utf-8') # 遍历 corpos DataFrame 中的每一行 for index, row in corpos.iterrows(): juan_ci = '' # 初始化一个空字符串,用于保存当前卷的分词结果 filePath = row['filePath'] # 获取当前文件路径 fileContent = row['fileContent'] # 获取当前文件内容 # 使用 jieba 对文件内容进行分词 segs = jieba.cut(fileContent) # 遍历分词结果,去除停用词和空白词 for seg in segs: # 如果当前词不是停用词且长度大于 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()运行结果:
1)运行成功界面
2)红楼梦分词后汇总.txt
计算TF-IDF值并保存每卷中top10关键词步骤:
读取分词结果:
打开分词后的汇总文件 红楼梦分词后汇总.txt,读取所有行作为语料库。
计算 TF-IDF 值:
使用 TfidfVectorizer 对语料库进行向量化,生成 TF-IDF 矩阵。
获取词汇列表:
使用 get_feature_names_out() 获取所有词汇(特征词)。
转换为 DataFrame:
将 TF-IDF 矩阵转换为 DataFrame,转置是为了让每一列对应一卷,每一行对应一个词汇。
提取核心关键词:
遍历每一卷,提取其 TF-IDF 值最高的前 10 个核心关键词。
保存结果:
将每回的核心关键词 TOP10 写入文件 红楼梦分节关键词排名TOP10.txt。
代码:
# 导入所需的库 from sklearn.feature_extraction.text import TfidfVectorizer import pandas as pd # 打开分词后的汇总文件,读取所有行作为语料库 inFile = open(r'.\红楼梦分词后汇总.txt', 'r', encoding='utf-8') corpus = inFile.readlines() # 语料库,每个元素是一行(即一卷的分词结果) # 初始化 TfidfVectorizer,用于计算 TF-IDF 值 vectorizer = TfidfVectorizer() # 使用语料库计算 TF-IDF 矩阵 tfidf = vectorizer.fit_transform(corpus) # 获取所有词汇(特征词) wordlist = vectorizer.get_feature_names_out() # 注意:`get_feature_names` 已弃用,推荐使用 `get_feature_names_out` # 将 TF-IDF 矩阵转换为 DataFrame,便于后续操作 # 转置矩阵是为了让每一列对应一卷,每一行对应一个词汇 df = pd.DataFrame(tfidf.T.todense(), index=wordlist) # 打开文件,用于保存每回的核心关键词排名 file_keywords = open(r'.\红楼梦分节关键词排名TOP10.txt', 'w', encoding='utf-8') # 遍历每一卷,提取其核心关键词 TOP10 for i in range(len(corpus)): # 获取当前卷的 TF-IDF 值列表 featurelist = df.iloc[:, i].to_list() # 初始化一个字典,用于存储词汇及其对应的 TF-IDF 值 resdict = {} # 将词汇和 TF-IDF 值一一对应 for j in range(0, len(wordlist)): resdict[wordlist[j]] = featurelist[j] # 对字典按 TF-IDF 值进行降序排序 resdict = sorted(resdict.items(), key=lambda x: x[1], reverse=True) # 将当前卷的核心关键词 TOP10 写入文件 file_keywords.write(f'第{i+1}回的核心关键词:' + str(resdict[0:10]) + '\n') # 如果需要在控制台打印结果,可以取消注释以下代码 print('第{}回的核心关键词:'.format(i+1), resdict[0:10]) # 关闭关键词文件 file_keywords.close()运行结果:
自然语言处理NLP03案例——提取小说红楼梦各卷关键词TOP10由讯客互联手机栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“自然语言处理NLP03案例——提取小说红楼梦各卷关键词TOP10”