Python 中拼音庫 PyPinyin 用法詳解
最近碰到瞭一個問題,項目中很多文件都是接手過來的中文命名的一些素材,結果在部署的時候文件名全都亂碼瞭,導致項目無法正常運行。
後來請教瞭一位大佬怎麼解決文件名亂碼的問題,他說這個需要正面解決嗎?不需要,把文件名全部改掉,文件名永遠不要用中文,永遠不要。
我想他這麼說的話,一定也是憑經驗得出來的。
這裡也友情提示大傢,項目裡面文件永遠不要用中文,永遠不要!
好,那不用中文用啥?平時來看,一般我們都會用英文來命名,一般也不會出現中文,比如 resource, controller, result, view, spider 等等,所以絕大多數情況下,是不會出現什麼問題的。但是也有個別的情況,比如一些素材、資源文件可能的中文命名的,那麼這時候該咋辦呢?
首先像,因為是中文資源文件,我們要改成非中文命名的,無非兩種,一種是英文,一種是拼音。
如果改英文,當然可以翻譯、我們想翻譯的話,逐個人工翻譯成本太高,機器翻譯的話,翻譯完可能有些文不對題瞭,而且我們自己也不知道一些奇怪的資源英語應該叫什麼,所以到時候真的找起來都找不到瞭。
所以第二種解決方案,那就是拼音瞭。中文轉拼音,很自然,而且一個字就對應一串拼音,而且也非常容易從拼音看懂是什麼意思,所以這確實是一個不錯的方案。
那麼問題就來瞭,怎樣把一批中文文件轉拼音命名呢?下面就讓我們來瞭解 Python 的一個庫 PyPinyin 吧!
概述
Python 中提供瞭漢字轉拼音的庫,名字叫做 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 pinyin print(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
有瞭這些,我們就可以輕松地實現風格轉換瞭。
好,再回到原來的問題,為什麼 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 參數是有幾種模式的:
u
下面是 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':kissing_heart:{pinyin}' return pinyin print(lazy_pinyin('麼麼噠', style='kiss'))
運行結果:
[‘:kissing_heart:me’, ‘:kissing_heart:me’, ‘dá’]
這裡我們調用 register 方法註冊瞭一個樣式 style,然後轉換的時候指定即可,通過觀察運行結果我們可以發現,這樣我們就可以將 me 字的拼音前面加上 :kissing_heart: 這個 Emoji 表情瞭。
以上就是Python 中拼音庫 PyPinyin 的用法的詳細內容,更多關於Python拼音庫 PyPinyin 的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- 教你使用Python pypinyin庫實現漢字轉拼音
- Python序列化與反序列化相關知識總結
- django中的*args 與 **kwargs使用介紹
- python入門學習關於for else的特殊特性講解
- Python序列化模塊之pickle與json詳解