《水浒传》一百零八将名字在原著中的出现频率

这两天偶然发现斗鱼的电视剧频道在放 2011 版的《水浒传》电视剧,刚好是三打祝家庄的那几集,拼命三郎石秀和锦豹子杨林在祝家庄做细作探路。我很早就知道拼命三郎石秀是作者施耐庵的亲儿子之一,突然萌生了统计一百零八将的名字在《水浒传》书里的具体出现次数的想法。这个可以反映出一百零八将中哪些角色是作者施耐庵着重用笔墨描写的,哪些角色是可有可无的。

2011 版《水浒传》全体演员合影

我在 Gutenberg 上找到了《水浒传》繁体版的电子书,然后写了一个简单的 Python 脚本进行统计,以下是统计结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
001 天魁星 呼保義   宋江  : 1868
014 天傷星 行者 武松 : 925
022 天殺星 黑旋風 李逵 : 628
006 天雄星 豹子頭 林沖 : 618
020 天速星 神行太保 戴宗 : 400
003 天機星 智多星 吳用 : 387
017 天暗星 青面獸 楊志 : 308
033 天慧星 拼命三郎 石秀 : 295
009 天英星 小李廣 花榮 : 260
008 天威星 雙鞭 呼延灼: 218
032 天牢星 病關索 楊雄 : 218
023 天微星 九紋龍 史進 : 210
012 天滿星 美髯公 朱仝 : 203
002 天罡星 玉麒麟 盧俊義: 196
007 天猛星 霹靂火 秦明 : 196
010 天貴星 小旋風 柴進 : 194
013 天孤星 花和尚 魯智深: 178
025 天退星 插翅虎 雷橫 : 176
030 天損星 浪裏白條 張順 : 175
004 天閒星 入雲龍 公孫勝: 156
005 天勇星 大刀 關勝 : 134
021 天異星 赤髮鬼 劉唐 : 134
107 地賊星 鼓上蚤 時遷 : 122
092 地囚星 旱地忽律 朱貴 : 121
085 地伏星 金眼彪 施恩 : 114
018 天佑星 金鎗手 徐寧 : 111
038 地煞星 鎮三山 黃信 : 103
039 地勇星 病尉遲 孫立 : 88
050 地強星 錦毛虎 燕順 : 88
011 天富星 撲天鵰 李應 : 84
026 天壽星 混江龍 李俊 : 82
051 地暗星 錦豹子 楊林 : 81
016 天捷星 沒羽箭 張清 : 79
034 天暴星 兩頭蛇 解珍 : 75
015 天立星 雙鎗將 董平 : 71
088 地孤星 金錢豹子 湯隆 : 71
019 天空星 急先鋒 索超 : 69
036 天巧星 浪子 燕青 : 69
037 地魁星 神機軍師 朱武 : 68
102 地刑星 菜園子 張青 : 68
035 天哭星 雙尾蠍 解寶 : 66
099 地醜星 石將軍 石勇 : 66
106 地耗星 白日鼠 白勝 : 66
101 地陰星 母大蟲 顧大嫂: 63
027 天劍星 立地太歲 阮小二: 58
031 天敗星 活閻羅 阮小七: 57
028 天平星 船火兒 張橫 : 54
063 地狂星 獨火星 孔亮 : 54
083 地妖星 摸著天 杜遷 : 53
086 地僻星 打虎將 李忠 : 53
100 地數星 小尉遲 孫新 : 52
024 天究星 沒遮攔 穆弘 : 51
054 地佐星 小溫侯 呂方 : 50
029 天罪星 短命二郎 阮小五: 49
077 地樂星 鐵叫子 樂和 : 49
040 地傑星 醜郡馬 宣贊 : 48
055 地佑星 賽仁貴 郭盛 : 48
072 地周星 跳澗虎 陳達 : 48
094 地平星 鐵臂膊 蔡福 : 47
042 地威星 百勝將軍 韓滔 : 45
082 地魔星 雲裏金剛 宋萬 : 45
089 地全星 鬼臉兒 杜興 : 44
076 地俊星 鐵扇子 宋清 : 42
087 地空星 小霸王 周通 : 42
062 地猖星 毛頭星 孔明 : 41
048 地闢星 摩雲金翅 歐鵬 : 40
049 地闔星 火眼狻猊 鄧飛 : 40
081 地羈星 操刀鬼 曹正 : 40
043 地英星 天目將 彭圯 : 37
073 地隱星 白花蛇 楊春 : 37
084 地幽星 病大蟲 薛永 : 36
090 地短星 出林龍 鄒淵 : 36
056 地靈星 神醫 安道全: 35
041 地雄星 井木犴 郝思文: 34
093 地藏星 笑面虎 朱富 : 34
097 地察能 青眼虎 李雲 : 34
103 地壯星 母夜叉 孫二娘: 33
067 地明星 鐵笛仙 馬麟 : 32
096 地奴星 催命判官 李立 : 31
046 地文星 聖手書生 蕭讓 : 30
074 地異星 白面郎君 鄭天壽: 30
044 地奇星 聖水將軍 單廷珪: 29
045 地猛星 神火將軍 魏定國: 29
064 地飛星 八臂哪吒 項充 : 29
052 地輔星 轟天雷 凌振 : 28
061 地默星 混世魔王 樊瑞 : 28
104 地劣星 活閃婆 王定六: 28
065 地走星 飛天大聖 李袞 : 27
068 地進星 出洞蛟 童威 : 25
066 地巧星 玉臂匠 金大堅: 23
069 地退星 翻江蜃 童猛 : 23
071 地遂星 通臂猿 侯健 : 23
080 地鎮星 小遮攔 穆春 : 22
105 地健星 險道神 郁保四: 21
047 地正星 鐵面孔目 裴宣 : 20
095 地損星 一枝花 蔡慶 : 19
079 地速星 中箭虎 丁得孫: 17
108 地狗星 金毛犬 段景住: 17
058 地微星 矮腳虎 王英 : 16
059 地慧星 一丈青 扈三娘: 16
078 地捷星 花項虎 龔旺 : 16
060 地暴星 喪門神 鮑旭 : 11
098 地惡星 沒面目 焦挺 : 11
070 地滿星 玉旛竿 孟康 : 10
075 地理星 九尾龜 陶宗旺: 10
053 地會星 神算子 蔣敬 : 9
057 地獸星 紫髯伯 皇甫端: 8
091 地角星 獨角龍 鄒潤 : 4

