接下来,我们将学习如何使用jieba模块来实现古典名著《西游记》的分词,并且会将书中重点人物出场次数以图形化的方式显示出来,并进一步创建一个词云图。
17.4.1 读取文件
因为小说《西游记》的内容非常长,我们不太可能会把它放到一个字符串中来操作,所以我们需要它保存在一个文件中。那么我们就需要操作整个文件,把文件中的内容读取出来。我们操作文件的流程是:
1.打开文件,得到文件句柄并赋值给一个变量;
2.通过句柄对文件进行操作;
3.关闭文件。
打开文件就要用到open()函数。其实,我们在第11章中详细介绍了打开文件的方法,读者如果忘了的话,可以再次查阅11.1节回顾一下。
17.4.2 《西游记》的分词
在前面,我们已经介绍了如何使用jieba库分词,以及如何打开一个文本文件。接下来,我们要对经典小说《西游记》进行分词,并且把出现频率最高的词语展示出来。首先,把《西游记》保存到一个文本文件中,要注意的是,保存文件的时候,要将编码格式选择为UTF-8,否则读取文件的时候会报错。此外,我们要把这个文本文件放到和程序代码所在位置相同的文件夹中,这样就不需要指定路径了。
读者可以从本书配套源代码和文件中获取整个文本文件,如图17-5所示。
![16983581e629287cfc3d7b1b3dc1af3f.png](https://i-blog.csdnimg.cn/blog_migrate/b4a9f0ec9d38ed218713faec5f011b0c.jpeg)
图17-5
我们先来看一下用于分词的程序代码,代码参见ch1717.2.py。
import jiebadef takeSecond(elem): return elem[1]def main(): path = "西游记.txt" file = open(path,"r",encoding="utf-8") text=file.read() file.close() words = jieba.lcut(text) counts = {} for word in words: counts[word] = counts.get(word,0) + 1 items = list(counts.items()) items.sort(key = takeSecond,reverse=True) for i in range(20): item=items[i] keyWord =item[0] count=item[1] print("{0:<10}{1:>5}".format(keyWord,count))main()
因为要使用jieba的函数,所以这里首先需要导入jieba模块。
import jieba
接下来,我们定义了两个函数:main(主体函数)和takeSecond(用于获取列表的第2个元素)。然后,定义了变量path来保存相对路径。使用open()函数以只读方式打开文本文件“西游记.txt”,指定的编码方式是UTF-8,并且将文件句柄赋值给变量file。随后调用read()方法读取文件中的内容并保存到变量text中。调用close()方法关闭文件。
然后我们使用jieba.lcut()方法对变量text中的内容进行分词,并且把分词的结果列表保存到变量words中。我们新建一个叫作counts的字典。然后,通过一个循环语句,遍历列表words中的每个元素,用变量word来表示每个元素。在循环中,把word作为字典counts的键,把get()方法返回的值加上1,作为这个键所对应的值。这表示每次遇到同样的键,都会让它的值加上1(以统计相同的键的数目)。需要注意,如果在字典中没有找到键所对应的值,那么get()方法会返回默认值0。当循环结束后,字典counts就包含了西游记中拆分出来的全部词语以及对应的该词语出现的次数。
接下来,我们想要按照词的出现次数排序。第4章介绍字典的时候曾经提到,字典是没有办法排序的,我们需要把字典转换为列表,然后利用列表的sort()方法来排序。因为我们是使用人物的出现次数来排序的,所以要给sort()方法传递一个key参数,以指定用来进行比较的元素,该元素就是取自于可迭代对象中。这里调用了自定义的takeSecond()函数。这个函数接收的参数是一个列表,返回的是这个列表的第2个元素。这样,我们就可以指定第2个元素进行逆序排序,并且把结果赋值给items。
然后,借助range()函数生成一个等差数组,展示items中前20个元素。在每次循环中,我们先把获取的元素赋值给变量item。然后把item的第1个列表元素赋值给变量keyWord,第2个元素赋值给变量count。然后使用print()方法把格式化后的两个变量输出到屏幕上。这里我们用到了format()方法,它可以按照需求来格式化字符串。代码的含义是把keyWord的值左对齐,宽度是10;把count的值右对齐&#