Python 中拼音庫 PyPinyin 的使用

ython 中提供了漢字轉拼音的庫,名字叫做 PyPinyin,可以用於漢字註音、排序、檢索等等場合,是基於 hotto/pinyin 這個庫開發的,一些站點鏈接如下:

GitHub: https://github.com/mozillazg/python-pinyin

文檔: https://pypinyin.readthedocs.io/zh_CN/master/

PyPi: https://pypi.org/project/pypinyin/

它有這麼幾個特性:

根據詞組智能匹配最正確的拼音。
支持多音字。
簡單的繁體支持, 註音支持。
支持多種不同拼音/註音風格。

是不是等不及了呢?那就讓我們來了解一下它的用法吧!
安裝
首先就是這個庫的安裝了,通過 pip 安裝即可:
pip3 install pypinyin

安裝完成之後導入一下這個庫,如果不報錯,那就說明安裝成功了。

>>> import pypinyin

好,接下來我們看下它的具體功能。

基本拼音

首先我們進行一下基本的拼音轉換,方法非常簡單,直接調用 pinyin 方法即可:

from pypinyin import pinyin

print(pinyin('中心'))

運行結果:
[['zhōng'],  ['xīn']]

可以看到結果會是一個二維的列表,每個元素都另外成了一個列表,其中包含了每個字的讀音。
那麼如果這個詞是多音字咋辦呢?比如 “朝陽”,它有兩個讀音,我們拿來試下:

from pypinyin import pinyin

print(pinyin('朝陽'))

運行結果:
[['zhāo'],  ['yáng']]

好吧,它只給出來了一個讀音,但是如果我們想要另外一種讀音咋辦呢?
其實很簡單,只需添加 heteronym 參數並設置爲 True 就好了,我們試下:

from pypinyin import pinyin

print(pinyin('朝陽',  heteronym=True))

運行結果:
[['zhāo',  'cháo'],  ['yáng']]

OK 了,這下子就顯示出來了兩個讀音了,而且我們也明白了結果爲什麼是一個二維列表,因爲裏面的一維的結果可能是多個,比如多音字的情況就是這樣。

但這個多少解析起來有點麻煩,很多情況下我們是不需要管多音字的,我們只是用它來轉換一下名字而已,而處理上面的二維數組又比較麻煩。

所以有沒有一個方法直接給我們一個一維列表呢?有!
我們可以使用 lazy_pinyin 這個方法來生成,嘗試一下:

from pypinyin import lazy_pinyin

print(lazy_pinyin('聰明的小兔子'))

運行結果:
['cong',  'ming',  'de',  'xiao',  'tu',  'zi']

這時候觀察到得到的是一個列表,並且不再包含音調了。
這裏我們就有一個疑問了,爲啥 pinyin 方法返回的結果默認是帶音調的,而 lazy_pinyin 是不帶的,這裏面就涉及到一個風格轉換的問題了。

風格轉換

我們可以對結果進行一些風格轉換,比如不帶聲調風格、標準聲調風格、聲調在拼音之後、聲調在韻母之後、註音風格等等,比如我們想要聲調放在拼音後面,可以這麼來實現:

from pypinyin import lazy_pinyin,  Style

style  =  Style.TONE3

print(lazy_pinyin('聰明的小兔子',  style=style))

運行結果:
['cong1',  'ming2',  'de',  'xiao3',  'tu4',  'zi']

可以看到運行結果每個拼音後面就多了一個聲調,這就是其中的一個風格,叫做 TONE3,其實還有很多風格,下面是我從源碼裏面找出來的定義:

#: 普通風格,不帶聲調。如: 中國 -> ``zhong guo``

NORMAL  =  0

#: 標準聲調風格,拼音聲調在韻母第一個字母上(默認風格)。如: 中國 -> ``zhōng guó``

TONE  =  1

#: 聲調風格2,即拼音聲調在各個韻母之後,用數字 [1-4] 進行表示。如: 中國 -> ``zho1ng guo2``

TONE2  =  2

#: 聲調風格3,即拼音聲調在各個拼音之後,用數字 [1-4] 進行表示。如: 中國 -> ``zhong1 guo2``

TONE3  =  8