这个统计结果有令我感到意外的地方,但是绝大多数将领的统计及排名是符合我的预期的。

在高顺位里,梁山泊大哥呼保义宋江肯定是名字出现次数最多,笔墨用的最多的人物。豹子头林冲名字出现次数居然不是第二,我是比较惊讶的。但是看到第二是行者武松,我觉得又很合理。宋江的铁跟班黑旋风李逵名字出现次数第三没啥争议,毕竟宋江在哪他就在哪。神行太保戴宗的名字出现次数居然高居第五,这个也是没想到的。座次第三十三名的施耐庵亲儿子拼命三郎石秀,因为做事是真的拼命,深得作者和大家喜欢,在名字出现次数的排名高居第八位。甚至天天跟石秀混在一起的病关索杨雄的名字出现次数排名也高居第十一位。大家比较熟知和喜欢的花和尚鲁智深,即便在原著中出场很早,他的名字出现次数也只有在第十七位,其可能原因在后面会提到。

在低顺位里,什么神算子蒋敬,轰天雷凌振,紫髯伯皇甫端,独角龙邹润,的确是可有可无毫无存在感的。另外,大家比较熟悉的矮脚虎王英和一丈青扈三娘夫妇居然也是倒数的,这个也比较令人诧异。

接着我们再看看三十六天罡里谁是低顺位的。阮氏三兄弟,船火儿张横,都是水军相关的将领,也可以理解。还有一个不知道怎么能混上天罡的地痞恶霸没遮拦穆弘,这个也没毛病。

最后再看看七十二地煞里谁是高顺位的。神偷鼓上蚤时迁实至名归。但是旱地忽律朱贵,金眼彪施恩这两个开酒店的居然顺位也很高,我就想不明白了。

