关注

【从文本拆分到关键词挖掘:Python 解锁《红楼梦》文本分析新方式】

本项目以 “文本结构化→特征量化→结果分析” 为核心逻辑,先将非结构化的全文 txt 拆分为结构化章节文件,再通过分词和 TF-IDF 算法实现词汇重要性量化,可快速适配其他长篇文本的分析需求

关键技术点包括:正则匹配定位章节、jieba 分词适配古典文学、TF-IDF 算法量化词汇重要性。

一、技术栈准备

本次实战所需的核心库:

  • 基础库:os(文件 / 路径处理)、re(正则匹配)、pandas(数据结构化);
  • 中文处理:jieba(中文分词),支持自定义词库;
  • 算法库:sklearn.feature_extraction.text.TfidfVectorizer(TF-IDF 特征提取)。

二、实战步骤:从文本拆分到关键词提取

(一)步骤 1:拆分《红楼梦》为 120 个章节文件
import os  # python标准库,不需要安装。关于操作系统的库
import re
import pandas as pd

# ===================== 核心优化:适配文本格式+解决报错 =====================
# 1. 确保保存目录存在(避免路径不存在报错)
output_dir = r'.\红楼梦\分卷1'
os.makedirs(output_dir, exist_ok=True)

# 2. 打开源文件(使用with语句自动关闭,更安全)
with open(r'.\红楼梦\红楼梦.txt', encoding='utf-8') as file:
    flag = 0  # 用来标记当前是不是在第一次保存文件
    juan_file = None  # 初始化文件对象,避免未定义报错


    # 定义:清理Windows非法文件名字符(解决OSError报错)
    def clean_filename(filename):
        illegal_chars = r'[\\/:*?"<>|,。?!;:""''《》()()【】]'
        clean_name = re.sub(illegal_chars, '', filename)  # 移除非法字符
        return clean_name[:50] + '.txt'  # 限制文件名长度,避免超长


    # 定义:精准匹配“卷+回”标题(适配文本中“上卷 第一回 XXX”格式)
    chapter_pattern = re.compile(r'^[ \s]*([上下]卷\s+第[一二三四五六七八九十百零]+回.*)$', re.MULTILINE)
    # chapter_pattern = re.compile(r'^[ \s]*([上下]卷)?\s*第([一二三四五六七八九十百]+|[\d]{1,3})回.*$', re.MULTILINE)

    for line in file:  # 开始遍历整个红楼梦
        line_strip = line.strip()
        # 精准匹配“卷+回”标题(核心:只识别章节标题行)
        match = chapter_pattern.match(line_strip)
        if match:
            # 提取纯净的标题(去除前后空格/全角空格)
            juan_title = match.group(1).strip()
            # 清理文件名(关键:避免非法字符)
            juan_name = clean_filename(juan_title)
            # 构建完整路径
            path = os.path.join(output_dir, juan_name)
            print(f"正在创建文件:{path}")

            if flag == 0:  # 判断是否是第1次读取到卷+回标题
                # 关闭初始可能存在的空文件
                if juan_file:
                    juan_file.close()
                # 创建第1个卷文件
                juan_file = open(path, 'w', encoding='utf-8')
                # 写入标题(保留原格式)
                juan_file.write(line)
                flag = 1
            else:  # 不是第1次读取到卷+回标题
                # 关闭上一次的文件对象
                juan_file.close()
                # 创建新的卷文件
                juan_file = open(path, 'w', encoding='utf-8')
                # 写入标题(保留原格式)
                juan_file.write(line)
            continue

        # 写入章节内容(仅当文件对象已创建时,避免空写)
        if juan_file is not None:
            juan_file.write(line)

# 最终关闭文件(避免资源泄露)
if juan_file:
    juan_file.close()

print(f"\n✅ 拆分完成!共生成{flag}个卷文件,保存在:{output_dir}")
  • 正则匹配:覆盖《红楼梦》所有回目标题格式,确保 120 回都能被精准识别;
  • 文件名清理:避免因特殊字符导致文件创建失败;
  • 文件管理:通过current_file变量管理当前写入的文件,确保章节内容正确归属
(二)步骤 2:结构化读取章节数据
import pandas as pd
import os  # 处理操作系统的文件,python标准库,和操作系统打交道!

# 41
filePaths = []  # #[#保存文件的路径]  filePaths: ['.\\红楼梦\\分卷\\上卷 第一回 甄士隐梦幻识通灵\\u3000']
fileContents = []  # #[#保存文件路径对应的内容] fileContents: []

