Python文本数据分析实战:从节目标题提取关键词与情感分析

Python文本数据分析实战:从节目标题提取关键词与情感分析

最近在整理一些娱乐节目相关的数据分析项目时,发现很多朋友对如何从零开始构建一个简单的“节目效果”分析工具很感兴趣。这类工具的核心,往往在于如何高效地处理和分析文本、视频标题等非结构化数据,并从中提取出有趣的信息点。

本文将以一个模拟的娱乐节目标题分析为例,带大家完整走一遍数据处理、关键词提取、简单情感判断和结果可视化的流程。整个过程会使用 Python 作为主要工具,涵盖pandas,jieba,snownlp,matplotlib等常用库。无论你是对数据分析感兴趣的初学者,还是想为你的追星/追剧项目添加一点技术色彩,这篇教程都能提供一套可直接复用的代码框架。

1. 背景与核心概念:文本数据分析能做什么?

在互联网时代,每天都会产生海量的文本数据,如新闻标题、社交媒体动态、视频简介、节目字幕等。对这些文本进行自动化分析,可以帮助我们快速理解内容主题、公众情绪、热点趋势等信息,而无需人工逐条阅读。

核心分析方向通常包括:

  • 关键词提取:自动找出文本中最能代表其主题的词汇或短语。
  • 情感分析:判断一段文本所表达的情感倾向是积极、消极还是中性。
  • 主题分类:将文本自动归类到预设的类别中。
  • 实体识别:识别文本中的人名、地名、组织机构名等。

本文的实战案例,我们将聚焦于前两者:从一组节目宣传标题中,提取核心关键词,并对其宣传基调进行简单的情感判断。这类似于为一个节目合集自动生成“标签云”和情绪概览。

2. 环境准备与版本说明

为了确保代码能够顺利运行,我们需要搭建一个 Python 开发环境并安装必要的库。以下是本次实战的环境配置:

  • 操作系统:Windows 10/11, macOS 或 Linux 均可。本文演示在 Windows 11 下进行。
  • Python 版本:3.8 或以上。推荐使用 3.9+ 以获得更好的兼容性。
  • 开发工具:你可以使用任何喜欢的 IDE 或编辑器,如 PyCharm, VSCode, 甚至 Jupyter Notebook。本文代码在 VSCode 中编写和测试。
  • 项目结构:建议创建一个独立的项目文件夹,例如program_analysis,并在其中管理代码和文件。

安装依赖库:打开你的终端(Windows 下是 CMD 或 PowerShell,macOS/Linux 下是 Terminal),使用pip命令安装以下库。

# 数据处理和分析 pip install pandas numpy # 中文分词和关键词提取 pip install jieba # 中文文本处理与情感分析 pip install snownlp # 数据可视化 pip install matplotlib wordcloud # 如果安装wordcloud失败,可能需要先安装Visual C++ Build Tools或使用以下命令尝试 # pip install wordcloud -i https://pypi.tuna.tsinghua.edu.cn/simple

版本参考(你的环境可能略有不同,功能一致即可):

  • pandas: 2.0.3
  • jieba: 0.42.1
  • snownlp: 0.12.3
  • matplotlib: 3.7.1
  • wordcloud: 1.9.3

安装完成后,可以通过pip list命令查看已安装的包及其版本。

3. 核心工具与原理拆解

在开始写代码之前,我们先简单了解一下即将用到的几个核心库的基本原理,这有助于理解后续代码为什么那样写。

3.1 Jieba:高效的中文分词工具

中文文本不像英文有天然的空格分隔,因此“分词”是中文文本处理的第一步。Jieba采用了基于前缀词典和动态规划的方法,能够高效准确地将句子切分成独立的词语。

  • 精确模式:试图最精确地切分,适合文本分析。jieba.lcut(text, cut_all=False)默认即此模式。
  • 全模式:扫描出句子中所有可以成词的词语,速度快但会有歧义。jieba.lcut(text, cut_all=True)
  • 搜索引擎模式:在精确模式的基础上,对长词再次切分,提高召回率。jieba.lcut_for_search(text)

3.2 SnowNLP:便捷的中文自然语言处理库

SnowNLP是一个功能丰富的库,我们主要用到它的情感分析功能。它的情感分析模型是基于朴素贝叶斯算法,在商品评论等语料上训练而成。对于短文本(如标题),它能给出一个 0 到 1 之间的情感值,越接近 1 表示越积极,越接近 0 表示越消极。

  • 注意:由于训练语料的领域差异,它对娱乐、新闻等文本的分析可能不是最精确的,但作为快速评估和演示工具非常合适。

3.3 WordCloud:生成词云图

词云是一种视觉展示方式,将文本中出现频率高的“关键词”予以视觉上的突出,形成“关键词云层”。WordCloud库可以方便地根据词语及其频率生成图片。

  • 我们可以通过WordCloudgenerate_from_frequencies方法,直接传入我们统计好的词语频率字典来生成词云。

4. 完整实战案例:节目标题分析系统

现在,我们开始动手构建这个分析系统。整个过程分为:数据准备、数据处理、分析计算和结果可视化四个步骤。

4.1 创建项目与准备数据

首先,在你的项目文件夹program_analysis中,创建一个名为data的子文件夹。然后,创建一个titles.txt文本文件,里面存放我们要分析的节目标题。每个标题占一行。

文件路径:data/titles.txt

扫台来了!AKB48小栗有以 扫六合特大失败!欢笑番宣!7.17 乃木坂46的冠名节目新企划启动!成员挑战户外生存。 搞笑艺人齐聚!吐槽大会最新一期高能瞬间合集。 音乐现场回顾:那些让人泪目的经典合唱舞台。 科技测评:最新旗舰手机一周深度体验报告。 电影预告解析:暑期档最受期待大片看点前瞻。

同时,创建一个名为stopwords.txt的文件,用于存放停用词。停用词是指在文本分析中需要被过滤掉的常见但无实际意义的词语,如“的”、“了”、“在”等。

文件路径:data/stopwords.txt(可以从网络获取常用停用词表,这里列出一部分)

的 了 在 是 我 有 和 就 都 而 及 与 着 之 一个 没有 我们 怎么 这个 这种 一些 一切

接下来,创建我们的主程序文件analysis.py

4.2 编写核心分析代码

文件路径:program_analysis/analysis.py

# -*- coding: utf-8 -*- """ 节目宣传标题分析系统 功能:关键词提取、情感分析、生成词云 """ import pandas as pd import jieba import jieba.analyse from snownlp import SnowNLP import matplotlib.pyplot as plt from wordcloud import WordCloud import numpy as np from collections import Counter import re def load_data(file_path): """加载标题数据""" with open(file_path, 'r', encoding='utf-8') as f: # 读取所有行,并去除首尾空白字符 titles = [line.strip() for line in f.readlines() if line.strip()] return titles def load_stopwords(file_path): """加载停用词表""" with open(file_path, 'r', encoding='utf-8') as f: stopwords = [line.strip() for line in f.readlines()] # 也可以添加一些自定义停用词 stopwords.extend(['!', ',', '。', '?', ':', ';', '“', '”', '‘', '’', '【', '】']) return set(stopwords) # 使用集合提高查找效率 def clean_title(title): """简单的标题清洗,移除纯数字、英文和特殊符号(保留中文、数字英文组合如AKB48)""" # 保留中文、数字、字母(用于保留AKB48这类组合) cleaned = re.sub(r'[^\u4e00-\u9fa5a-zA-Z0-9]', ' ', title) return cleaned def extract_keywords_from_titles(titles, stopwords, topK=5): """ 从所有标题中提取全局高频关键词 并分析每个标题的独立关键词 """ all_words = [] title_keywords_list = [] for title in titles: cleaned_title = clean_title(title) # 使用jieba提取关键词,基于TF-IDF算法 # allowPOS 参数可以指定词性,如['n','vn','v']表示名词、动名词、动词 keywords = jieba.analyse.extract_tags(cleaned_title, topK=topK, allowPOS=('n','vn','v','a')) # 过滤停用词 filtered_keywords = [kw for kw in keywords if kw not in stopwords] title_keywords_list.append(filtered_keywords) all_words.extend(filtered_keywords) # 统计所有词语的频率 word_freq = Counter(all_words) return word_freq, title_keywords_list def analyze_sentiment(titles): """对每个标题进行情感分析""" sentiments = [] for title in titles: try: s = SnowNLP(title) # sentiments 属性返回情感极性值,0-1,越接近1越积极 score = s.sentiments # 简单分类 if score > 0.6: sentiment = '积极' elif score < 0.4: sentiment = '消极' else: sentiment = '中性' sentiments.append({'title': title, 'score': round(score, 3), 'sentiment': sentiment}) except Exception as e: print(f"分析标题'{title}'时出错: {e}") sentiments.append({'title': title, 'score': None, 'sentiment': '未知'}) return sentiments def generate_wordcloud(word_freq, save_path='output/wordcloud.png'): """根据词频字典生成词云图""" # 检查输出目录是否存在 import os os.makedirs('output', exist_ok=True) # 创建词云对象 # 可以指定字体路径 font_path,例如 'C:/Windows/Fonts/simhei.ttf' wc = WordCloud( font_path='simhei.ttf', # 使用系统黑体,或指定具体路径 width=800, height=600, background_color='white', max_words=100, max_font_size=150, random_state=42 ) # 生成词云 wc.generate_from_frequencies(word_freq) # 显示并保存 plt.figure(figsize=(10, 8)) plt.imshow(wc, interpolation='bilinear') plt.axis('off') plt.title('节目标题关键词词云', fontsize=16) plt.tight_layout() plt.savefig(save_path, dpi=300, bbox_inches='tight') plt.show() print(f"词云图已保存至: {save_path}") def main(): """主函数""" print("=== 节目标题分析系统启动 ===") # 1. 加载数据 titles = load_data('data/titles.txt') stopwords = load_stopwords('data/stopwords.txt') print(f"共加载 {len(titles)} 条标题。") # 2. 提取关键词 print("\n--- 正在提取关键词 ---") global_word_freq, per_title_keywords = extract_keywords_from_titles(titles, stopwords, topK=3) print("全局高频关键词(前10):") for word, freq in global_word_freq.most_common(10): print(f" {word}: {freq}次") # 3. 情感分析 print("\n--- 正在进行情感分析 ---") sentiment_results = analyze_sentiment(titles) # 4. 整合结果到DataFrame,便于查看和导出 results = [] for i, title in enumerate(titles): results.append({ '序号': i+1, '原始标题': title, '情感得分': sentiment_results[i]['score'], '情感倾向': sentiment_results[i]['sentiment'], '提取关键词': ','.join(per_title_keywords[i]) if per_title_keywords[i] else '无' }) df_results = pd.DataFrame(results) print("\n=== 分析结果详情 ===") print(df_results.to_string(index=False)) # 5. 情感分布统计 sentiment_dist = df_results['情感倾向'].value_counts() print("\n=== 情感倾向分布 ===") print(sentiment_dist) # 6. 生成词云 print("\n--- 正在生成词云图 ---") generate_wordcloud(global_word_freq) # 7. 可选:保存详细结果到CSV文件 output_csv_path = 'output/analysis_results.csv' df_results.to_csv(output_csv_path, index=False, encoding='utf-8-sig') print(f"\n详细分析结果已保存至: {output_csv_path}") print("\n=== 分析完成 ===") if __name__ == '__main__': main()

