[编程心得]用Python给汉字加上带音调的拼音
作为一个南方人,拼音没学好那似乎已是一件非常正常的事。什么卷舌音、鼻音,也只有在近几年才算是分清了一部分。但尴尬的事情仍在继续,发短信的时候,总有些字拼得不准;说话的时候,总有些字没有卷舌、或忘了加鼻音……痛定思痛,于是有了一个用SuperMemo来强化拼音的训练方案。
要实现这个方案,得具备两个条件,一是选定汉字范围——舍得选的是一级国标汉字,共计3700余个;二是利用程序将这些汉字转化为拼音,要求拼音带上音调,这个就需要对转换精灵进行适度的改造。
舍得以HzqGhost(小强)童鞋的代码为蓝本,进行了如下的改造:
- 编码部分采用这份码表:下载地址
- 源代码为python2.x的,改造为python 3.x;
- 在给韵母添加声调的部分代码,原代码有个别地方出现错误,在我家傻妹的提醒下,舍得修复了这一错误;
下面是相关的部分代码,分段描述:
1、读入码表文件,转成dict:
fileName = './Mandarin.dat' self.dict = {} for line in open(fileName): k, v = line.split('\t') self.dict[k] = v
2、然后对传入的中文字符串进行处理:
self.yunmu = ( 'ang','eng','ing','ong','an','en','in','un','ai','ei','ao','ou','iu','er','en','a','o','e','i','u', 'v') self.sheng = {'a':'ā á ǎ à','o':'ō ó ǒ ò','e':'ē é ě è','i':'ī í ǐ ì','u':'ū ú ǔ ù', 'v':'ǖ ǘ ǚ ǜ'} result = [] for char in chars:#chars为传入的中文字符串 key = "%X" % ord(char)#将汉字转为utf16编码,“码表”文件中用的是这个编码 try: py = self.dict[key].split(" ")[0].strip().lower()#只取查到的拼音第一个值(当有多音字的时候),同时将结果转为小写 for ym in self.yunmu: if re.search(ym, py):#匹配 py = getPy(py, ym) break#只取第一个结果 result.append(py) except: result.append(char) return " ".join(result)
原来的self.yunmu设置不合理,在碰到'ui','iu','ie','ue'四个韵母时,音调会标在第一个字母上,舍得在元组中去除了'ui','ie','ue'这三个值,这样在匹配时根据a,o,e,i,u的顺序,这三个韵母的音调才会落在第二个字母上。而对于'iu'这个韵母,则需在下面的getPy里作一个特殊的处理:
3、给匹配到的韵母标上音调:
def getPy(py, ym): t = py[-1:].encode('ascii','ignore')#‘码表’中返回的拼音字符串最后一位是数字,表示音调值 t2 = "%d" % ord(t) t3 = (int(t2) - 48)%4 -1 py2 = py[:-len(ym)-1]#声母 if ym == "iu":#如果韵母是iu letter = self.sheng[ym[1]].split(' ')[t3]#音调字母要标在u上 ym = ym[0] + letter else: letter = self.sheng[ym[0]].split(' ')[t3]#其它情况,音调标在第一个字母上 ym = letter + ym[1:] py = py2 + ym return py
最终完整的代码如下:
def cnCode(self, chars): def getPy(py, ym): t = py[-1:].encode('ascii','ignore')#‘码表’中返回的拼音字符串最后一位是数字,表示音调值 t2 = "%d" % ord(t) t3 = (int(t2) - 48)%4 -1 py2 = py[:-len(ym)-1]#声母 if ym == "iu":#如果韵母是iu letter = self.sheng[ym[1]].split(' ')[t3]#音调字母要标在u上 ym = ym[0] + letter else: letter = self.sheng[ym[0]].split(' ')[t3]#其它情况,音调标在第一个字母上 ym = letter + ym[1:] py = py2 + ym return py fileName = './Mandarin.dat' self.dict = {} for line in open(fileName): k, v = line.split('\t') self.dict[k] = v self.yunmu = ( 'ang','eng','ing','ong','an','en','in','un','ai','ei','ao','ou','iu','er','en','a','o','e','i','u', 'v') self.sheng = {'a':'ā á ǎ à','o':'ō ó ǒ ò','e':'ē é ě è','i':'ī í ǐ ì','u':'ū ú ǔ ù', 'v':'ǖ ǘ ǚ ǜ'} result = [] for char in chars:#chars为传入的中文字符串 key = "%X" % ord(char)#将汉字转为utf16编码,“码表”文件中用的是这个编码 try: py = self.dict[key].split(" ")[0].strip().lower()#只取查到的拼音第一个值(当有多音字的时候),同时将结果转为小写 for ym in self.yunmu: if re.search(ym, py):#匹配 py = getPy(py, ym) break#只取第一个结果 result.append(py) except: result.append(char) return " ".join(result)
调用的时候,只要这样就可以了:
chars = "舍得英语魔法学苑" print(self.cnCode(chars))
返回的结果如下图所示:
不过舍得通常会读取当前文本,然后按换行符分割,再逐个传入,得到拼音,最后拼成TAB文本,这样就可以利用转换精灵制作成课程了。这里边的细节就不再一一叙述了。
附上最终完成的课程: