在文本分析领域,Python 是功能强大且常用的工具。借助 jieba
库进行中文分词,再结合 fitz
库读取 PDF 文件、wordcloud
库生成词云图,我们可以对《西游记》这样的文学作品开展人物统计并生成直观的词云图。下面会对代码中的各个函数展开详细解析。
1. 导入必要的库
python
import jieba
import fitz
from wordcloud import WordCloud
import matplotlib.pyplot as plt
jieba
:它是专门用于中文分词的库,能把文本准确地拆分成单个词语,为后续的词频统计做准备。fitz
:属于 PyMuPDF 库的别名,其作用是读取 PDF 文件,将其中的文本内容提取出来。WordCloud
:用于生成词云图,能依据词频把词语以不同大小的字体展示在图中。matplotlib.pyplot
:用来展示生成的词云图,提供了便捷的可视化功能。
2. 词云生成函数 createWordCloud
python
def createWordCloud(items):
word_freq = {name: count for name, count in items}
font_path = 'simhei.ttf' # 按需修改字体路径
wc = WordCloud(
font_path=font_path,
background_color='white',
width=500,
height=300,
max_font_size=100,
margin=1,
relative_scaling=0.4,
scale=3,
prefer_horizontal=0.8
)
wordcloud = wc.generate_from_frequencies(word_freq)
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis('off')
plt.show()
- 功能:依据输入的词语及其词频生成词云图并展示。
- 参数:
items
是一个包含词语和对应词频的元组列表。 - 实现步骤:
- 把
items
转换为字典word_freq
,键为词语,值为词频。 - 指定字体路径
font_path
,这里默认使用simhei.ttf
,可根据需求修改。 - 创建
WordCloud
对象wc
,并设置一系列参数,像背景颜色、宽度、高度、最大字体大小等。 - 调用
generate_from_frequencies
方法,依据词频生成词云图。 - 利用
matplotlib.pyplot
展示词云图,同时关闭坐标轴显示。
- 把
3. 辅助排序函数 takeSecond
python
def takeSecond(elem):
return elem[1]
- 功能:返回元素的第二个值,在后续排序操作中作为排序的依据。
- 参数:
elem
是一个元组。 - 返回值:元组的第二个元素。
4. PDF 文本提取函数 extract_text_from_pdf
python
def extract_text_from_pdf(path):
doc = fitz.open(path)
text = ""
for page in doc:
text += page.get_text()
return text
- 功能:从指定路径的 PDF 文件中提取文本内容。
- 参数:
path
是 PDF 文件的路径。 - 实现步骤:
- 用
fitz.open
打开 PDF 文件,得到文档对象doc
。 - 遍历文档的每一页,调用
page.get_text
方法提取文本,并累加到字符串text
中。 - 返回提取的文本。
- 用
5. 文本处理与词频统计函数 process_text
python
def process_text(text):
words = jieba.lcut(text)
counts = {}
# 角色名称合并
role_mapping = {
"孙悟空": ["大圣", "老孙", "行者", "猴王", "悟空", "猴子"],
"唐僧": ["师父", "三藏", "圣僧", "玄奘"],
"猪八戒": ["呆子", "八戒", "老猪"],
"沙僧": ["沙和尚"],
"妖怪": ["妖精", "妖魔", "妖道"],
"如来": ["佛祖"],
"白马": ["三太子"]
}
# 使用字典推导式生成同义词映射
synonym_map = {alias: role for role, aliases in role_mapping.items() for alias in aliases}
for word in words:
if len(word) == 1:
continue
rword = synonym_map.get(word, word)
counts[rword] = counts.get(rword, 0) + 1
return counts
- 功能:对输入的文本进行分词处理,统计词频,同时合并同义词。
- 参数:
text
是待处理的文本。 - 实现步骤:
- 用
jieba.lcut
对文本进行分词,得到词语列表words
。 - 创建空字典
counts
用于存储词频。 - 定义
role_mapping
字典,将同义词映射到统一的名称。 - 使用字典推导式生成
synonym_map
,键为同义词,值为统一名称。 - 遍历词语列表
words
,过滤掉单个字符的词语。 - 对于每个词语,通过
synonym_map
查找其统一名称rword
,若不存在则使用原词。 - 更新
counts
字典中该词语的词频。 - 返回词频统计结果。
- 用
6. 过滤排除词函数 filter_excluded_words
python
def filter_excluded_words(counts):
file = open("excludes.txt", "r", encoding='utf-8')
excludes = file.read().split(",")
file.close # 保持原始实现方式
for word in excludes:
if word in counts:
del counts[word]
- 功能:从词频统计结果中过滤掉指定的排除词。
- 参数:
counts
是词频统计结果的字典。 - 实现步骤:
- 打开
excludes.txt
文件,以 UTF - 8 编码读取其中的内容。 - 按中文逗号分割文件内容,得到排除词列表
excludes
。 - 遍历
excludes
列表,若某个排除词存在于counts
字典中,则将其删除。
- 打开
7. 排序并输出结果函数 sort_and_print_results
python
def sort_and_print_results(counts, top_n=15):
items = list(counts.items())
items.sort(key=takeSecond, reverse=True)
print("频率TOP{}词汇:".format(top_n))
for i in range(top_n):
item = items[i]
print("{0:<10}{1:>5}".format(item[0], item[1]))
return items[:top_n]
- 功能:对词频统计结果进行排序,输出前
top_n
个高频词语及其词频,并返回这些词语及其词频的列表。 - 参数:
counts
是词频统计结果的字典。top_n
是要输出的高频词语数量,默认为 15。
- 实现步骤:
- 将
counts
字典转换为元素为元组的列表items
。 - 使用
sort
方法对items
列表进行排序,排序依据是每个元组的第二个元素(词频),按降序排列。 - 打印前
top_n
个高频词语及其词频。 - 返回前
top_n
个高频词语及其词频的列表。
- 将
8. 主流程函数 main
python
def main():
path = '西游记.pdf'
text = extract_text_from_pdf(path)
counts = process_text(text)
filter_excluded_words(counts)
top_items = sort_and_print_results(counts)
createWordCloud(top_items)
if __name__ == "__main__":
main()
- 功能:整合上述函数,完成从 PDF 文件提取文本、文本处理、词频统计、过滤排除词、排序输出结果以及生成词云图的整个流程。
- 实现步骤:
- 指定 PDF 文件的路径
path
。 - 调用
extract_text_from_pdf
函数提取 PDF 文本。 - 调用
process_text
函数对文本进行处理并统计词频。 - 调用
filter_excluded_words
函数过滤排除词。 - 调用
sort_and_print_results
函数排序并输出前top_n
个高频词语及其词频。 - 调用
createWordCloud
函数生成并展示词云图。
- 指定 PDF 文件的路径
通过上述一系列函数,我们可以轻松地对《西游记》的 PDF 文本进行分析,统计人物出现的频率并生成直观的词云图
最后输出: