用Python进行《琵琶行》文本分析:从NLP基础到情感计算实战
2026/9/3 2:37:40 网站建设 项目流程

最近在整理经典古诗文学习资料时,发现很多朋友对白居易的《琵琶行》停留在“背诵全文”的层面,对其背后的创作背景、情感内核、艺术手法以及如何将其转化为可分析、可应用的“数据”理解不深。作为一首将音乐描写推向极致的叙事长诗,它不仅是文学瑰宝,也蕴含着丰富的情感逻辑和叙事结构,非常适合作为文本分析、情感计算乃至文化项目开发的绝佳案例。

本文将从一个技术实践者的视角,重新拆解《琵琶行》。我们将不仅回顾诗文本身,更会探讨如何利用现代技术(如Python)对其进行量化分析,例如情感倾向分析、高频词统计、意象挖掘等,并尝试构建一个简单的交互式赏析应用。无论你是文学爱好者、中文信息处理的学习者,还是想寻找一个有趣编程项目的开发者,都能从中获得启发和可直接复用的代码。

1. 背景与核心概念:为何《琵琶行》是技术分析的优质样本?

《琵琶行》是唐代诗人白居易创作的一首长篇叙事诗,收录于《白氏长庆集》。诗前小序点明了创作背景:元和十一年(816年),白居易被贬为江州司马,次年秋夜送客浔阳江头,偶遇一位技艺高超却漂泊沦落的琵琶女,有感于“同是天涯沦落人”的共鸣,创作此诗。

从技术分析的角度看,这首诗具有以下突出特点,使其成为理想的文本分析对象:

  1. 叙事结构完整清晰:诗作拥有完整的故事线(相遇-演奏-倾诉-感慨),段落分明,便于进行篇章结构分析和情节划分。
  2. 情感曲线跌宕起伏:情感从“醉不成欢惨将别”的沉闷,到听曲时的“如听仙乐耳暂明”的激昂,再到了解身世后的“江州司马青衫湿”的悲怆,变化显著,适合做情感时序分析。
  3. 语言密度与意象丰富:诗中运用了大量比喻(“大弦嘈嘈如急雨”)、通感(“冰泉冷涩弦凝绝”)和典故,词汇丰富,意象(“枫叶荻花”、“江月”)集中,便于进行词频、共现网络和意象分析。
  4. 音乐描写数据化潜力:对琵琶乐声的描绘极其生动,通过一系列比喻将抽象的听觉感受转化为具体的视觉和触觉意象,这为“音乐文本化”及情感映射提供了绝佳素材。

理解这些特点,我们就能超越单纯的文学赏析,将其视为一个结构化的、富含多维特征的数据集,从而应用自然语言处理(NLP)的基础技术进行探索。

2. 环境准备与版本说明

为了进行后续的文本分析和小型应用开发,我们需要搭建一个Python编程环境。本文的示例将主要使用Jupyter Notebook进行交互式分析,并使用几个核心库。

基础环境:

  • 操作系统:Windows 10/11, macOS, 或 Linux (如 Ubuntu) 均可。
  • Python版本:>= 3.8。本文示例在 Python 3.9 下测试通过。
  • 包管理工具pip(通常随Python安装)。

核心Python库及版本:我们将使用以下库,请通过pip安装。

# 在终端或命令提示符中执行以下命令进行安装 pip install jieba==0.42.1 # 中文分词工具 pip install wordcloud==1.8.2.2 # 词云生成 pip install matplotlib==3.5.3 # 绘图库 pip install numpy==1.22.4 # 数值计算 pip install snownlp==0.12.3 # 中文自然语言处理库,用于情感分析 pip install streamlit==1.19.0 # 用于构建交互式Web应用(可选,用于第6节)

IDE/编辑器推荐:

  • VS Code:安装 Python 扩展和 Jupyter 扩展。
  • PyCharm:专业的 Python IDE。
  • Jupyter Lab:直接在浏览器中进行交互式编程。

项目结构建议:创建一个项目文件夹,例如pipaxing_analysis,内部结构如下:

pipaxing_analysis/ │ ├── data/ │ └── pipaxing.txt # 存放《琵琶行》纯文本 │ ├── images/ # 存放生成的图片,如词云 │ ├── notebooks/ # 存放Jupyter Notebook分析文件 │ └── 01_text_analysis.ipynb │ ├── scripts/ # 存放可执行的Python脚本 │ ├── 01_word_freq.py │ └── 02_sentiment_analysis.py │ └── app/ # 存放Streamlit应用文件(可选) └── app.py

