☰
用Python数据验证甲骨文“册”字:简册编连之形的量化分析
2026/9/29 9:05:17 网站建设 项目流程

之前在整理汉字字形资料时,一直对甲骨文里的“册”字很感兴趣。很多资料把它解释为“古代竹简的形状”,但只看拓片上的弯曲线条,很难直接确认。这篇文章就用一个程序员的思路,把“册”字的字形结构拆成可量化的数据,再用代码验证:甲骨文“册”字,到底是不是简册编连的形状。

全文会从文字学常识讲起,给出可复现的 Python 分析脚本,并讨论计算机辅助古文字研究的边界和注意事项。无论你是第一次接触甲骨文,还是想了解数字人文方向的实际操作,都能从里面找到可以上手的思路。

1. 从“册”字说起:一个和竹简有关的问题

1.1 甲骨文“册”字长什么样

甲骨文,是商代晚期刻写在龟甲和兽骨上的文字,主要用于占卜记录,1899 年之后在河南安阳殷墟一带大量出土。甲骨文已经是一种相当成熟的文字系统,其中包含大量的象形字、指事字、会意字和形声字。“册”就是被反复讨论的典型象形字之一。

从字形上看,甲骨文里的“册”通常写作多根竖直的短线条并列,中间或两端有横向或略弯的线条把它们串联起来。这种形态非常像把一根一根的长条形薄片用绳子编连在一起。东汉许慎在《说文解字》里解释“册”字时,也说这个字是“符命”的意思,字形“象其札一长一短,中有二编之形”。用今天的话解释就是:像长短不一的简札,中间有两道编绳把它们连起来。

所谓“札”,指古代写字用的木简或竹简;所谓“编”,就是用来串联简札的绳子。所以“册”的字形从商代甲骨文到《说文解字》的记录,始终围绕同一个意象:把简札编连成书册。

1.2 “册”与“简”不是一回事

标题问的是“册”字究竟是不是古代竹简的形状。这个提问很自然,但严谨地说,“册”象的不是单独一根竹简,而是多根简札编连成册之后的形象。

先区分几个概念:

  • 简:单根竹片或木片,古人写字的主要载体。
  • 牍:较宽的木片,常常用来写公文或书信。
  • 册:把若干简牍用绳索编连起来的整体。
  • 策:古书中与“册”经常通用,指成编的简册,也引申为策略、计策。

所以更准确的表述是:甲骨文“册”字像“编简成册”之形。通俗地说成“竹简的形状”可以理解,因为简以竹制最常见;但从文字学和考古学的角度,应该说是“简册/简牍编连之形”。商代中原地带竹材的使用情况、简册实物的保存情况,仍需要更多考古材料佐证,因此“竹简形状”适合作为科普表达,“简册形状”更适合作为严谨结论。

1.3 为什么本文要用代码来验证

传统文字学判断一个象形字,主要靠字形排比、文献记载和考古实物互证。这种方法很可靠,但对初学者来说门槛高,而且不同学者对同一个字形可能有不同描述。计算机能做的是把“看上去像”变成“可以统计的特征”。

例如,我们可以把“册”的核心字形特征拆成三个可计算指标:

  • 简札数量:字形里有多少根竖直笔画。
  • 简札长短:这些竖直笔画是否长短不一。
  • 编绳数量:字形里有多少道横向长线条。

如果一组字形数据经过自动检测后,得到“多根竖线 + 长短不同 + 多道横线贯穿”的结果,那就说明计算机量化结果与传统文字学描述一致。这就是数字人文里很常见的“字形结构量化”思路,也是本文后面要实现的完整示例。

2. 计算机能帮文字学做什么

2.1 古文字数字化的现状

近些年古文字数字化发展很快。甲骨文、金文、简帛文字都建立了各种数据库和字形库,研究者可以在线检索字形、辞例和文献出处。对程序员来说,这意味着大量字形图像、结构化标注数据可以被下载、处理和分析。

常见的切入点有三类:

第一类是编码和检索。汉字在计算机里有 Unicode、GBK 等编码方案,甲骨文也有专门的编码提案和字形数据。处理编码问题本身就是一个技术任务。

第二类是图像处理。甲骨文拓片往往有噪声、裂纹和残损,需要用灰度化、二值化、去噪、形态学运算等方法提取笔画,再做形状匹配或分类。