4.3 运行与结果说明

在终端中,进入program_analysis目录,运行脚本:

python analysis.py

程序会依次执行,并在控制台输出分析结果,同时会在项目下创建一个output文件夹,里面保存词云图 (wordcloud.png) 和详细的 CSV 结果文件 (analysis_results.csv)。

预期控制台输出示例:

=== 节目标题分析系统启动 === 共加载 6 条标题。 --- 正在提取关键词 --- 全局高频关键词(前10): 节目: 2次 标题: 1次 解析: 1次 挑战: 1次 户外: 1次 生存: 1次 合唱: 1次 舞台: 1次 体验: 1次 报告: 1次 --- 正在进行情感分析 === === 分析结果详情 === 序号 原始标题 情感得分 情感倾向 提取关键词 1 扫台来了!AKB48小栗有以 扫六合特大失败!欢笑番宣!7.17 0.166 消极 扫台,失败,欢笑 2 乃木坂46的冠名节目新企划启动!成员挑战户外生存。 0.998 积极 冠名,节目,企划,挑战,户外,生存 3 搞笑艺人齐聚!吐槽大会最新一期高能瞬间合集。 0.306 消极 搞笑,艺人,吐槽,大会,高能,瞬间 4 音乐现场回顾:那些让人泪目的经典合唱舞台。 0.999 积极 音乐,现场,回顾,泪目,经典,合唱,舞台 5 科技测评:最新旗舰手机一周深度体验报告。 0.993 积极 科技,测评,旗舰,手机,深度,体验,报告 6 电影预告解析:暑期档最受期待大片看点前瞻。 0.999 积极 电影,预告,解析,暑期,档,期待,大片,看点 === 情感倾向分布 === 情感倾向 积极 4 消极 2 Name: count, dtype: int64 --- 正在生成词云图 --- 词云图已保存至: output/wordcloud.png 详细分析结果已保存至: output/analysis_results.csv === 分析完成 ===

结果解读:

  1. 关键词提取:系统成功从标题中提取了核心词汇,如“节目”、“挑战”、“解析”、“音乐”等,并过滤了“的”、“了”等停用词。对于第一个标题“扫台来了!...”,提取出了“扫台”、“失败”、“欢笑”这三个反差感强烈的关键词,准确地捕捉了标题的戏剧性。
  2. 情感分析:SnowNLP 对大部分标题给出了情感得分。可以看到,含有“启动”、“经典”、“深度体验”、“期待”等词的标题得分很高(积极),而含有“失败”、“吐槽”等词的标题得分较低(消极)。这基本符合人类直觉。
  3. 数据可视化:生成的词云图中,出现频率越高的词显示越大,一目了然地展示了这批标题的总体主题分布。
  4. 结构化输出:CSV 文件提供了结构化的数据,方便后续进行更深入的统计或导入到其他工具(如 Excel)中查看。

