页面载入中...
首页 » Tag ‘汉字’

[编程心得]用Python给汉字加上带音调的拼音

作为一个南方人,拼音没学好那似乎已是一件非常正常的事。什么卷舌音、鼻音,也只有在近几年才算是分清了一部分。但尴尬的事情仍在继续,发短信的时候,总有些字拼得不准;说话的时候,总有些字没有卷舌、或忘了加鼻音……痛定思痛,于是有了一个用SuperMemo来强化拼音的训练方案。

要实现这个方案,得具备两个条件,一是选定汉字范围——舍得选的是一级国标汉字,共计3700余个;二是利用程序将这些汉字转化为拼音,要求拼音带上音调,这个就需要对转换精灵进行适度的改造。

舍得以HzqGhost(小强)童鞋的代码为蓝本,进行了如下的改造:

  1. 编码部分采用这份码表:下载地址
  2. 源代码为python2.x的,改造为python 3.x;
  3. 在给韵母添加声调的部分代码,原代码有个别地方出现错误,在我家傻妹的提醒下,舍得修复了这一错误;

下面是相关的部分代码,分段描述:

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文本,这样就可以利用转换精灵制作成课程了。这里边的细节就不再一一叙述了。

附上最终完成的课程:

国标汉字拼音课程

 

本文版权归舍得英语魔法学苑所有,欢迎转载,转载请注明作者和出处。谢谢!

作者:
舍得

首发:
舍得@学习力博客

[编程心得]用python取汉字首字母

近日给兄弟公司编写一个HR管理软件,其中需要用到这样一个功能:当用户在窗口中输入员工姓名时,能够自动取出姓名中的拼音首字母,作为"助记码",以便用于后续的查询。

尝试了几种不同的方案以后,最终参考水木社区中的Roy兄提出的方案,用Python+Sqlite的方式来完成此项工作。

软件环境如下:

Python 3.2.2

PyQt 4.9.1

Sqlite 3

在文件头部需先导入sqlite3:

import sqlite3

 

然后来看getFirstLetter段代码:

   1:      def getFirstLetter(self, text):
   2:          pinyinlist=[]
   3:          for i in range(len(text)):
   4:              hanziSql = 'select pinyin from hanzi where hanzi = "'\
   5:                              + text[i] + '"'
   6:              pinyinlist.append([])
   7:              result = self.execSql(hanziSql)
   8:              for pinyin in result:                    
   9:                  pinyinlist[i].append(pinyin[0][0])#数据库中查到的是整个拼音,用pinyin[0][0]则指定返回首字母
  10:          poslist=[-1]*len(text)
  11:          i=0
  12:          results=[]
  13:          n=0
  14:          while (i>=0):
  15:              poslist[i]=poslist[i]+1
  16:              if (poslist[i]>=len(pinyinlist[i])) :
  17:                  poslist[i]=-1
  18:                  i=i-1
  19:                  continue
  20:              if i==len(text)-1:
  21:                  results.append('')
  22:                  for t in range(len(text)):
  23:                      results[n]=results[n]+pinyinlist[t][poslist[t]]
  24:                  n=n+1
  25:              else :
  26:                  i=i+1
  27:          return results 
 
里面调用到的execSql段代码如下:
   1:      def execSql(self, sql):
   2:          cxn = sqlite3.connect(db)
   3:          cur = cxn.cursor()
   4:          cur.execute(sql)#执行查询
   5:          return cur.fetchall()
   6:          cxn.close()
 
execSql这一段当然可以直接并到getFirstLetter中,不过舍得在其它地方要调用它,所以单独列出.
 
具体使用的方法如下,比如我们要查"舍得学苑"的拼音首字母:

        easyCode = self.getFirstLetter("舍得学苑")
        if len(easyCode) > 0:
            print(easyCode[0])#返回的结果中有多音词 ,只取第一个


 

本文用到的数据库可到这里下载:华为网盘下载
 

本文版权归舍得英语魔法学苑所有,欢迎转载,转载请注明作者和出处。谢谢!

作者:
舍得

首发:
舍得@学习力博客