漢字轉拼音工具庫

僅做收藏用

最近需要實現漢字轉拼音功能,找了一個簡單的vue-py,結果很多生僻字轉不了,后來找了一個能很好轉拼音的工具類

一個實現漢字與拼音互轉的小巧web工具庫,另外還包含一個非常非常簡單的JS版拼音輸入法。

演示地址:http://demo.haoji.me/pinyinjs/

支持多音字演示:http://demo.haoji.me/pinyinjs/polyphone.html

更多詳細介紹:http://blog.haoji.me/pinyinjs.html

本工具的優(yōu)點:

  1. 體積足夠小,適合web環(huán)境,常見漢字字典文件僅26kb,完整漢字也只有122kb,應該說是互聯(lián)網上最小的;
  2. 支持多種輸出格式,如帶聲調、不帶聲調、拼音首字母;
  3. 支持多音字:如果不引入詞庫文件,會將所有結果枚舉出來,如果引入詞庫,則可以識別多音字(當然識別的準確度有待持續(xù)完善),由于詞庫較大,一般不推薦web環(huán)境使用;
  4. 附帶一個簡單的JS版拼音輸入法;

前言

網上關于JS實現漢字和拼音互轉的文章很多,但是比較雜亂,都是互相抄來抄去,而且有的不支持多音字,有的不支持聲調,有的字典文件太大,還比如有時候我僅僅是需要獲取漢字拼音首字母卻要引入200kb的字典文件,無法根據實際需要滿足需求。

綜上,我精心整理并修改了網上幾種常見的字典文件并簡單封裝了一下可以直接拿來用的工具庫。

關于多音字

鑒于很多人都比較關心多音字的問題,所以單獨拿出一個小章節(jié)來介紹多音字的相關問題。

準確識別各種復雜語句中混雜的多音字其實并沒有那么容易,有兩個關鍵的地方,一個是多音字詞庫的豐富程度,一個是能否正確的給語句進行分詞。而詞庫和分詞的實現都需要一個非常豐富的詞典文件,現代漢語詞語有多少個,估計沒有人算得清,再加上每天新出現的人名、網絡詞語、科技詞語等等。一個普通的詞庫文件至少也有幾百kb,所以不太適合web環(huán)境下去實現,一般最好放在服務器端做成一個接口。

鑒于很多人都希望有多音字識別的功能,所以我簡單實現了一個版本。詞庫文件是從這里找到的,并根據實際情況將文件從1.8M壓縮到了912kb,分詞暫時只是自己非常簡單的實現(也可以說壓根就沒有分詞),如果是服務器端推薦幾個不錯的中文分詞工具:Python版的JiebaNodeJieba,性能非常好,其它語言版的參考上面項目的README。

關于分詞,摘抄一段網絡解釋:

詞是最小的能夠獨立活動的有意義的語言成分,英文單詞之間是以空格作為自然分界符的,而漢語是以字為基本的書寫單位,詞語之間沒有明顯的區(qū)分標記,因此,要對中文信息進行處理,正確的分詞就顯得尤為關鍵。

比如看中國這一個詞,單獨的看中kàn zhòng中國zhōng guó,連在一起卻讀作kàn zhōng guó

我這個實現非常得簡單,效果一般,性能也一般,需要下載將近1M的詞庫文件,所以不適合web環(huán)境,演示地址:

http://demo.haoji.me/pinyinjs/polyphone.html

拼音字典文件

按照字典文件的大小從小到大依次介紹。

字典一:拼音首字母

字典文件的內容大致如下:

/**
 * 拼音首字母字典文件
 */
var pinyin_dict_firstletter = {};
pinyin_dict_firstletter.all = "YDYQSXMWZSSXJBYMGCCZQPSSQBYCDSCDQLDYLYBSSJG...";
pinyin_dict_firstletter.polyphone = {"19969":"DZ","19975":"WM","19988":"QJ","20048":"YL",...};

該數據字典將Unicode字符中4E00(19968)-9FA5(40869)共計20902個漢字的拼音首字母拼接在一起得到一個很長的字符串,然后再將有多音字的漢字(共計370個多音字)單獨列出來。該字典文件大小為25kb

