Python jieba分词实例:对《西游记》进行分词(下)

上节教程我们已经介绍过,西游记中的有些词组对理解西游记没有什么帮助。本节,我们会介绍如何去除这类不需要的词语。

去除不需要的词语

其实,人名的词语对于分析小说剧情和主人公是最有帮助的,所以我们还要进一步优化程序,将不需要的词语进行过滤。

具体代码如下所示,新增代码还是突出显示。
import jieba
def 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:
    if len(word) == 1:
        continue   
    else:
        counts[word] = counts.get(word,0) + 1
    file = open("excludes.txt","r")
    excludes =file.read().split(",")
    file.close
    for delWord in excludes:
        try:
            del counts[delWord]
        except:
            continue
    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()

这里介绍一下突出显示的代码的含义。我们把想要从高频词语结果中去除的词组放到一个叫作 excludes.txt 的文本文件中。可以从上节的运行结果中进行筛选,从而得到这些词。

读取这个文件,并且对读取内容调用 split 方法,以“,”(逗号)作为分隔符,将结果赋值给一个叫作 excludes 的列表。现在 excludes 列表中的元素就是我们在上节中想要从高频词语结果中去除的词组。

接下来,通过一个新的 for 循环遍历列表 excludes 中的元素,把每个元素赋值给变量delWord。在循环体中,使用 del 语句,将字典 counts 中的键为 delWord 的键—值对删除。

这里需要注意一下,如果字典中不包含所要删除的键,程序会报错。所以我们用到了异常处理的语句,当出现异常后,在 except 语句中使用 continue 语句跳转到下一次循环。

运行程序,得到的词频统计结果如图 1 所示。

Python jieba去除不需要的词语
图 1

现在得到的结果已经把不需要的词组都去掉了。但是,我们发现结果还是有些瑕疵,因为“行者”“大圣”“老孙”和“悟空”都是指的“孙悟空”,而分开统计显然是不妥的。下面,我们会介绍如何将同一个人名进行合并。

合并人名

从前面的词频统计结果可知,输出的结果中存在同一个人的多个称呼的词语。所以我们会进一步优化程序,将同一个人名的不同称呼进行合并。

具体代码如下所示,新增代码突出显示出来了。
import jieba
def 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:
        if len(word) == 1:
            continue   
        elif word == "大圣" or word=="老孙" or word=="行者" or word=="孙大圣" or word=="孙行者" or word=="猴王" or word=="悟空" or word=="齐天大圣" or word=="猴子":
            rword = "孙悟空"
        elif word == "师父" or word == "三藏" or word=="圣僧":
            rword = "唐僧"
        elif word == "呆子" or word=="八戒" or word=="老猪":
            rword = "猪八戒"
        elif word=="沙和尚":
            rword="沙僧"
        elif word == "妖精" or word=="妖魔" or word=="妖道":
            rword = "妖怪"
        elif word=="佛祖":
            rword="如来"
        elif word=="三太子":
            rword="白马"
        else:
            rword = word
        counts[rword] = counts.get(rword,0) + 1
    file = open("excludes.txt","r")
    excludes =file.read().split(",")
    file.close
    for delWord in excludes:
        try:
            del counts[delWord]
        except:
            continue
    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()

来看一下新增代码含义。这里新建了一个变量 rword,用它代替 word 作为字典 counts 的键。我们会将同一个人但是有多个称谓的词语变量 word,重新赋值给变量 rword。

然后,将 rword 作为字典 counts 的键,将其出现次数作为值。例如,我们知道“师傅”“三藏”和“圣僧”都是对“唐僧”的尊称,所以我们可以这些词归类为唐僧。其他几个人物也都有重复的称谓,处理方法都是类似的。

运行程序,得到的词频统计结果如图 2 所示。

合并人名
图 2

现在,我们就可以得到《西游记》里出现最多的词语,其中“孙悟空”出现了 6639 次,是当之无愧的主角,紧随其后的是“唐僧”和“猪八戒”。作为各类反派的统称“妖怪”排名第四。“沙僧”位列第五,属于师徒四人中存在感最低的。这个统计结果和我们平常对《西游记》的认知是完全符合的。

从图 2 显示,现在得到的这个结果太不直观了,如果你想更直观的看到结果,我们将在下节详细介绍。