# 42
for root, dirs, files in os.walk(r'.\红楼梦\分卷1'):  # os.walk是直接对文件夹进行遍历 #os.list
    for name in files:  # name: '下卷 第八十四回 试文字宝玉始提亲 探惊风贾环重结怨.txt'
        filePath = os.path.join(root, name)  # root+'\\'+name获取每个文件的路径 #filePath:
        filePaths.append(filePath)  # 将文件路径添加到列表filePaths中

        f = open(filePath, 'r', encoding='utf-8')  # f: <_io.TextIOWrapper name='.\\红楼梦\\
        fileContent = f.read()  # 读取每一个的文件中内容 fileContent: "
        f.close()

        fileContents.append(fileContent)  # 将每一卷的文件内容添加到列表fileContents中

corpos = pd.DataFrame({  # 将文件路径及文件内容添加为DataFrame框架中  numpy ->c corpos: f
    'filePath': filePaths,  # 'int64'  str()  float('3.142')
    'fileContent': fileContents})  # 训练大家的数据处理能力

print(corpos)

目录遍历:自动获取所有章节文件,无需手动指定路径;
结构化存储:将文件路径和内容关联,便于后续按章节处理。

(三)步骤 3:中文分词 + 停用词过滤
import jieba  # 保存的词库就是  辞海,   形容词、语气词 不会作为核心关键词的。提前我就剔除TF-IDF的。
jieba.load_userdict(r'.\红楼梦\红楼梦词库.txt')  # 导入分词库,把红楼梦专属的单词添加到jieba词库中。

# 导入停用词库 ,把无关心的词提出。
stopwords = pd.read_csv(r'.\红楼梦\StopwordsCN.txt',  # StopwordsCN.txt保存的是 常见的助动词
                        encoding='utf8', engine='python', index_col=False)  # engine读取文件时的解析引擎

file_to_jieba = open(r'.\红楼梦\分词后汇总1.txt', 'w', encoding='utf-8')  # 创建一个新文本 file_to
for index, row in corpos.iterrows():  # iterrows遍历行数据 index: 119  row: ('filePath',
    juan_ci = ''  # 空的字符串,处理后的单词依次添加到juan_ci后面 juan_ci: '手机 电子书 大学生 小说
    fileContent = row['fileContent']
    segs = jieba.cut(fileContent)  # 对文本内容进行分词,返回一个可遍历的迭代器 segs: <gen
    for seg in segs:  # 遍历每一个词 seg: '\n'
        if seg not in stopwords.stopword.values and len(seg.strip()) > 0:  # 剔除停用词和字符为
            juan_ci = juan_ci + seg + ' '  # juan_ci = juan_ci + '电子' + '电子'
    file_to_jieba.write(juan_ci + '\n')

file_to_jieba.close()

自定义词库:解决 jieba 对 “贾宝玉、林黛玉” 等古典文学词汇的识别问题;
停用词过滤:移除无意义词汇,仅保留核心语义词汇,提升后续分析准确性。

(四)步骤 4:TF-IDF 提取核心关键词

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

inFile = open(r".\红楼梦\分词后汇总1.txt", 'r', encoding='utf-8')
corpus = inFile.readlines()  # 返回一个列表,列表一个元素就是一行内容,一行内容一篇分词后的文章

vectorizer = TfidfVectorizer()  # 类,转为TF-IDF的向量器
tfidf = vectorizer.fit_transform(corpus)  # 传入数据,返回包含TF-IDF的向量值
wordlist = vectorizer.get_feature_names_out()  # 获取特征名称,所有的词

df = pd.DataFrame(tfidf.T.todense(), index=wordlist)  # tfidf.T.todense() 恢复为稀疏矩阵

# 下面的任务就是对表格进行排序 pandas
for i in range(len(corpus)):  # 排序,将重要的关键词排序在最前面
    featurelist = df.iloc[:, i].to_list()  # 通过索引号获取第i列的内容并转换为列表

    resdict = {}  # 排序以及看输出结果对不对
    for j in range(0, len(wordlist)):
        resdict[wordlist[j]] = featurelist[j]  # [('贾宝玉',0.223), ()]
    resdict = sorted(resdict.items(), key=lambda x: x[1], reverse=True)  # 字典的键值对,元组数据类型
    print('第{}回的核心关键词:'.format(i+1), resdict[0:10])

TF-IDF 向量转换:将分词文本转为数学矩阵,量化词汇重要性;
关键词排序:按 TF-IDF 值降序排序,提取前 10 个关键词,快速定位章节核心内容。

运行结果:

转载自CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/m0_74373135/article/details/158852888

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--