該字典文件優(yōu)點是體積小,支持多音字,缺點是只能獲取拼音首字母。

字典二:常用漢字

該字典文件將漢字按照拼音進行歸類,共計401種組合,收錄了6763個常用漢字,不支持多音字。由于從網絡上收集的,收錄字數較少,所以文件體積只有24kb,后續(xù)有空看能不能給擴充一下。

字典文件大致內容如下(這里只是示例,所以只展示一小部分):

/**
 * 常規(guī)拼音數據字典,收錄常見漢字6763個,不支持多音字
 */
var pinyin_dict_notone = 
{
    "a":"啊阿錒",
    "ai":"埃挨哎唉哀皚癌藹矮艾礙愛隘誒捱噯嗌嬡璦曖砹锿靄",
    "an":"鞍氨安俺按暗岸胺案諳埯揞犴庵桉銨鵪頇黯",
    "ang":"骯昂盎",
    "ao":"凹敖熬翱襖傲奧懊澳坳拗嗷噢岙廒遨媼驁聱螯鏊鰲鏖",
    "ba":"芭捌扒叭吧笆八疤巴拔跋靶把耙壩霸罷爸茇菝萆捭岜灞杷鈀粑鲅魃",
    "bai":"白柏百擺佰敗拜稗薜掰鞴",
    "ban":"斑班搬扳般頒板版扮拌伴瓣半辦絆阪坂豳鈑瘢癍舨",
    "bang":"邦幫梆榜膀綁棒磅蚌鎊傍謗蒡螃",
    "bao":"苞胞包褒雹保堡飽寶抱報暴豹鮑爆勹葆宀孢煲鴇褓趵齙",
    "bo":"剝薄玻菠播撥缽波博勃搏鉑箔伯帛舶脖膊渤泊駁亳蕃啵餑檗擘礴鈸鵓簸跛",
    "bei":"杯碑悲卑北輩背貝鋇倍狽備憊焙被孛陂邶埤蓓唄怫悖碚鵯褙鐾",
    "ben":"奔苯本笨畚坌錛"
    // 省略其它
};

后來慢慢發(fā)現這個字典文件中存在諸多錯誤,比如把的拼音寫成了nue(正確寫法應該是nve),寫成了thang,而且不支持多音字,所以后來我根據其它字典文件自己重新生成了一份這樣格式的 字典文件

  • 共有404種拼音組合
  • 收錄了6763個常用漢字
  • 支持多音字
  • 不支持聲調
  • 文件大小為27kb

同時,我根據網上一份常用6763個漢字使用頻率表,將這6763個漢字按照使用頻率進行了排序,這樣就可以實現一個差強人意的JS版輸入法了。

另外,根據另外一份更完整的字典文件發(fā)現其實共有412種拼音組合,上面字典文件中沒有出現的8種發(fā)音是:

chua,den,eng,fiao,m,kei,nun,shei

字典三:終極字典

首先,從網上找的如下結構字典文件(下面稱為字典A),具體是哪不記得了,支持聲調和多音字,它將Unicode字符中4E00(19968)-9FA5(40869)共計20902個漢字(如果算上〇的話那就是20903個)拼音全部列舉,該字典文件大小為280kb

3007 (ling2)
4E00 (yi1)
4E01 (ding1,zheng1)
4E02 (kao3)
4E03 (qi1)
4E04 (shang4,shang3)
4E05 (xia4)
4E06 (none0)
4E07 (wan4,mo4)
4E08 (zhang4)
4E09 (san1)
4E0A (shang4,shang3)
4E0B (xia4)
4E0C (ji1)
4E0D (bu4,bu2,fou3)
4E0E (yu3,yu4,yu2)
4E0F (mian3)
4E10 (gai4)
4E11 (chou3)
4E12 (chou3)
4E13 (zhuan1)
4E14 (qie3,ju1)
...

其中,對于沒有或者找不到讀音的漢字,統(tǒng)一標注為none0,我統(tǒng)計了一下,這樣的漢字一共有525個。

本著將字典文件盡可能減小體積的目標,發(fā)現上述文件中除了第一個〇(3007)之外,其它都是連續(xù)的,所以我把它改成了如下結構,文件體積也從280kb減小到了117kb