要注意的一点是,名字出现次数并不能毫无误差的反映作者对该角色的用笔墨的程度。比如说,豹子头林冲在书中也可能以林教头的称呼出现,鲁智深出家之前的名字鲁达就没有被统计,黑旋风李逵在书中也可能以铁牛的称呼出现。但相对来说,名字出现次数和作者对该角色的用笔墨的程度是正相关的。

下面是可以用来重复上述结果的 Python 脚本。

bro_count.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import urllib.request

# Download the text file
url = "https://www.gutenberg.org/files/23863/23863-0.txt"
response = urllib.request.urlopen(url)
data = response.read()

# Open the text file in memory
content = data.decode('utf-8')

heroes = [
'宋江', '盧俊義', '吳用', '公孫勝', '關勝', '林沖', '秦明', '呼延灼', '花榮', '柴進', '李應', '朱仝',
'魯智深', '武松', '董平', '張清', '楊志', '徐寧', '索超', '戴宗', '劉唐', '李逵', '史進', '穆弘',
'雷橫', '李俊', '阮小二', '張橫', '阮小五', '張順', '阮小七', '楊雄', '石秀', '解珍', '解寶', '燕青',
'朱武', '黃信', '孫立', '宣贊', '郝思文', '韓滔', '彭圯', '單廷珪', '魏定國', '蕭讓', '裴宣', '歐鵬',
'鄧飛', '燕順', '楊林', '凌振', '蔣敬', '呂方', '郭盛', '安道全', '皇甫端', '王英', '扈三娘', '鮑旭',
'樊瑞', '孔明', '孔亮', '項充', '李袞', '金大堅', '馬麟', '童威', '童猛', '孟康', '侯健', '陳達',
'楊春', '鄭天壽', '陶宗旺', '宋清', '樂和', '龔旺', '丁得孫', '穆春', '曹正', '宋萬', '杜遷', '薛永',
'施恩', '李忠', '周通', '湯隆', '杜興', '鄒淵', '鄒潤', '朱貴', '朱富', '蔡福', '蔡慶', '李立',
'李雲', '焦挺', '石勇', '孫新', '顧大嫂', '張青', '孫二娘', '王定六', '郁保四', '白勝', '時遷', '段景住'
]

nicknames = [
'呼保義', '玉麒麟', '智多星', '入雲龍', '大刀', '豹子頭', '霹靂火', '雙鞭', '小李廣', '小旋風', '撲天鵰',
'美髯公', '花和尚', '行者', '雙鎗將', '沒羽箭', '青面獸', '金鎗手', '急先鋒', '神行太保', '赤髮鬼',
'黑旋風', '九紋龍', '沒遮攔', '插翅虎', '混江龍', '立地太歲', '船火兒', '短命二郎', '浪裏白條', '活閻羅',
'病關索', '拼命三郎', '兩頭蛇', '雙尾蠍', '浪子', '神機軍師', '鎮三山', '病尉遲', '醜郡馬', '井木犴',
'百勝將軍', '天目將', '聖水將軍', '神火將軍', '聖手書生', '鐵面孔目', '摩雲金翅', '火眼狻猊', '錦毛虎',
'錦豹子', '轟天雷', '神算子', '小溫侯', '賽仁貴', '神醫', '紫髯伯', '矮腳虎', '一丈青', '喪門神',
'混世魔王', '毛頭星', '獨火星', '八臂哪吒', '飛天大聖', '玉臂匠', '鐵笛仙', '出洞蛟', '翻江蜃', '玉旛竿',
'通臂猿', '跳澗虎', '白花蛇', '白面郎君', '九尾龜', '鐵扇子', '鐵叫子', '花項虎', '中箭虎', '小遮攔',
'操刀鬼', '雲裏金剛', '摸著天', '病大蟲', '金眼彪', '打虎將', '小霸王', '金錢豹子', '鬼臉兒', '出林龍',
'獨角龍', '旱地忽律', '笑面虎', '鐵臂膊', '一枝花', '催命判官', '青眼虎', '沒面目', '石將軍', '小尉遲',
'母大蟲', '菜園子', '母夜叉', '活閃婆', '險道神', '白日鼠', '鼓上蚤', '金毛犬'
]