第三类是机器学习和数据挖掘。当字形数据足够多时,可以用卷积神经网络做甲骨文单字识别,用聚类算法研究字形变体,或者用知识图谱把“字形、读音、释义、辞例、出处”组织起来。

本文属于第二类的入门演示,但不会直接处理真实拓片,而是先用一个可复现的点阵模型把“册”字的结构特征做出来,再用代码检验理论描述是否成立。

2.2 一条可执行的验证思路

传统文字学对“册”的描述是“一长一短,中有二编”。要验证这个描述,可以按下面四步来做:

第一步,把字形转成二值网格。黑色笔画记作 1,白色背景记作 0。第二步,按列扫描,统计每一列里连续出现 1 的段落,段落长度超过阈值的就认为是简札。第三步,按行扫描,统计每一行里连续出现 1 的跨度,跨度超过阈值的就认为是编绳。第四步,统计简札数量和编绳数量,对比文字学描述。

这个思路的本质是“投影法”。它简单、直观,也很适合做入门示例。真实拓片会有断裂和噪声,效果会打折扣,但在可控的模型数据上,它能完整展示从字形假设到代码验证的闭环。

2.3 本文涉及的技术边界

需要提前说明,这篇文章不会训练神经网络,也不会对真实甲骨拓片做高精度识别。我选择的是最简单、最稳定的二值点阵分析方案。这样做有三个好处:

一是零基础也能看懂。不需要安装 TensorFlow 或 PyTorch。二是在本地可完整复现。只要安装 Python 和 Pillow,就能跑出全部结果。三是避免“纸上学来终觉浅”的问题。很多人看过甲骨文图片后依然不知道“册”字为什么像简册,亲手用代码把笔画结构拆出来之后,印象会深得多。

如果你想用这套方法处理真实拓片,只需要把“读点阵”换成“读图片”,后续预处理思路是相通的。

3. 环境准备与基础知识

3.1 Python 环境与依赖安装

本文示例使用 Python 3 编写,理论上 Python 3.8 及以上版本都可以运行。主要用到的第三方库是 Pillow,用于把点阵模型渲染成 PNG 图片。如果你只想做编码查询和行列扫描,甚至可以不安装任何第三方库。

安装 Pillow 的命令如下:

pip install pillow

如果下载速度比较慢,可以选择国内镜像源:

pip install pillow -i https://pypi.tuna.tsinghua.edu.cn/simple

安装完成后,可以执行下面的命令确认版本:

python -c "import PIL; print(PIL.__version__)"

看到类似10.0.0的版本号输出,就说明环境没问题。需要提醒的是,Pillow 版本不同,部分 API 可能有细微差异,但本文用到的Image.new()、img.load()、img.save()都是长期稳定的接口。

3.2 汉字编码基础

在计算机里,每个字符都有一个编号,最通用的编号体系是 Unicode。以“册”字为例,它的 Unicode 码点是 U+518C。计算机存储和传输文本时,又需要把码点转换成字节序列,常见方案包括 UTF-8、UTF-16、GBK 等。

UTF-8 是互联网最常用的编码,一个汉字通常占 3 个字节;GBK 是中文环境常见的编码,一个汉字通常占 2 个字节。理解这些概念对后续处理中文文本、数据库存储、接口返回值都很重要。

3.3 图像与点阵的基本概念

本文说的“点阵”,就是把一张二值图像抽象成一个二维数组。数组的行对应图片的横向,列对应图片的纵向,元素 1 表示黑色笔画,元素 0 表示白色背景。

例如下面这个 3 行 5 列的点阵:

0 0 1 0 0 0 0 1 0 0 1 1 1 1 1

它其实表示一个“T”形笔画。计算机不能像人一样直接“看懂”图片,它看到的只是这样的数值网格。所谓图像处理,就是对这些数值做各种统计和变换。本文的检测算法也建立在这个基础上,先构造点阵,再按列和按行扫描数值。

4. 第一步:在计算机里定位“册”字

4.1 查看“册”的 Unicode 与编码字节

先来看一个最简单的 Python 脚本,它负责查询“册”字在计算机里的编码身份。虽然这个步骤不涉及字形分析,但能帮你建立“文字本身也是数据”的直觉。