#: 聲母風格,只返回各個拼音的聲母部分(注:有的拼音沒有聲母,詳見 `#27`_)。如: 中國 -> ``zh g``

INITIALS  =  3

#: 首字母風格,只返回拼音的首字母部分。如: 中國 -> ``z g``

FIRST_LETTER  =  4

#: 韻母風格,只返回各個拼音的韻母部分,不帶聲調。如: 中國 -> ``ong uo``

FINALS  =  5

#: 標準韻母風格,帶聲調,聲調在韻母第一個字母上。如:中國 -> ``ōng uó``

FINALS_TONE  =  6

#: 韻母風格2,帶聲調,聲調在各個韻母之後,用數字 [1-4] 進行表示。如: 中國 -> ``o1ng uo2``

FINALS_TONE2  =  7

#: 韻母風格3,帶聲調,聲調在各個拼音之後,用數字 [1-4] 進行表示。如: 中國 -> ``ong1 uo2``

FINALS_TONE3  =  9

#: 註音風格,帶聲調,陰平(第一聲)不標。如: 中國 -> ``ㄓㄨㄥ ㄍㄨㄛˊ``

BOPOMOFO  =  10

#: 註音風格,僅首字母。如: 中國 -> ``ㄓ ㄍ``

BOPOMOFO_FIRST  =  11

#: 漢語拼音與俄語字母對照風格,聲調在各個拼音之後,用數字 [1-4] 進行表示。如: 中國 -> ``чжун1 го2``

CYRILLIC  =  12

#: 漢語拼音與俄語字母對照風格,僅首字母。如: 中國 -> ``ч г``

CYRILLIC_FIRST  =  13

如果你依然在編程的世界裏迷茫,
不知道自己的未來規劃,
對python感興趣,
這裏推薦一下我的學習交流圈QQ羣:895 797 751,
裏面都是學習python的,


有了這些,我們就可以輕鬆地實現風格轉換了。
好,再回到原來的問題,爲什麼 pinyin 的方法默認帶聲調,而 lazy_pinyin 方法不帶聲調,答案就是:它們二者使用的默認風格不同,我們看下它的函數定義就知道了:
pinyin 方法的定義如下:

def pinyin(hans,  style=Style.TONE,  heteronym=False,  errors='default',  strict=True)

lazy_pinyin 方法的定義如下:
def lazy_pinyin(hans,  style=Style.NORMAL,  errors='default',  strict=True)

這下懂了吧,因爲 pinyin 方法默認使用了 TONE 的風格,而 lazy_pinyin 方法默認使用了 NORMAL 的風格,所以就導致二者返回風格不同了。

好了,有了這兩個函數的定義,我們再來研究下其他的參數,比如定義裏面的 errors 和 strict 參數又怎麼用呢?
錯誤處理

在這裏我們先做一個測試,比如我們傳入無法轉拼音的字,比如:

from pypinyin import lazy_pinyin

print(lazy_pinyin('你好☆☆,我是xxx'))

其中包含了星號兩個,還有標點一個,另外還包含了一個 xxx 英文字符,結果會是什麼呢?
['ni',  'hao',  '☆☆,',  'wo',  'shi',  'xxx']

可以看到結果中星號和英文字符都作爲一個整體並原模原樣返回了。

那麼這種特殊字符可以單獨進行處理嗎?當然可以,這裏就用到剛纔提到的 errors 參數了。

errors 參數是有幾種模式的:

下面是 errors 這個參數的源碼實現邏輯:

def _handle_nopinyin_char(chars,  errors='default'):

    """處理沒有拼音的字符"""

    if  callable_check(errors):

        return  errors(chars)

    if  errors  ==  'default':

        return  chars

    elif errors  ==  'ignore':

        return  None

    elif errors  ==  'replace':

        if  len(chars)  >  1:

            return  ''.join(text_type('%x'  %  ord(x))  for  x  in  chars)

        else:

            return  text_type('%x'  %  ord(chars))

當處理沒有拼音的字符的時候,errors 的不同參數會有不同的處理結果,更詳細的邏輯可以翻看源碼。

好了,下面我們來嘗試一下,比如我們想將不能轉拼音的字符去掉,則可以這麼設置:

from pypinyin import lazy_pinyin

print(lazy_pinyin('你好☆☆,我是xxx',  errors='ignore'))