var pinyin_dict_withtone = "yi1,ding1 zheng1,kao3,qi1,shang4 shang3,xia4,none0,wan4 mo4,zhang4,san1,shang4 shang3,xia4,ji1,bu4 bu2 fou3,yu3 yu4 yu2,mian3,gai4,chou3,chou3,zhuan1,qie3 ju1...";

該字典文件的缺點是聲調是用數字標出的,如果想要得出類似xiǎo míng tóng xué這樣的拼音的話,需要一個算法將合適位置的字母轉換成āáǎàōóǒòēéěèīíǐìūúǔùüǖǘǚǜńň

本來還準備自己嘗試寫一個轉換的方法的,后來又找到了如下字典文件(下面稱為字典B),它收錄了20867個漢字,也支持聲調和多音字,但是聲調是直接標在字母上方的,由于它將漢字也列舉出來,所以文件體積比較大,有327kb,大致內容如下:

{
    "吖": "yā,ā",
    "阿": "ā,ē",
    "呵": "hē,a,kē",
    "嗄": "shà,á",
    "啊": "ā,á,ǎ,à,a",
    "腌": "ā,yān",
    "錒": "ā",
    "錒": "ā",
    "矮": "ǎi",
    "愛": "ài",
    "挨": "āi,ái",
    "哎": "āi",
    "礙": "ài",
    "癌": "ái",
    "艾": "ài",
    "唉": "āi,ài",
    "藹": "ǎi"
    /* 省略其它 */
}

但是經過比對,發(fā)現有502個漢字是字典A中讀音為none但是字典B中有讀音的,還有21個漢字是字典A中有但是B中沒有的:

{
    "兙": "shí kè",
    "兛": "qiān",
    "兝": "fēn",
    "兞": "máo",
    "兡": "bǎi kè",
    "兣": "lǐ",
    "唞": "dǒu",
    "嗧": "jiā lún",
    "囍": "xǐ",
    "堎": "lèng líng",
    "猤": "hú",
    "瓩": "qián wǎ",
    "礽": "réng",
    "膶": "rùn",
    "芿": "rèng",
    "蟘": "tè",
    "貣": "tè",
    "釀": "niàng niàn niáng",
    "醸": "niàng",
    "鋱": "tè",
    "鋱": "tè"
}

還有7個漢字是B中有但是A中沒有的:

{
    "?": "lēng",
    "?": "léng",
    "?": "léng",
    "?": "lèng",
    "?": "lèng,lì,lìn",
    "?": "réng",
    "?": "niàng"
}

所以我在字典A的基礎上將二者進行了合并,得到了最終的字典文件 pinyin_dict_withtone.js,文件大小為122kb

var pinyin_dict_withtone = "yī,dīng zhēng,kǎo qiǎo yú,qī,shàng,xià,hǎn,wàn mò,zhàng,sān,shàng shǎng,xià,qí jī...";

如何使用

我將這幾種字典文件放在一起并簡單封裝了一下解析方法,使用中可以根據實際需要引入不同字典文件。

封裝好的3個方法:

/**
 * 獲取漢字的拼音首字母
 * @param str 漢字字符串,如果遇到非漢字則原樣返回
 * @param polyphone 是否支持多音字,默認false,如果為true,會返回所有可能的組合數組
 */
pinyinUtil.getFirstLetter(str, polyphone);
/**
 * 根據漢字獲取拼音,如果不是漢字直接返回原字符
 * @param str 要轉換的漢字
 * @param splitter 分隔字符,默認用空格分隔
 * @param withtone 返回結果是否包含聲調,默認是
 * @param polyphone 是否支持多音字,默認否
*/
pinyinUtil.getPinyin(str, splitter, withtone, polyphone);
/**
 * 拼音轉漢字,只支持單個漢字,返回所有匹配的漢字組合
 * @param pinyin 單個漢字的拼音,不能包含聲調
 */
pinyinUtil.getHanzi(pinyin);

下面分別針對不同場合如何使用作介紹。

如果你只需要獲取拼音首字母

<script type="text/javascript" src="pinyin_dict_firstletter.js"></script>
<script type="text/javascript" src="pinyinUtil.js"></script>