# file: ce_encoding.py ch = "册" print("字符:", ch) print("Unicode 码点:U+%04X" % ord(ch)) print("UTF-8 编码:", ch.encode("utf-8")) print("GBK 编码:", ch.encode("gbk")) print("码点十进制:", ord(ch))

在这段代码中,ord()返回字符的 Unicode 码点,encode()把字符编码成指定格式的字节串。运行后,你会看到类似下面的结果:

字符: 册 Unicode 码点:U+518C UTF-8 编码: b'\xe5\x86\x8c' GBK 编码: b'\xb2\xe1' 码点十进制: 20876

需要注意,不同 Python 环境、不同版本的编码表可能会导致 GBK 输出字节略有差异,但 UTF-8 的结果是稳定的。如果你的控制台显示为b'\xe5\x86\x8c',说明“册”字在 UTF-8 下被编码成了 3 个字节,这与前面说的汉字 UTF-8 占用 3 字节规则完全一致。

4.2 编码信息说明了什么

“册”字在 Unicode 中的码点是 U+518C,这个码点属于 CJK 统一表意文字区。所谓 CJK,是指中国、日本、韩国、越南等地使用的汉字字符集。这说明现代计算机里的“册”字,和甲骨文里的“册”字虽然跨越了三千年,但在文字序列上是一脉相承的。

从工程角度看,了解这些编码信息有助于解决实际问题。比如当你从数据库读取中文数据出现乱码,或者调用第三方接口返回\u518c这样的字符串时,你就知道\u518c就是“册”字。对古文字数字化项目来说,编码问题更是基础中的基础,因为甲骨文、金文等古文字往往需要专门的字体和码位支持,处理不好就是一堆乱码。

5. 第二步:把“册”的字形结构变成数据

5.1 模型设计:一长一短、中有二编

现在我们进入核心环节:把《说文解字》里“象其札一长一短,中有二编之形”的描述,转成一个可控的点阵模型。

我建一个 16 行、20 列的二值网格,用来表示简化的“册”字示意图形。设计规则如下:

  • 4 根竖直笔画代表简札,其中两根较长、两根较短。
  • 2 道横向长笔画代表编绳,横跨整个字形。

需要说明的是,真实甲骨文中的“册”字形并不只有这一种,有的简札数量更多,有的编绳只有一道,有的线条弯曲。这里构造的是一个理想化的示意模型,目的是让代码检测结果能够和文献描述一一对应。

5.2 用点阵数据构造字形

下面代码负责生成这个点阵。先把网格全部填充为 0,然后按坐标把对应位置设为 1。

# file: ce_shape_model.py H, W = 16, 20 grid = [[0] * W for _ in range(H)] # 简札:两根长、两根短 for r in range(2, 14): grid[r][3] = 1 for r in range(4, 12): grid[r][7] = 1 for r in range(4, 12): grid[r][11] = 1 for r in range(2, 14): grid[r][16] = 1 # 编绳:两道横向贯穿线 for c in range(1, 19): grid[5][c] = 1 grid[10][c] = 1

这段代码里,range(2, 14)表示从第 2 行到第 13 行,共 12 行;range(4, 12)表示从第 4 行到第 11 行,共 8 行。所以最后检测出来简札长度应该分别是 12 和 8,刚好形成“一长一短”的区别。编绳放在第 5 行和第 10 行,对应“中有二编”。

你可以用一个简单的循环把它打印出来看看效果:

for row in grid: print("".join("█" if x == 1 else "·" for x in row))

打印结果大致是一个上下、左右对称的结构:中间两根短竖,两侧两根长竖,两道横线穿过所有竖线。虽然这是理想化图形,但它的结构特征已经非常接近“册”字的造字意图。

5.3 简札数量与编绳数量检测

点阵生成好之后,就要用算法自动统计结构特征。检测简札的思路是按列扫描:如果某一列里连续出现多个 1,说明这一列存在一条竖直笔画,连续长度超过阈值就记为一根简札。

检测编绳的思路是按行扫描:如果某一行里连续出现多个 1,说明这一行存在一条横向笔画,连续跨度超过阈值就记为一道编绳。

对应的检测函数如下:

def detect_vertical_bars(graph, min_len=3): rows = len(graph) cols = len(graph[0]) bars = [] for c in range(cols): length = 0 for r in range(rows): if graph[r][c] == 1: length += 1 else: if length >= min_len: bars.append((c, length)) length = 0 if length >= min_len: bars.append((c, length)) return bars def detect_horizontal_bands(graph, min_span=5): rows = len(graph) cols = len(graph[0]) bands = [] for r in range(rows): span = 0 for c in range(cols): if graph[r][c] == 1: span += 1 else: if span >= min_span: bands.append((r, span)) span = 0 if span >= min_span: bands.append((r, span)) return bands

min_len和min_span是阈值参数。真实图像中笔画可能断裂,阈值设得越小,越容易把噪声看成笔画;设得越大,越容易漏掉真实笔画。后续处理真实图片时,这两个参数需要反复调整。

6. 完整实战:从点阵到 PNG 再到检测结果

6.1 完整脚本

把生成点阵、渲染图片和结构检测三个步骤整合到一起,就得到一个完整的实战脚本。建议保存在同一个目录下,文件名叫ce_analysis.py。

# file: ce_analysis.py from PIL import Image # 1. 构造简化“册”字点阵 H, W = 16, 20 grid = [[0] * W for _ in range(H)] # 简札:两根长、两根短 for r in range(2, 14): grid[r][3] = 1 for r in range(4, 12): grid[r][7] = 1 for r in range(4, 12): grid[r][11] = 1 for r in range(2, 14): grid[r][16] = 1 # 编绳:两道横向贯穿线 for c in range(1, 19): grid[5][c] = 1 grid[10][c] = 1 # 2. 把点阵渲染成 PNG 图片 scale = 20 img = Image.new("L", (W * scale, H * scale), 255) pixels = img.load() for r in range(H): for c in range(W): if grid[r][c] == 1: for dr in range(scale): for dc in range(scale): pixels[c * scale + dc, r * scale + dr] = 0 img.save("ce_model.png") print("已生成图片 ce_model.png,尺寸:", img.size) # 3. 检测竖直简札 def detect_vertical_bars(graph, min_len=3): rows = len(graph) cols = len(graph[0]) bars = [] for c in range(cols): length = 0 for r in range(rows): if graph[r][c] == 1: length += 1 else: if length >= min_len: bars.append((c, length)) length = 0 if length >= min_len: bars.append((c, length)) return bars # 4. 检测横向编绳 def detect_horizontal_bands(graph, min_span=5): rows = len(graph) cols = len(graph[0]) bands = [] for r in range(rows): span = 0 for c in range(cols): if graph[r][c] == 1: span += 1 else: if span >= min_span: bands.append((r, span)) span = 0 if span >= min_span: bands.append((r, span)) return bands # 5. 输出结果 bars = detect_vertical_bars(grid) bands = detect_horizontal_bands(grid) print("检测到的竖直简札数量:", len(bars)) for col, length in bars: print(f" 列 {col},长度 {length}") print("检测到的横向编绳数量:", len(bands)) for row, span in bands: print(f" 行 {row},跨度 {span}")

6.2 运行与预期输出

在终端里执行下面的命令:

python ce_analysis.py

预期输出如下:

已生成图片 ce_model.png,尺寸: (400, 320) 检测到的竖直简札数量: 4 列 3,长度 12 列 7,长度 8 列 11,长度 8 列 16,长度 12 检测到的横向编绳数量: 2 行 5,跨度 18 行 10,跨度 18

图片尺寸 400×320 是因为点阵宽 20 列、高 16 行,放大 20 倍得到 20×20=400 和 16×20=320。如果你的输出出现类似结果,说明整条流程没有问题。

6.3 结果与文字学描述对照

把检测结果和《说文解字》的描述放在一起,会发现对应关系非常清楚:

文字学描述检测结果
象其札一长一短4 根简札,长度分别为 12 和 8
中有二编之形检测到 2 道横向编绳,跨度 18
整体像编简成册竖直笔画被横向笔画贯穿

这说明“册”字的造字意图,确实可以用“编连简札”来解释。回到标题的问题:甲骨文“册”字究竟是不是古代竹简的形状?答案是可以这么说。更严谨的说法是,它像“简册/简牍编连之形”,也就是把一根一根简札编起来的那个整体状态。

必须强调,这只是一个示意模型的验证,不构成对真实甲骨文“册”字全部字形的完整统计。真实字形中存在简札数量更多、编绳只有一道、笔画断裂或弯曲等变体,需要拿真实资料继续做统计分析。

