PiPiName如何从诗经中挖掘好名:诗文挖名算法源码深度剖析
【免费下载链接】PiPiName根据三才五格和古诗文给宝宝起名项目地址: https://gitcode.com/gh_mirrors/pi/PiPiName
PiPiName 是一款基于三才五格和古诗文的宝宝起名工具。给它一个姓氏,它就能从《诗经》《楚辞》《论语》《周易》《唐诗》《宋诗》《宋词》中自动挖掘出符合吉数笔画组合的名字,并附上原文出处,比如"张恒寿"会标注出自"如月之「恆」,如日之升。如南山之「壽」,不騫不崩"。本文带你深度剖析它的诗文挖名算法:从笔画组合预计算、诗句逐字匹配到名字过滤,一共三步,源码只有几百行,非常适合作为 NLP 方向的新手入门项目。
项目快速上手:5分钟跑通诗经起名
第一步:获取代码
git clone https://gitcode.com/gh_mirrors/pi/PiPiName第二步:安装依赖
项目只依赖一个第三方库 OpenCC(简繁体转换):
pip install opencc第三步:配置并运行
修改 config.py 中的参数,然后运行python main.py,结果会写入names.txt。示例输出:
张恒寿 男 恒 寿 10 14 如月之「恆」,如日之升。如南山之「壽」,不騫不崩。 张家宁 男 家 宁 10 14 有飶其香。邦「家」之光。有椒其馨,胡考之「寧」。配置参数清单
| 参数 | 作用 | 示例 |
|---|---|---|
name_source | 词库:0默认 / 1诗经 / 2楚辞 / 3论语 / 4周易 / 5唐诗 / 6宋诗 / 7宋词 | 1 |
last_name | 姓氏(仅支持单姓) | "林" |
dislike_words | 名字中禁止出现的字 | list("明") |
min_stroke_count/max_stroke_count | 名字用字的笔画区间 | 3/30 |
allow_general | 是否放宽到"中吉"配置,名字会更多 | False |
name_validate | 只在常用名字库中筛选,过滤奇怪组合 | True |
gender | 按性别筛选:男 / 女 / 空 | "" |
check_name | 填入三字姓名则切换为"查五格"模式 | "" |
所有词库数据都放在data/目录下:诗经.json、楚辞.txt、论语.json、周易.txt,以及唐诗/宋诗/宋词的按千首分片文件(如data/唐诗/poet.tang.0.json),data/Chinese_Names.dat是带性别标注的常用名字库,data/stoke.dat是汉字笔画表。
算法核心:三步诗文挖名流程
整个挖名流程在 main.py 的main()中串起来,可以概括为三步。
第一步:预计算姓氏的吉数笔画组合
get_stroke_list(last_name, allow_general)位于 wuge.py,这是整个算法的起点。它的思路是:先算出姓氏笔画,然后穷举 1~80 笔的每对数字 (i, j),逐一计算五格:
- 天格= 姓氏笔画 + 1
- 人格= 姓氏笔画 + 名字第一字笔画 (i)
- 地格= i + j
- 总格= 姓氏笔画 + i + j
- 外格= 总格 − 人格 + 1
只有人格、地格、总格、外格四个格子的笔画数都落在"大吉"列表stroke_goods中,且三才(天格+人格+地格换算成的五行组合,如"木木火")属于吉配置,这对笔画 (i, j) 才会被加入候选列表stroke_list。
举个例子:姓"林"(繁体 18 画),程序会算出类似[1, 3], [5, 9], [9, 9]这样的合法笔画组合。后续从诗经里挖字时,只需要检查"某两句中的某两字笔画是否恰好命中这些组合"。
💡 这里有个巧思:五格判定只依赖笔画数,与具体是哪个字无关。所以把"哪对笔画吉"提前算好,挖名时就能 O(1) 判断。
第二步:逐句扫描诗经,匹配笔画组合
词库加载入口在 name_set.py 的get_source(),source == 1时对应《诗经》:
elif source == 1: print('>>加载诗经...') get_name_json('诗经', names, 'content', stroke_list)get_name_json()的流程非常直白:
- 读入
data/诗经.json,逐篇遍历content字段里的每一句; - 用 OpenCC 把简体统一转成繁体(
s2tConverter.convert),因为五格论以康熙字典繁体笔画为准; - 用正则
re.split('!?,。,.?! \n', string)按标点把长句切成短句; - 交给核心的
check_and_add_names()。
check_and_add_names()是挖名的心脏,逻辑只有几行:
# 转换笔画数 strokes = list() for ch in sentence: if is_chinese(ch): strokes.append(get_stroke_number(ch)) else: strokes.append(0) # 判断是否包含指定笔画数 for stroke in stroke_list: if stroke[0] in strokes and stroke[1] in strokes: index0 = strokes.index(stroke[0]) index1 = strokes.index(stroke[1]) if index0 < index1: names.add(Name(name0 + name1, sentence, ''))- 先把句子里每个汉字的笔画算出来排成列表;
- 遍历第一步算好的每一对吉数笔画 (i, j),检查它俩是否都出现在本句的笔画列表中;
- 若出现,且 i 对应字的下标在 j 之前(保证顺序成词),就把这两个字组成名字,同时保存原句作为出处,用
「」高亮命中的字。
一句话总结:用"笔画指纹"代替"词义理解",在几十万字的诗经语料里做双字枚举匹配,简单、确定、可复现。
第三步:三重过滤,留下能用的好名
挖出来的候选名可能生僻或别扭,main()里还有三道关卡:
- 笔画区间过滤:两字笔画必须落在
min_stroke_count~max_stroke_count之间,避免生僻怪字; - 性别/常用库过滤:开启
name_validate后,get_intersect()会把候选名与data/Chinese_Names.dat名字库求交集——只有真实存在过的名字才保留,并顺带继承其性别标注,再按gender参数过滤; - 忌用字过滤:
dislike_words里列出的字直接剔除。
最后按拼音排序,全部写入names.txt,可以粘贴进 Excel 按字、笔画、性别继续筛选。
细节剖析:那些容易踩坑的设计
笔画不是简单的"数字几画"
get_stroke_number()在 stroke_number.py 中,做了两个新手容易忽略的处理:
- 按康熙字典取笔画:基础笔画来自
data/stoke.dat,查不到才回退到内置的一到十; - 部首变形加补:
data/chaizi-ft.dat记录了字的拆字结构,命中后按传统规则修正——三点水"氵"算 4 画(水+1)、提手旁"扌"算 5 画(手+1)、草字头"艹"算 6 画(艸+3)、左阝算 8 画(阜+6)、右阝算 7 画(邑+5)等等。
如果直接用简体笔画,"林"姓算出来是 8 画,而算法按 18 画计算——这正是为什么全程要先转繁体、再按康熙笔画计算。
Name 对象自带"出处高亮"
name.py 中的Name类在构造时就把原句里的命中字替换成带「」的形式存入source字段,__str__输出时格式固定为"名字、性别、两字、两字笔画、出处句"。这就是 README 里示例输出"如月之「恆」,如日之升"这种高亮效果的全部来源。
反向查询:这个名字出自哪些诗句?
把check_name填成三字姓名、check_name_resource置为True,就进入"溯源模式":check_resource()会遍历七大词库,找到所有包含该名字两字(按序)的诗句并高亮打印,同时check_wuge_config()输出完整的五格吉凶报表。比如查"周杰伦",会提示出处"谁谓三「杰」才,功业独殊「伦」"。这相当于把挖名算法倒过来用——从名字反查语料。
算法结构一图流
| 模块 | 文件 | 职责 |
|---|---|---|
| 参数配置 | config.py | 词库、姓氏、笔画区间、筛选开关 |
| 五格计算 | wuge.py | 笔画组合预计算、三才五行判定 |
| 笔画字典 | stroke_number.py | 康熙笔画 + 部首变形修正 |
| 挖名引擎 | name_set.py | 词库加载、句子切分、笔画匹配、溯源查询 |
| 数据模型 | name.py | 名字对象、出处高亮 |
| 入口 | main.py | 起名 / 查五格两种模式的调度与过滤 |
写在最后
PiPiName 的诗文挖名算法看似"黑科技",本质只是三个经典技巧的组合:穷举预计算 + 笔画指纹匹配 + 语料库过滤。全部源码不过千行,没有数据库、没有模型,却能把《诗经》305 篇变成一台随取随用的"起名搜索引擎"。如果你对 NLP 数据管线感兴趣,从这个项目入手,可以完整体会"语料清洗 → 特征提取 → 结果过滤"的标准工程思路。🚀
【免费下载链接】PiPiName根据三才五格和古诗文给宝宝起名项目地址: https://gitcode.com/gh_mirrors/pi/PiPiName
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考