<script type="text/javascript">
pinyinUtil.getFirstLetter('小茗同學'); // 輸出 XMTX
pinyinUtil.getFirstLetter('大中國', true); // 輸出 ['DZG', 'TZG']
</script>

需要特別說明的是,如果你引入的是其它2個字典文件,也同樣可以獲取拼音首字母的,只是說用這個字典文件更適合。

如果拼音不需要聲調

<script type="text/javascript" src="pinyin_dict_notone.js"></script>
<script type="text/javascript" src="pinyinUtil.js"></script>

<script type="text/javascript">
pinyinUtil.getPinyin('小茗同學'); // 輸出 'xiao ming tong xue'
pinyinUtil.getHanzi('ming'); // 輸出 '明名命鳴銘冥茗溟酩瞑螟暝'
</script>

如果需要聲調或者需要處理生僻字

<script type="text/javascript" src="pinyin_dict_withtone.js"></script>
<script type="text/javascript" src="pinyinUtil.js"></script>

<script type="text/javascript">
pinyinUtil.getPinyin('小茗同學'); // 輸出 'xiǎo míng tóng xué'
pinyinUtil.getPinyin('小茗同學', '-', true, true); // 輸出 ['xiǎo-míng-tóng-xué', 'xiǎo-míng-tòng-xué']
</script>

如果需要精準識別多音字

由于詞典文件較大,本示例不推薦在web環(huán)境下使用:

<script type="text/javascript" src="dict/pinyin_dict_withtone.js"></script>
<script type="text/javascript" src="dict/pinyin_dict_polyphone.js"></script>
<script type="text/javascript" src="pinyinUtil.js"></script>

<script type="text/javascript">
pinyinUtil.getPinyin('長城和長大', ' ', true, true); // 輸出:cháng chéng hé zhǎng dà
pinyinUtil.getPinyin('喝水和喝彩', ' ', true, true); // 輸出:hē shuǐ hé hè cǎi
pinyinUtil.getPinyin('偉大的大夫', ' ', true, true); // 輸出:wěi dà de dài fū
</script>

關于簡單拼音輸入法

一個正式的輸入法需要考慮的東西太多太多,比如詞庫、用戶個人輸入習慣等,這里只是實現一個最簡單的輸入法,沒有任何詞庫(雖然加上也可以,但是web環(huán)境不適合引入太大的文件)。

推薦使用第二個字典文件pinyin_dict_noletter.js,雖然字典三字數更多,但是不能按照漢字使用頻率排序,一些生僻字反而在前面。

<link rel="stylesheet" type="text/css" href="simple-input-method/simple-input-method.css">
<input type="text" class="test-input-method"/>
<script type="text/javascript" src="pinyin_dict_noletter.js"></script>
<script type="text/javascript" src="pinyinUtil.js"></script>
<script type="text/javascript" src="simple-input-method/simple-input-method.js"></script>
<script type="text/javascript">
    SimpleInputMethod.init('.test-input-method');
</script>
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,663評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 98,125評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,506評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,614評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,402評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,934評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,021評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,168評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 48,690評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,596評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,288評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,027評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,404評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,662評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,398評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,743評論 2 370

推薦閱讀更多精彩內容

  • 封裝好的3個方法: /** * 獲取漢字的拼音首字母 * @param str 漢字字符串,如果遇到非漢字則原樣返...
    他在發(fā)呆閱讀 818評論 0 0
  • (供參考) 老汪這個好多了,語言有些文釆了!而且有話則長,無話則短,不啰...
    老樹A閱讀 215評論 0 0
  • 北斗七星高,崔巖夜帶刀 夏日,遠足,登山,這還不夠,還要加點作料,那么夜深人靜,北斗七星高,以及背后的跨刀,這夠了...
    four0928閱讀 1,036評論 1 4
  • 今天是2017年8月12日,星期六。 早上睡到八點多,肚子餓到咕咕叫,實在頂唔順,起床吃早餐:三條兩指粗的地瓜和一...
    弟哥閱讀 201評論 0 0
  • 我覺得每一個人的內心里都有住著一個不完美的自己與完美的他人,當自己不完美的一面與完美的他人產生碰撞時,會產生...
    蘭榴蓮閱讀 360評論 0 0