《琵琶行》文本准备:data/pipaxing.txt文件中存入诗文全文(需去除标题、作者和注释)。确保文本编码为UTF-8。

3. 核心分析技术与原理拆解

在对《琵琶行》进行分析前,我们需要理解几个关键的NLP基础概念和对应工具的使用方法。

3.1 中文分词:从连续字符到有意义的词语

中文文本没有像英文那样的天然空格分隔,分词是第一步。jieba库是最常用的中文分词工具。

  • 原理:基于统计模型(如隐马尔可夫模型HMM)和词典,将连续的中文序列切分成一个个独立的词。
  • 关键方法
    • jieba.lcut(text): 精确模式,返回列表,适合文本分析。
    • jieba.lcut_for_search(text): 搜索引擎模式,在精确模式基础上对长词再次切分。
    • jieba.add_word(word, freq=None, tag=None): 添加自定义词典,对于古诗文中的专有名词(如“浔阳江”、“虾蟆陵”)特别有用。

示例:

import jieba text = "浔阳江头夜送客,枫叶荻花秋瑟瑟。" seg_list = jieba.lcut(text) print(seg_list) # 输出:['浔阳', '江头', '夜', '送客', ',', '枫叶', '荻花', '秋', '瑟瑟', '。']

为什么这么做?精确分词是后续词频统计、情感分析的基础。错误的分词会导致“江头”被误认为“江”和“头”,影响分析结果。

3.2 词频统计与词云生成:洞察文本焦点

词频统计是了解文本主题最直观的方法。词云则能可视化展示高频词。

  • 原理:统计分词后每个词语出现的次数,并过滤掉无实际意义的“停用词”(如“的”、“了”、“和”)。
  • 关键工具
    • collections.Counter: Python内置模块,用于高效计数。
    • wordcloud.WordCloud: 生成词云对象。
    • 停用词表:需要自己准备或从网上下载一个中文停用词表文件(stopwords.txt)。

注意事项:古诗文中的虚词(“之”、“乎”、“者”、“也”)和某些常用字(“人”、“月”)可能频率很高但信息量低,需要根据分析目标谨慎设置停用词。

3.3 情感分析:量化情感波动

情感分析旨在判断一段文本所表达的情感倾向(积极、消极、中性)。对于《琵琶行》这种情感强烈的文本,可以分析其情感变化。

  • 原理SnowNLP库基于朴素贝叶斯模型,在已标注的情感语料上训练,可以计算文本的情感极性值(sentiments),范围通常在0到1之间,越接近1表示越积极,越接近0表示越消极。
  • 局限性:通用模型对古诗文的适配性可能不佳,因为古今汉语表达差异大。但对于宏观的情感趋势分析仍有参考价值。

示例:

from snownlp import SnowNLP s1 = SnowNLP("同是天涯沦落人,相逢何必曾相识!") s2 = SnowNLP("满座重闻皆掩泣。座中泣下谁最多?江州司马青衫湿。") print(f"句子1情感值:{s1.sentiments:.3f}") # 可能输出 0.6xx, 感慨中带消极 print(f"句子2情感值:{s2.sentiments:.3f}") # 可能输出 0.1xx, 明显消极

为什么这么做?通过将全诗按句或按联分割,计算每部分的情感值并绘制折线图,可以直观看到白居易情感随叙事推进的起伏过程。

3.4 简单意象分析:发现核心意象群

意象是古诗的灵魂。我们可以通过寻找特定主题词(如自然意象:月、水、花;音乐意象:弦、声、泣)的出现位置和上下文来进行分析。

  • 原理:结合分词结果和自定义的意象词典,统计特定意象词的出现频率、分布段落,并可以结合其相邻词进行简单分析。
  • 方法:使用正则表达式或简单的字符串查找与统计。

4. 完整实战案例:《琵琶行》多维文本分析

现在,我们将结合上述技术,对《琵琶行》进行一次完整的分析。

4.1 数据加载与预处理

首先,读取文本并进行基础清洗。