7. 常见问题与排查思路

在实际运行或扩展本项目时,你可能会遇到下面几类问题,这里给出排查方向。

问题现象常见原因解决思路
提示ModuleNotFoundError: No module named 'PIL'没有安装 Pillow执行pip install pillow
中文输出乱码控制台编码不是 UTF-8Windows 下执行set PYTHONIOENCODING=utf-8
检测到的简札数量偏多阈值min_len太小,噪声被当成笔画调大min_len,例如改为 5
检测不到编绳横线断裂,或者min_span过大先做形态学闭运算,再调小min_span
把横向笔画当成简札转置问题或预处理不充分检查行列方向是否理解反了
真实拓片效果很差噪声、裂纹、残损、反色先做灰度化、去噪、二值化,再人工标注局部区域测试

关于真实甲骨文拓片,还有一个容易踩的坑:拓片通常是白字黑底或黑字白底,没有统一标准。直接套用本文点阵逻辑前,必须先确定“哪部分是笔画、哪部分是背景”,必要时还要对图像做旋转校正和裁剪。

8. 最佳实践与工程建议

8.1 古文字数字化项目建议

如果你想把这类示例扩展到真实项目,建议在工程层面做好三件事。

第一,数据建模要规范化。可以设计一张“字形表”,字段包括字形编号、字形图片路径、所属字头、时期、出处、备注;再设计一张“字头表”,保存该字的楷书字形、读音、释义和异体关系。这样后续检索和统计都方便。

第二,要记录算法参数和处理版本。图像处理非常依赖参数,比如二值化阈值、形态学核大小、连通域面积阈值。同一个字,参数不同,结果可能完全不同。建议把处理脚本、参数配置和运行时间一起记录下来,保证结果可复现。

第三,遵守数据来源的使用协议。公开的甲骨文数据库和字形网站有自己的版权和使用条款,不要批量抓取受保护的接口,不要未注明出处就大段复制资料。规范的引用和授权是数字人文项目长期发展的基础。

8.2 图像分析的正确姿势

真实甲骨文图像不是干净的点阵,直接做列扫描很容易得到错误结果。比较稳妥的处理流程是:

首先做灰度化,把彩色拓片变成单通道图像。接着做去噪,用中值滤波或者高斯模糊去掉细碎噪声。然后做二值化,把图像变成 0 和 1 两个值。再之后做形态学闭运算,把断裂的笔画接起来。最后再做行列投影统计,效果会好很多。

如果字形存在倾斜,还需要先做旋转校正。旋转角度可以用最小外接矩形估算,也可以用霍夫变换检测长直线。这一步不是必须的,但对最终统计结果影响很大。

8.3 学术结论的边界

程序员容易犯的一个错,是看到代码输出了“4 根简札、2 道编绳”,就认为计算机证明了“册”字是竹简形状。实际上,计算机只是完成了“特征提取”,并没有完成“历史判断”。

“册”字为什么造得像简册,还需要结合商代书写制度、简牍实物发现、文献记载等多方面的证据。代码结果可以作为辅助材料,但不能替代专家判断。反过来看,文字研究者如果能掌握一点图像处理和数据分析技能,也能在字形排比和变体统计中节省大量时间。数字人文的价值,正在于让两种思维方式互相补充。

9. 总结与下一步探索

本文从“册”字是不是竹简形状这个问题出发,介绍了相关文字学背景,并用 Python 完成了一个简化的字形结构验证。你掌握的并不是一个复杂的识别模型,而是一条完整的研究思路:提出字形假说、把特征转化成数据、用算法做统计、再和文献描述对照。

下一步可以尝试三个方向。第一,去做“典”字分析。甲骨文“典”字像双手捧册或册放在几案上,可以继续用同样的点阵思路拆解。第二,把本文的检测函数换成 OpenCV 实现,结合形态学运算直接处理真实字形图片。第三,收集几十个“册”字的不同甲骨文字形,统计简札数量和编绳数量的分布,写一个小规模的量化分析报告。

这类小项目最大的价值,不是立刻得到学术结论,而是帮你建立从“字形直觉”到“数据验证”的完整感觉。下次再看到甲骨文图片时,你至少不会觉得它只是一堆神秘线条,而是能意识到,每个笔画背后都是一种可以被观察、被记录、被分析的古人的造字逻辑。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询