案例-基于潜在狄利克雷分配(LDA)的内容主题挖掘

# 说明
# - 依赖库:tarfile、os、jieba、gensim、bs4
# - 程序输入:article.txt、news_data.tar.gz
# - 程序输出:打印输出18个主题及新文本的预测主题归属

# 程序

# 导入库

import os
import tarfile

import jieba.posseg as pseg
from bs4 import BeautifulSoup
from gensim import corpora, models


# 函数模块

# 中文分词
def jieba_cut(text):
    '''
    将输入的文本句子根据词性标注做分词
    :param text: 文本句子,字符串型
    :return: 符合规则的分词结果
    '''
    rule_words = ['z', 'vn', 'v', 't', 'nz', 'nr', 'ns', 'n', 'l', 'i', 'j', 'an', 'a']
    words = pseg.cut(text)
    seg_list = [word.word for word in words if word.flag in rule_words]
    return seg_list


# 文本预处理
def text_pro(words_list, tfidf_object=None, training=True):
    '''
    gensim主题建模预处理过程,包含分词类别转字典、生成语料库和TF-IDF转换
    :param words_list: 分词列表,列表型
    :param tfidf_object: TF-IDF模型对象,该对象在训练阶段生成
    :param training: 是否训练阶段,用来针对训练和预测两个阶段做预处理
    :return: 如果是训练阶段,返回词典、TF-IDF对象和TF-IDF向量空间数据;如果是预测阶段,返回TF-IDF向量空间数据
    '''
    # 分词列表转字典
    dic = corpora.Dictionary(words_list)  # 将分词列表转换为字典形式
    print('{:*^60}'.format('token & word mapping review:'))
    for i, w in list(dic.items())[:5]:  # 循环读出字典前5条的每个key和value,对应的是索引值和分词
        print('token:%s -- word:%s' % (i, w))
    # 生成语料库
    corpus = [dic.doc2bow(words) for words in words_list]  # 用于存储语料库的列表
    print('{:*^60}'.format('bag of words review:'))
    print(corpus[0])
    # TF-IDF转换
    if training:
        tfidf = models.TfidfModel(corpus)  # 建立TF-IDF模型对象
        corpus_tfidf = tfidf[corpus]  # 得到TF-IDF向量稀疏矩阵
        print('{:*^60}'.format('TF-IDF model review:'))
        print(list(corpus_tfidf)[0])  # 打印第一条向量
        return dic, corpus_tfidf, tfidf
    else:
        return tfidf_object[corpus]


# 全角转半角
def str_convert(content):
    '''
    将内容中的全角字符,包含英文字母、数字键、符号等转换为半角字符
    :param content: 要转换的字符串内容
    :return: 转换后的半角字符串
    '''
    strs = []
    for each_char in content:  # 循环读取每个字符
        code_num = ord(each_char)  # 读取字符的ASCII值或Unicode值
        if code_num == 12288:  # 全角空格直接转换
            code_num = 32
        elif 65281 <= code_num <= 65374:  # 全角字符(除空格)根据关系转化
            code_num -= 65248
        strs.append(chr(code_num))
    return ''.join(strs)


# 解析文件内容
def data_parse(data):
    '''
    从原始文件中解析出文本内容数据
    :param data: 包含代码的原始内容
    :return: 文本中的所有内容,列表型
    '''
    raw_code = BeautifulSoup(data, 'lxml')  # 建立BeautifulSoup对象
    content_code = raw_code.find_all('content')  # 从包含文本的代码块中找到content标签
    content_list = [str_convert(each_content.text) for each_content in content_code if len(each_content) > 0]
    return content_list


# 读取数据并解析

# 解压缩文件
if not os.path.exists('./news_data'):  # 如果不存在数据目录,则先解压数据文件
    with tarfile.open('news_data.tar.gz') as tar:  # 打开tar.gz压缩包对象
        names = tar.getnames()  # 获得压缩包内的每个文件对象的名称
        for name in names:  # 循环读出每个文件
            tar.extract(name, path='./')  # 将文件解压到指定目录

# 汇总所有内容
all_content = []  # 总列表,用于存储所有文件的文本内容
for root, dirs, files in os.walk('./news_data'):  # 分别读取遍历目录下的根目录、子目录和文件列表
    for file in files:  # 读取每个文件
        file_name = os.path.join(root, file)  # 将目录路径与文件名合并为带有完整路径的文件名
        with open(file_name, encoding='utf-8') as f:  # 以只读方式打开文件
            data = f.read()  # 读取文件内容
        all_content.extend(data_parse(data))  # 从文件内容中获取文本并将结果追加到总列表

# 分词

print('get word list...')
words_list = [list(jieba_cut(each_content)) for each_content in all_content]  # 分词列表,用于存储所有文件的分词结果

# 建立主题模型

dic, corpus_tfidf, tfidf = text_pro(words_list)  # 训练集的文本预处理
num_topics = 3  # 设置主题个数
lda = models.LdaModel(corpus_tfidf, id2word=dic, num_topics=num_topics)  # 通过LDA进行主题建模
print('{:*^60}'.format('topic model review:'))
print(lda.print_topics())

# 新数据集的主题模型预测

with open('article.txt', encoding='utf-8') as f:  # 打开新的文本
    text_new = f.read()  # 读取文本数据
text_content = data_parse(data)  # 解析新的文本
words_list_new = jieba_cut(text_new)  # 将文本转换为分词列表
corpus_tfidf_new = text_pro([words_list_new], tfidf_object=tfidf, training=False)  # 新文本数据集的预处理
corpus_lda_new = lda[corpus_tfidf_new]  # 获取新的分词列表(文档)的主题概率分布
print('{:*^60}'.format('topic forecast:'))
print(list(corpus_lda_new))

注:数据文件链接: https://pan.baidu.com/s/1LN0ZVjf-WfgUFLEXf4VXIA 密码: 0qg4

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值