standard.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. """
  4. 处理汉语拼音方案中的一些特殊情况
  5. 汉语拼音方案:
  6. * https://zh.wiktionary.org/wiki/%E9%99%84%E5%BD%95:%E6%B1%89%E8%AF%AD%E6%8B%BC%E9%9F%B3%E6%96%B9%E6%A1%88
  7. * http://www.moe.edu.cn/s78/A19/yxs_left/moe_810/s230/195802/t19580201_186000.html
  8. """ # noqa
  9. from __future__ import unicode_literals
  10. import re
  11. from pypinyin.style._constants import _FINALS
  12. # u -> ü
  13. UV_MAP = {
  14. 'u': 'ü',
  15. 'ū': 'ǖ',
  16. 'ú': 'ǘ',
  17. 'ǔ': 'ǚ',
  18. 'ù': 'ǜ',
  19. }
  20. U_TONES = set(UV_MAP.keys())
  21. # ü行的韵跟声母j,q,x拼的时候,写成ju(居),qu(区),xu(虚)
  22. UV_RE = re.compile(
  23. r'^(j|q|x)({tones})(.*)$'.format(
  24. tones='|'.join(UV_MAP.keys())))
  25. I_TONES = set(['i', 'ī', 'í', 'ǐ', 'ì'])
  26. # iu -> iou
  27. IU_MAP = {
  28. 'iu': 'iou',
  29. 'iū': 'ioū',
  30. 'iú': 'ioú',
  31. 'iǔ': 'ioǔ',
  32. 'iù': 'ioù',
  33. }
  34. IU_TONES = set(IU_MAP.keys())
  35. IU_RE = re.compile(r'^([a-z]+)({tones})$'.format(tones='|'.join(IU_TONES)))
  36. # ui -> uei
  37. UI_MAP = {
  38. 'ui': 'uei',
  39. 'uī': 'ueī',
  40. 'uí': 'ueí',
  41. 'uǐ': 'ueǐ',
  42. 'uì': 'ueì',
  43. }
  44. UI_TONES = set(UI_MAP.keys())
  45. UI_RE = re.compile(r'([a-z]+)({tones})$'.format(tones='|'.join(UI_TONES)))
  46. # un -> uen
  47. UN_MAP = {
  48. 'un': 'uen',
  49. 'ūn': 'ūen',
  50. 'ún': 'úen',
  51. 'ǔn': 'ǔen',
  52. 'ùn': 'ùen',
  53. }
  54. UN_TONES = set(UN_MAP.keys())
  55. UN_RE = re.compile(r'([a-z]+)({tones})$'.format(tones='|'.join(UN_TONES)))
  56. def convert_zero_consonant(pinyin):
  57. """零声母转换,还原原始的韵母
  58. i行的韵母,前面没有声母的时候,写成yi(衣),ya(呀),ye(耶),yao(腰),
  59. you(忧),yan(烟),yin(因),yang(央),ying(英),yong(雍)。
  60. u行的韵母,前面没有声母的时候,写成wu(乌),wa(蛙),wo(窝),wai(歪),
  61. wei(威),wan(弯),wen(温),wang(汪),weng(翁)。
  62. ü行的韵母,前面没有声母的时候,写成yu(迂),yue(约),yuan(冤),
  63. yun(晕);ü上两点省略。
  64. """
  65. raw_pinyin = pinyin
  66. # y: yu -> v, yi -> i, y -> i
  67. if raw_pinyin.startswith('y'):
  68. # 去除 y 后的拼音
  69. no_y_py = pinyin[1:]
  70. first_char = no_y_py[0] if len(no_y_py) > 0 else None
  71. # yu -> ü: yue -> üe
  72. if first_char in U_TONES:
  73. pinyin = UV_MAP[first_char] + pinyin[2:]
  74. # yi -> i: yi -> i
  75. elif first_char in I_TONES:
  76. pinyin = no_y_py
  77. # y -> i: ya -> ia
  78. else:
  79. pinyin = 'i' + no_y_py
  80. # w: wu -> u, w -> u
  81. if raw_pinyin.startswith('w'):
  82. # 去除 w 后的拼音
  83. no_w_py = pinyin[1:]
  84. first_char = no_w_py[0] if len(no_w_py) > 0 else None
  85. # wu -> u: wu -> u
  86. if first_char in U_TONES:
  87. pinyin = pinyin[1:]
  88. # w -> u: wa -> ua
  89. else:
  90. pinyin = 'u' + pinyin[1:]
  91. # 确保不会出现韵母表中不存在的韵母
  92. if pinyin not in _FINALS:
  93. return raw_pinyin
  94. return pinyin
  95. def convert_uv(pinyin):
  96. """ü 转换,还原原始的韵母
  97. ü行的韵跟声母j,q,x拼的时候,写成ju(居),qu(区),xu(虚),
  98. ü上两点也省略;但是跟声母n,l拼的时候,仍然写成nü(女),lü(吕)。
  99. """
  100. return UV_RE.sub(
  101. lambda m: ''.join((m.group(1), UV_MAP[m.group(2)], m.group(3))),
  102. pinyin)
  103. def convert_iou(pinyin):
  104. """iou 转换,还原原始的韵母
  105. iou,uei,uen前面加声母的时候,写成iu,ui,un。
  106. 例如niu(牛),gui(归),lun(论)。
  107. """
  108. return IU_RE.sub(lambda m: m.group(1) + IU_MAP[m.group(2)], pinyin)
  109. def convert_uei(pinyin):
  110. """uei 转换,还原原始的韵母
  111. iou,uei,uen前面加声母的时候,写成iu,ui,un。
  112. 例如niu(牛),gui(归),lun(论)。
  113. """
  114. return UI_RE.sub(lambda m: m.group(1) + UI_MAP[m.group(2)], pinyin)
  115. def convert_uen(pinyin):
  116. """uen 转换,还原原始的韵母
  117. iou,uei,uen前面加声母的时候,写成iu,ui,un。
  118. 例如niu(牛),gui(归),lun(论)。
  119. """
  120. return UN_RE.sub(lambda m: m.group(1) + UN_MAP[m.group(2)], pinyin)
  121. def convert_finals(pinyin):
  122. """还原原始的韵母"""
  123. pinyin = convert_zero_consonant(pinyin)
  124. pinyin = convert_uv(pinyin)
  125. pinyin = convert_iou(pinyin)
  126. pinyin = convert_uei(pinyin)
  127. pinyin = convert_uen(pinyin)
  128. return pinyin