stars = [
'天魁星', '天罡星', '天機星', '天閒星', '天勇星', '天雄星', '天猛星', '天威星', '天英星', '天貴星',
'天富星', '天滿星', '天孤星', '天傷星', '天立星', '天捷星', '天暗星', '天佑星', '天空星', '天速星',
'天異星', '天殺星', '天微星', '天究星', '天退星', '天壽星', '天劍星', '天平星', '天罪星', '天損星',
'天敗星', '天牢星', '天慧星', '天暴星', '天哭星', '天巧星', '地魁星', '地煞星', '地勇星', '地傑星',
'地雄星', '地威星', '地英星', '地奇星', '地猛星', '地文星', '地正星', '地闢星', '地闔星', '地強星',
'地暗星', '地輔星', '地會星', '地佐星', '地佑星', '地靈星', '地獸星', '地微星', '地慧星', '地暴星',
'地默星', '地猖星', '地狂星', '地飛星', '地走星', '地巧星', '地明星', '地進星', '地退星', '地滿星',
'地遂星', '地周星', '地隱星', '地異星', '地理星', '地俊星', '地樂星', '地捷星', '地速星', '地鎮星',
'地羈星', '地魔星', '地妖星', '地幽星', '地伏星', '地僻星', '地空星', '地孤星', '地全星', '地短星',
'地角星', '地囚星', '地藏星', '地平星', '地損星', '地奴星', '地察能', '地惡星', '地醜星', '地數星',
'地陰星', '地刑星', '地壯星', '地劣星', '地健星', '地耗星', '地賊星', '地狗星'
]

assert len(heroes) == 108
assert len(nicknames) == 108
assert len(stars) == 108

hero_to_index = {heroes[i]: i for i in range(len(heroes))}

hero_freqs = [0 for _ in range(len(heroes))]
for hero in heroes:
hero_freqs[hero_to_index[hero]] = content.count(hero)

hero_index_sorted = [
i
for i, _ in sorted(enumerate(hero_freqs), key=lambda x: x[1], reverse=True)
]

for index in hero_index_sorted:
print(f"{index + 1:0>3} "
f"{stars[index]} "
f"{nicknames[index].ljust(8 - len(nicknames[index]))} "
f"{heroes[index].ljust(6 - len(heroes[index]))}: "
f"{hero_freqs[index]}")

如果要克服上述提到的一些统计的问题,可能就要用到对《水浒传》的 tokenization,对每个 token 进行单独统计,然后对人物名称的 token 进行归类,这样,像鲁智深,鲁提辖,鲁达之类的称呼都会归到一个人物下。

具体做起来的话,可能可以用一个 pre-trained 的 Language 模型,对《水浒传》进行 finetune,允许更新 token 的 embedding,然后对所有 token 的 embedding 进行 clustering,找出一百零八将每个将领对应的 cluster 的所有 tokens,然后进行统计。但是这个是理想情况下的,实际可能一个人物称呼由多个 tokens 组成,而且单一 token 并不特指某一个人物,比如“林 教头”,那上述的做法就不 work 了。

另外一种做法可以是利用网上的 pre-trained 的模型先做 Named Entity Recognition(NER),找出所有人物名称的 string,然后把每个人物名称的 string 单独作为一个 token,再用一个 pre-trained 的 Language 模型,对《水浒传》进行 finetune,允许更新 token 的 embedding(新的人物名称的 string 是没有 embedding 的,需要通过学习得到),然后对人物名称 token 的 embedding 进行 clustering,找出一百零八将每个将领对应的 cluster 的所有 tokens,然后进行统计,这样效果应该就会非常好了,而且自动化程度会比较高。有兴趣的朋友可以尝试一下。

《水浒传》一百零八将名字在原著中的出现频率

https://leimao.github.io/essay/水浒传一百零八将名字在原著中的出现频率/

Author

Lei Mao

Posted on

05-17-2023

Updated on

05-17-2023

Licensed under


Comments