運行結果:
['ni',  'hao',  'wo',  'shi']

如果我們想要自定義處理,比如把 ☆ 轉化爲 ※ ,則可以這麼設置:

print(lazy_pinyin('你好☆☆,我是xxx',  errors=lambda item:  ''.join(['※'  if  c  ==  '☆'  else  c  for  c  in  item])))

運行結果:
['ni',  'hao',  '※※,',  'wo',  'shi',  'xxx']

如上便是一些相關異常處理的操作,我們可以隨心所欲地處理自己想處理的字符了。

嚴格模式

最後再看下 strict 模式,這個參數用於控制處理聲母和韻母時是否嚴格遵循《漢語拼音方案》 標準。

下面的一些說明來源於官方文檔:

當 strict 參數爲 True 時根據《漢語拼音方案》 的如下規則處理聲母、在韻母相關風格下還原正確的韻母:

  • 21 個聲母: b p m f d t n l g k h j q x zh ch sh r z c s ( y, w 不是聲母 )

  • i行的韻母,前面沒有聲母的時候,寫成yi(衣),ya(呀),ye(耶),yao(腰),you(憂),yan(煙), yin(因),yang(央),ying(英),yong(雍)。( y 不是聲母 )

  • u行的韻母,前面沒有聲母的時候,寫成wu(烏),wa(蛙),wo(窩),wai(歪),wei(威),wan(彎), wen(溫),wang(汪),weng(翁)。( w 不是聲母 )

  • ü行的韻母,前面沒有聲母的時候,寫成yu(迂),yue(約),yuan(冤),yun(暈);ü上兩點省略。 ( 韻母相關風格下還原正確的韻母 ü )

  • ü行的韻跟聲母j,q,x拼的時候,寫成ju(居),qu(區),xu(虛),ü上兩點也省略; 但是跟聲母n,l拼的時候,仍然寫成nü(女),lü(呂)。( 韻母相關風格下還原正確的韻母 ü )

  • iou,uei,uen前面加聲母的時候,寫成iu,ui,un。例如niu(牛),gui(歸),lun(論)。 ( 韻母相關風格下還原正確的韻母 iou,uei,uen )

當 strict 爲 False 時就是不遵守上面的規則來處理聲母和韻母, 比如: y , w 會被當做聲母,yu(迂) 的韻母就是一般認爲的 u 等。

具體差異可以查看源碼中 tests/test_standard.py 中的對比結果測試用例。

自定義拼音

如果對庫返回的結果不滿意,我們還可以自定義自己的拼音庫,這裏用到的方法就有 load_single_dict 和 load_phrases_dict 方法了。

比如剛纔我們看到 “朝陽” 兩個字的發音默認返回的是 zhao yang,我們想默認返回 chao yang,那可以這麼做:

from pypinyin import lazy_pinyin,  load_phrases_dict

print(lazy_pinyin('朝陽'))

personalized_dict  =  {

    '朝陽':  [['cháo'],  ['yáng']]

}

load_phrases_dict(personalized_dict)

print(lazy_pinyin('朝陽'))

這裏我們自定義了一個詞典,然後使用 load_phrases_dict 方法設置了一下就可以了。
運行結果:

['zhao',  'yang']

['chao',  'yang']

這樣就可以完成自定義的設置了。
在一些項目裏面我們可以自定義很多拼音庫,然後加載就可以了。
另外我們還可以註冊樣式實現自定義,比如將某個拼音前面加上 Emoji 表情,樣例:

from pypinyin.style import register

from pypinyin import lazy_pinyin

@register('kiss')

def kiss(pinyin,  **kwargs):

    if  pinyin  ==  'me':

        return  f'

{pinyin}'

    return  pinyin

print(lazy_pinyin('麼麼噠',  style='kiss'))

運行結果:
me',  

me',  'dá']

如果你依然在編程的世界裏迷茫,
不知道自己的未來規劃,
對python感興趣,
這裏推薦一下我的學習交流圈QQ羣:895 797 751,
裏面都是學習python的,


這裏我們調用 register 方法註冊了一個樣式 style,然後轉換的時候指定即可,通過觀察運行結果我們可以發現,這樣我們就可以將 me 字的拼音前面加上
這個 Emoji 表情了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章