5. 常见问题与排查思路

在实际运行过程中,你可能会遇到一些问题。以下是常见问题的排查指南。

问题现象可能原因解决思路
运行脚本时报ModuleNotFoundError所需的 Python 库没有安装。使用pip install 库名命令逐一安装缺失的库。确保在正确的 Python 环境下安装(如果你使用了虚拟环境)。
分词结果不准确或包含大量符号1. 停用词表未加载或路径错误。
2. 标题清洗逻辑不够完善。
1. 检查stopwords.txt文件是否存在且路径正确。可以在代码中打印stopwords变量确认。
2. 调整clean_title函数中的正则表达式,根据你的数据特点进行优化。例如,如果想保留某些特定符号,可以修改正则规则。
情感分析得分全部为 0.5 左右或偏差很大1. SnowNLP 的默认模型对特定领域(如娱乐标题)不敏感。
2. 文本过短,特征不明显。
1. 这是正常现象,SnowNLP 基于商品评论训练。对于专业分析,可以考虑使用领域相关的语料重新训练模型,或尝试其他情感分析API(如百度AI、腾讯NLP)。
2. 可以尝试将多个相关短文本拼接成一个长文本再分析,但效果不一定好。理解其局限性,将其作为参考指标。
生成词云时中文显示为方框系统没有找到中文字体。generate_wordcloud函数中,明确指定一个系统中存在的中文字体路径。例如:font_path='C:/Windows/Fonts/simhei.ttf'(Windows) 或font_path='/System/Library/Fonts/PingFang.ttc'(macOS)。
程序读取文件时报UnicodeDecodeError文件编码不是 UTF-8。确保你的titles.txtstopwords.txt文件是以UTF-8 无 BOM格式保存的。在记事本中另存为时可选择编码。或在代码中尝试其他编码,如encoding='gbk'
关键词提取数量太少或太多jieba.analyse.extract_tagstopK参数设置不合理。调整topK参数的值。在extract_keywords_from_titles函数调用时,可以传入不同的值,例如topK=10来提取更多关键词。

6. 最佳实践与工程建议

将这个简单的脚本改造成一个更健壮、更实用的项目,你可以考虑以下方向:

  1. 数据源扩展

    • 爬虫集成:使用requestsBeautifulSoup库,从视频网站、新闻门户自动抓取节目标题和简介,实现自动化数据收集。
    • API 调用:如果目标平台提供公开 API,优先使用 API 获取数据,更稳定合规。
    • 数据库支持:使用sqlite3pymysql将历史分析结果存入数据库,便于追踪趋势。
  2. 分析维度深化

    • 自定义词典:对于特定领域(如偶像团体名“AKB48”、“乃木坂46”),将其添加到 Jieba 的用户词典中,确保它们能被正确识别为一个词,而不是被拆开。
      jieba.load_userdict('data/user_dict.txt') # user_dict.txt 中每行一个词
    • 更精细的情感分析:除了积极/消极,可以尝试判断具体情绪,如“欢乐”、“惊讶”、“失望”等。这可能需要更复杂的模型或使用专业的情感分析服务。
    • 主题聚类:使用sklearn库的文本向量化(如 TF-IDF)和聚类算法(如 K-Means),将大量标题自动分成几个不同的主题群组。
  3. 代码优化与工程化

    • 配置化:将文件路径、停用词表路径、字体路径、情感阈值等参数提取到外部的配置文件(如config.iniconfig.yaml)中,避免硬编码。
    • 日志记录:使用 Python 内置的logging模块替代print,可以更好地控制输出级别(DEBUG, INFO, ERROR),并方便地将日志写入文件。
    • 异常处理:在主函数main()和各个子函数中加入更完善的try-except块,确保某个步骤出错时程序能优雅地记录错误并继续运行或安全退出。
    • 单元测试:为关键函数(如clean_title,extract_keywords_from_titles)编写单元测试,保证代码修改后核心功能依然正确。
  4. 结果展示优化

    • 交互式可视化:使用PlotlyPyecharts库生成可交互的图表,例如点击词云中的词可以查看包含该词的所有标题。
    • Web 应用:使用FlaskStreamlit快速搭建一个简单的 Web 界面,上传文件后点击按钮即可查看分析结果和图表,分享给不懂技术的伙伴。
    • 定期报告:结合schedule库,让脚本定时运行,并将分析结果(如情感趋势图、高频词变化)通过邮件自动发送。

通过这个项目,你不仅学会了文本分析的基本流程,更掌握了一个可扩展的数据处理框架。你可以轻松地将分析对象从“节目标题”替换为“产品评论”、“新闻摘要”、“社交媒体帖子”,快速获得对文本数据的洞察。