# 文件路径:scripts/01_data_preprocess.py import re def load_and_clean_text(filepath): """加载文本,并移除数字、标点(保留必要句读以分析情感)等""" with open(filepath, 'r', encoding='utf-8') as f: text = f.read() # 移除诗题、作者、注释行(假设它们以数字或特殊字符开头) lines = text.split('\n') cleaned_lines = [line for line in lines if line.strip() and not re.match(r'^[0-9【】()]*$', line.strip())] full_text = '\n'.join(cleaned_lines) # 为了分词和词频,可以移除所有标点(但保留空格和换行) text_for_word_analysis = re.sub(r'[^\w\s\u4e00-\u9fff]', '', full_text) # 移除非汉字、非单词字符、非空格 # 为了情感分析,保留句读,按句分割 sentences_for_sentiment = re.split(r'[,。!?;]', full_text) sentences_for_sentiment = [s.strip() for s in sentences_for_sentiment if s.strip()] return full_text, text_for_word_analysis, sentences_for_sentiment if __name__ == "__main__": raw_text, clean_text, sentences = load_and_clean_text('../data/pipaxing.txt') print(f"原始文本行数示例:\n{raw_text[:200]}...") print(f"\n清洗后文本(用于分词):\n{clean_text[:200]}...") print(f"\n分割后的句子数:{len(sentences)}") print("前5句:", sentences[:5])

4.2 分词与词频统计

加载停用词表,进行分词和词频统计。

# 文件路径:scripts/02_word_frequency.py import jieba from collections import Counter import matplotlib.pyplot as plt # 1. 加载文本 with open('../data/pipaxing.txt', 'r', encoding='utf-8') as f: text = f.read() # 简单清洗,只保留汉字 chinese_text = re.sub(r'[^\u4e00-\u9fff]', '', text) # 2. 添加自定义词典(针对古诗文专有名词) jieba.add_word("浔阳江") jieba.add_word("虾蟆陵") jieba.add_word("善才") jieba.add_word("秋娘") jieba.add_word("青衫湿") # 3. 分词 words = jieba.lcut(chinese_text) print(f"分词总数:{len(words)}") print(f"前20个分词:{words[:20]}") # 4. 加载停用词表 def load_stopwords(filepath): with open(filepath, 'r', encoding='utf-8') as f: stopwords = [line.strip() for line in f] return set(stopwords) stopwords = load_stopwords('stopwords_cn.txt') # 你需要准备这个文件 # 可以额外添加古诗文常见虚词 extra_stopwords = {'之', '乎', '者', '也', '矣', '焉', '哉', '曰', '尔', '兮'} stopwords.update(extra_stopwords) # 5. 过滤停用词并统计词频 filtered_words = [w for w in words if w not in stopwords and len(w) > 1] # 通常单字信息量少,也过滤掉 word_freq = Counter(filtered_words) # 6. 输出最高频的20个词 top_n = 20 most_common_words = word_freq.most_common(top_n) print(f"\n出现频率最高的前{top_n}个词(二字及以上):") for word, freq in most_common_words: print(f"{word}: {freq}") # 7. 简单可视化 words_list, freqs_list = zip(*most_common_words) # 解包 plt.figure(figsize=(12, 6)) plt.bar(words_list, freqs_list) plt.title('《琵琶行》高频词统计(过滤停用词后)') plt.xlabel('词语') plt.ylabel('出现次数') plt.xticks(rotation=45) plt.tight_layout() plt.savefig('../images/word_freq_bar.png', dpi=300) plt.show()

运行结果分析:你可能会发现“琵琶”、“江州”、“司马”、“天涯”、“沦落”、“月明”等词频率很高,这直接呼应了诗的主题和核心情感。

4.3 生成词云

将词频结果可视化。

# 文件路径:scripts/03_wordcloud_gen.py from wordcloud import WordCloud import matplotlib.pyplot as plt # 从上一节的 word_freq 继续 # word_freq 是一个 Counter 对象 # 生成词云,设置字体路径(否则中文乱码) font_path = 'SimHei.ttf' # 你需要指定一个系统中文字体路径,如‘C:/Windows/Fonts/simhei.ttf’ wc = WordCloud( font_path=font_path, width=800, height=600, background_color='white', max_words=100, contour_width=1, contour_color='steelblue' ).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('../images/wordcloud.png', dpi=300, bbox_inches='tight') plt.show()

4.4 情感趋势分析

按诗句分析全诗情感走向。

