判断一个字符是简体字还是繁体字。

Unicode 范围

开始以为可以用 Unicode 范围来表示,了解后发现简繁之间在 Unicode 字符集中位置存在交集,并且不是连续的,没办法用这种方法搞定。

如果真要靠这种办法,需要在茫茫字表中进行超级详细和繁杂的范围指定。

看到叶典网有一个字符集范围,但没有区分简繁。

Golang 也有一个 unicode.Han,也没有区分简繁。

Unihan_Variants.txt

http://www.unicode.org/Public/UCD/latest/ucd/ 下载 Unihan.zip,打开里面的 Unihan_Variants.txt

比如「战斗」的「斗」(繁体是「鬥」)这两行:

「斗」是 U+6597,「鬥」是 U+9B25

U+6597	kTraditionalVariant	U+9B25
U+9B25	kSimplifiedVariant	U+6597
  • kTraditionalVariant 前面是简体专用,后面是繁体专用;

  • kSimplifiedVariant 前面是繁体专用,后面是简体专用。

另外有「后U+540E、後U+5F8C」这种的字,「皇后」是简繁体通用,但表示 behind 时,简体用「后面」,繁体用「後面」。

所以就有以下这些行:

U+540E	kSimplifiedVariant	U+540E
U+5F8C	kSimplifiedVariant	U+540E
U+540E	kTraditionalVariant	U+540E U+5F8C
------- 翻译一下: -------
后	kSimplifiedVariant	后
後	kSimplifiedVariant	后
后	kTraditionalVariant	后 後

这种一对多、多对一的转换,除了「后/後」,还有「干/幹」等。

还有 kSpecializedSemanticVariant 这种「井/丼」的。

还有 kSpoofingVariant 这种欺骗性变体,比如「胶 U+80F6」和「㬵 U+3B35」不是同一个字。


参照 http://www.unicode.org/reports/tr38/#SCTC 查看各种标记的说明。

用不到这么精细的,不过这是个好工具啊,以后可能会用到。

自己弄个简体字表

适合简单的场景。

比如《通用汉字规范表》,但只有 8105 个字,并没有涵盖全部的简体字,比如「肏」「屄」「〇」「屌」「囧」等等很多字不在其中。

但《通用汉字规范表》缺失了大量生僻字,比如一大堆以鸟字旁、鱼字旁做为偏旁的汉字,不知道去哪里找到比较全面的字表。

opencc

如果不是太严谨的需求,临时使用的脚本等,可以考虑这个。

opencc 做简繁转换,然后对比原字符。


示例,判断字符是否为繁体字:

把字符进行繁转简。

c1 和繁转简后一致,则 c1 是简体字;

c2 和繁转简后不同,则 c2 是繁体字。

import opencc

converter = opencc.OpenCC('t2s.json')  # 繁体→简体

c1 = '门'
print(c1 == converter.convert(c1))  # '门' == '门' True

c2 = '門'
print(c2 == converter.convert(c2))  # '門' != '门' False

但并不完全成功:

import opencc

converter = opencc.OpenCC('t2s.json')  # 繁体→简体

for _, c in enumerate(['鴞', '鶲', '鮡', '鮠', '鮣', '鮋', '鮈', '鮊', '鰺', '鰏', '鰟']):
    print(c+' -> '+converter.convert(c))
    if c == converter.convert(c):
        print(c)
# 鴞 -> 鸮
# 鶲 -> 鹟
# 鮡 -> 鮡
# 鮡
# 鮠 -> 鮠
# 鮠
# 鮣 -> 䲟
# 鮋 -> 鲉
# 鮈 -> 鮈
# 鮈
# 鮊 -> 鲌
# 鰺 -> 鲹
# 鰏 -> 鲾
# 鰟 -> 鳑

试了一些超冷门的字,如「鮡 鮠 鮈」并没有被转换为「𬶐 𬶏 𬶋」。

另外还有一些问题,如「乾」会被识别为繁体字,转换为「干」。