# 文件路径:scripts/04_sentiment_analysis.py from snownlp import SnowNLP import matplotlib.pyplot as plt import numpy as np # 使用 4.1 节中分割好的 sentences 列表 # sentences = [...] sentiment_values = [] valid_sentences = [] for sent in sentences: if len(sent) < 2: # 过滤过短的句子 continue try: s = SnowNLP(sent) # SnowNLP的情感分析对古文可能不准,这里主要看趋势 sentiment_values.append(s.sentiments) valid_sentences.append(sent) except Exception as e: print(f"分析句子 '{sent}' 时出错:{e}") continue print(f"成功分析了 {len(sentiment_values)} 个句子的情感。") # 绘制情感趋势图 plt.figure(figsize=(15, 6)) x = np.arange(len(sentiment_values)) plt.plot(x, sentiment_values, marker='o', linestyle='-', linewidth=1, markersize=4) plt.axhline(y=0.5, color='r', linestyle='--', alpha=0.5, label='中性线 (0.5)') plt.title('《琵琶行》句子情感值变化趋势', fontsize=14) plt.xlabel('句子序列') plt.ylabel('情感值 (越接近1越积极)') plt.grid(True, alpha=0.3) plt.legend() plt.tight_layout() # 在关键位置添加注释(需要手动根据诗句内容判断) # 例如,找到情感值最低点的句子 min_idx = np.argmin(sentiment_values) plt.annotate(f'最低点: {valid_sentences[min_idx][:10]}...', xy=(min_idx, sentiment_values[min_idx]), xytext=(min_idx, sentiment_values[min_idx]-0.1), arrowprops=dict(arrowstyle='->'), fontsize=9) plt.savefig('../images/sentiment_trend.png', dpi=300) plt.show() # 输出情感最积极和最消极的几句 print("\n=== 情感最积极的5句(SnowNLP判断)===") sorted_positive = sorted(zip(sentiment_values, valid_sentences), reverse=True)[:5] for val, sent in sorted_positive: print(f"[{val:.3f}] {sent}") print("\n=== 情感最消极的5句(SnowNLP判断)===") sorted_negative = sorted(zip(sentiment_values, valid_sentences))[:5] for val, sent in sorted_negative: print(f"[{val:.3f}] {sent}")

结果解读:虽然SnowNLP对古文的判断绝对数值可能不准,但趋势图能清晰展示情感低谷(如琵琶女自述身世、诗人感慨自身遭遇时)和短暂的高峰(如初闻琵琶时的惊喜)。这印证了诗歌情感结构的起伏。

4.5 意象分析示例:寻找“月”与“水”

我们手动分析诗中的核心意象。

# 文件路径:scripts/05_imagery_analysis.py import re # 使用原始文本 with open('../data/pipaxing.txt', 'r', encoding='utf-8') as f: full_text = f.read() # 定义意象关键词 imagery_dict = { '月': ['月', '明月', '秋月', '江月', '月明'], '水': ['水', '江', '河', '海', '流', '浪', '波', '浔阳江', '江水'], '音乐': ['琵琶', '弦', '声', '音', '乐', '嘈嘈', '切切', '幽咽'], '悲情': ['泣', '哭', '泪', '湿', '掩泣', '青衫湿', '沦落', '天涯'] } # 统计意象词出现次数 for category, keywords in imagery_dict.items(): count = 0 found_phrases = [] for kw in keywords: # 使用正则表达式查找,避免部分匹配 pattern = re.compile(kw) matches = pattern.findall(full_text) count += len(matches) if matches: found_phrases.extend([kw] * len(matches)) # 记录匹配到的词 print(f"意象类别【{category}】出现总次数:{count}") if found_phrases: # 统计该类别下哪个词出现最多 from collections import Counter freq = Counter(found_phrases) print(f" 主要构成:{freq.most_common(3)}") print("-" * 40) # 查找“月”出现的上下文 print("\n=== ‘月’意象出现的位置及上下文 ===") lines = full_text.split('\n') for i, line in enumerate(lines): if '月' in line: # 显示该行及前后一行 start = max(0, i-1) end = min(len(lines), i+2) context = '\n'.join(lines[start:end]) print(f"第{i+1}行附近:\n{context}\n{'-'*60}")

这个分析能直观展示“月”作为核心意象,如何贯穿全诗,渲染了孤寂、清冷的氛围。

5. 常见问题与排查思路

在实践上述分析过程中,你可能会遇到以下问题:

问题现象常见原因解决思路
jieba分词结果不准确,专有名词被切散默认词典未收录古诗文专有名词使用jieba.add_word()手动添加词汇,或加载自定义词典文件。
词云图显示乱码(方框)未指定正确的中文字体路径WordCloud初始化时设置font_path参数,指向系统内的中文字体文件(如‘SimHei.ttf’)。
SnowNLP情感分析结果异常,所有值接近0.51. 句子过短或不含情感词。
2. 模型对古文不适应。
1. 过滤掉过短句子。
2. 重点观察相对趋势而非绝对数值。
3. 考虑使用针对古诗词训练的情感词典(如BosonNLP情感词典)进行基于规则的分析。
停用词过滤后,高频词仍包含很多无意义单字停用词表未包含古诗文虚词,或过滤时未排除单字1. 扩充停用词表,加入“之乎者也矣焉哉”等。
2. 在统计词频时,通过len(w) > 1条件过滤掉单字词。
运行脚本时提示ModuleNotFoundError未安装所需Python库,或不在正确的虚拟环境中1. 使用pip list检查库是否安装。
2. 在终端使用pip install -r requirements.txt一次性安装所有依赖(需先创建requirements文件)。
文本文件读取时编码错误 (UnicodeDecodeError)文件保存的编码不是UTF-81. 用记事本或代码编辑器(如VS Code)将文件另存为UTF-8编码。
2. 尝试使用encoding='gbk'encoding='gb2312'(如果文件是GBK编码)。

6. 最佳实践与工程建议

将一次性的分析脚本转化为更稳健、可复用的项目,需要考虑以下工程化实践:

  1. 配置与路径管理

    • 不要将文件路径硬编码在代码中。使用配置文件(如config.yaml)或通过命令行参数传递。
    • 使用os.path.join()pathlib.Path来构建路径,保证跨平台兼容性。
    from pathlib import Path DATA_DIR = Path(__file__).parent / 'data' text_file = DATA_DIR / 'pipaxing.txt'
  2. 代码模块化

    • 将不同的功能封装成函数或类。例如,创建TextAnalyzer类,包含load_data,clean_text,calculate_word_freq,plot_sentiment等方法。
    • 将工具函数(如停用词加载)放在独立的utils.py模块中。
  3. 数据持久化

    • 将中间分析结果(如词频字典、情感值列表)保存为JSON或Pickle文件,避免每次重新计算。
    import json with open('word_freq.json', 'w', encoding='utf-8') as f: json.dump(dict(word_freq), f, ensure_ascii=False, indent=2)
  4. 构建交互式应用(可选进阶)

    • 使用Streamlit可以快速将分析结果构建成一个Web应用,方便非技术用户交互探索。
    # 文件路径:app/app.py import streamlit as st import pandas as pd from scripts.word_frequency import analyze_word_freq # 假设你的分析函数已模块化 st.title('《琵琶行》交互式赏析分析仪') uploaded_file = st.file_uploader("上传你的《琵琶行》文本文件", type=['txt']) if uploaded_file: text = uploaded_file.read().decode('utf-8') if st.button('开始分析'): word_freq_df = analyze_word_freq(text) # 返回一个DataFrame st.subheader('高频词表') st.dataframe(word_freq_df.head(20)) # 可以继续添加词云、情感图等组件
  5. 分析结果的批判性审视

    • 始终记住,工具是辅助。SnowNLP的情感分析结果需要结合诗歌背景人工校验。
    • 词频统计的高频词需要结合停用词表的设计来解读,避免过度解读。
    • 最好的分析是“人文解读”与“数据验证”相结合。
  6. 扩展方向

    • 更高级的NLP模型:尝试使用BERTRoBERTa等预训练模型进行更深度的情感分析或文本分类(需微调)。
    • 关系图谱:利用NetworkX库,基于词共现关系,绘制诗中人物、地点、意象之间的关系网络图。
    • 风格对比:分析白居易其他诗作(如《长恨歌》),与《琵琶行》进行用词、情感风格的对比。

通过这样一个从文本处理到可视化,再到简单应用构建的完整流程,我们不仅重温了《琵琶行》的文学魅力,更实践了一套可复用的文本数据分析方法论。这不仅能用于古诗文,也能迁移到现代文本的分析中,为你的数据分析或人文计算项目打下基础。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询