Skip to content

Commit

Permalink
Merge ecead60 into 04a0f39
Browse files Browse the repository at this point in the history
  • Loading branch information
mozillazg committed Oct 1, 2017
2 parents 04a0f39 + ecead60 commit a8aa9bd
Show file tree
Hide file tree
Showing 11 changed files with 396 additions and 14 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Expand Up @@ -44,3 +44,8 @@ venv
.cache/
2.7/
.python-version
venv2.7/
venvPyInstaller/
output.dat
vocab.bin
vocab.large.bin
45 changes: 45 additions & 0 deletions CHANGELOG.rst
@@ -1,6 +1,50 @@
Changelog
---------

0.25.0 (2017-mm-dd)
++++++++++++++++++++

* **[New]** 内置一个最大匹配分词模块,使用内置的词语拼音库来训练这个分词模块,
解决自定义词语库有时可能不生效的问题(因为这个词语在 jieba 等分词模块中不是可用词)。(via `#81`_)


获取拼音或自定义词库后使用:

.. code-block:: python
>>> from pypinyin import pinyin, load_phrases_dict
>>> load_phrases_dict({'了局': [['liǎo'], ['']]})
>>> pinyin('了局啊') # 使用 jieba 分词
Building prefix dict from the default dictionary ...
Dumping model to file cache /var/folders/s6/z9r_07h53pj_d4x7qjszwmbw0000gn/T/jieba.cache
Loading model cost 1.175 seconds.
Prefix dict has been built succesfully.
[['le'], [''], ['a']]
>>> from pypinyin.contrib.mmseg import seg, retrain
>>> retrain(seg) # 没有使用 load_phrases_dict 时可以不调用这个函数
>>> pinyin(seg.cut('了局啊')) # 使用内置的最大匹配分词
[['liǎo'], [''], ['a']]
>>>
单独使用:

.. code-block:: python
>>> from pypinyin.contrib.mmseg import seg
>>> text = '你好,我是中国人,我爱我的祖国'
>>> seg.cut(text)
<generator object Seg.cut at 0x10b2df2b0>
>>> list(seg.cut(text))
['你好', '', '', '', '中国人', '', '', '',
'我的', '', '']
>>> seg.train(['祖国', '我是'])
>>> list(seg.cut(text))
['你好', '', '我是', '中国人', '', '', '',
'我的', '祖国']
>>>
0.24.0 (2017-09-17)
+++++++++++++++++++++

Expand Down Expand Up @@ -498,3 +542,4 @@ __ https://github.com/mozillazg/python-pinyin/issues/8
.. _#86: https://github.com/mozillazg/python-pinyin/issues/86
.. _#92: https://github.com/mozillazg/python-pinyin/issues/92
.. _#93: https://github.com/mozillazg/python-pinyin/issues/93
.. _#81: https://github.com/mozillazg/python-pinyin/issues/81
37 changes: 32 additions & 5 deletions README.rst
Expand Up @@ -76,14 +76,43 @@ FAQ
为什么没有 y, w, yu 几个声母?
++++++++++++++++++++++++++++++++++++++++++++

声母风格(INITIALS)下,“雨”、“我”、“圆”等汉字返回空字符串,因为根据 `《汉语拼音方案》 <http://www.moe.edu.cn/s78/A19/yxs_left/moe_810/s230/195802/t19580201_186000.html>`__ , y,w,ü (yu) 都不是声母,在某些特定韵母无声母时,才加上 y 或 w,而 ü 也有其特定规则。 —— @hotoo
声母风格(INITIALS)下,“雨”、“我”、“圆”等汉字返回空字符串,因为根据
`《汉语拼音方案》 <http://www.moe.edu.cn/s78/A19/yxs_left/moe_810/s230/195802/t19580201_186000.html>`__ ,
y,w,ü (yu) 都不是声母,在某些特定韵母无声母时,才加上 y 或 w,而 ü 也有其特定规则。 —— @hotoo

如果你觉得这个给你带来了麻烦,那么也请小心一些无声母的汉字(如“啊”、“饿”、“按”、“昂”等)。 这时候你也许需要的是首字母风格(FIRST_LETTER)。 —— @hotoo
如果你觉得这个给你带来了麻烦,那么也请小心一些无声母的汉字(如“啊”、“饿”、“按”、“昂”等)。
这时候你也许需要的是首字母风格(FIRST_LETTER)。 —— @hotoo

参考: `hotoo/pinyin#57 <https://github.com/hotoo/pinyin/issues/57>`__, `#22 <https://github.com/mozillazg/python-pinyin/pull/22>`__, `#27 <https://github.com/mozillazg/python-pinyin/issues/27>`__,
参考: `hotoo/pinyin#57 <https://github.com/hotoo/pinyin/issues/57>`__,
`#22 <https://github.com/mozillazg/python-pinyin/pull/22>`__,
`#27 <https://github.com/mozillazg/python-pinyin/issues/27>`__,
`#44 <https://github.com/mozillazg/python-pinyin/issues/44>`__


自定义了词典,但是结果没用使用自定义词典中的拼音信息?
++++++++++++++++++++++++++++++++++++++++++++++++++++++

自定义的词语在你使用的分词模块(比如:jieba)中没有被切分为一个词语,
可以考虑使用内置的最大匹配分词器来分词或者训练使用的分词模块。

.. code-block:: python
>>> from pypinyin import pinyin, load_phrases_dict
>>> load_phrases_dict({'了局': [['liǎo'], ['']]})
>>> pinyin('了局啊') # 使用 jieba 分词
Building prefix dict from the default dictionary ...
Dumping model to file cache /var/folders/s6/z9r_07h53pj_d4x7qjszwmbw0000gn/T/jieba.cache
Loading model cost 1.175 seconds.
Prefix dict has been built succesfully.
[['le'], [''], ['a']]
>>> from pypinyin.contrib.mmseg import seg, retrain
>>> retrain(seg) # 没有使用 load_phrases_dict 时可以不调用这个函数
>>> pinyin(seg.cut('了局啊')) # 使用内置的最大匹配分词
[['liǎo'], [''], ['a']]
>>>
拼音数据
---------

Expand All @@ -109,8 +138,6 @@ __ https://github.com/mozillazg/rust-pinyin
:target: https://coveralls.io/r/mozillazg/python-pinyin
.. |PyPI version| image:: https://img.shields.io/pypi/v/pypinyin.svg
:target: https://pypi.python.org/pypi/pypinyin
.. |PyPI downloads| image:: https://img.shields.io/pypi/dm/pypinyin.svg
:target: https://pypi.python.org/pypi/pypinyin
.. _Russian translation: https://github.com/mozillazg/python-pinyin/blob/master/README_ru.rst
.. _pinyin-data: https://github.com/mozillazg/pinyin-data
.. _phrase-pinyin-data: https://github.com/mozillazg/phrase-pinyin-data
20 changes: 20 additions & 0 deletions docs/api.rst
Expand Up @@ -2,6 +2,9 @@ API
====


核心 API
-------------

.. autoclass:: pypinyin.Style
:members:
:undoc-members:
Expand All @@ -17,9 +20,26 @@ API

.. autofunction:: pypinyin.slug


风格转换
-----------

.. autofunction:: pypinyin.style.register

.. autofunction:: pypinyin.style.convert



分词
-------

.. autodata:: pypinyin.contrib.mmseg.seg

.. autodata:: pypinyin.contrib.mmseg.retrain

.. autoclass:: pypinyin.contrib.mmseg.Seg
:members:
:member-order: bysource


.. _#27: https://github.com/mozillazg/python-pinyin/issues/27
59 changes: 50 additions & 9 deletions docs/faq.rst
Expand Up @@ -2,21 +2,62 @@ FAQ
-----


* | Q: 如何禁用“自动调用结巴分词模块”功能
| A: 设置环境变量 ``PYPINYIN_NO_JIEBA=true``
如何禁用“自动调用结巴分词模块”功能
+++++++++++++++++++++++++++++++++++++

* | Q: 如何禁用内置的“词组拼音库”:
| A: 设置环境变量 ``PYPINYIN_NO_PHRASES=true``

* | Q: ``INITIALS`` 声母风格下,以 ``y``, ``w``, ``yu`` 开头的汉字返回空字符串,例如:
设置环境变量 ``PYPINYIN_NO_JIEBA=true`` 即可


如何禁用内置的“词组拼音库”
++++++++++++++++++++++++++++++++

设置环境变量 ``PYPINYIN_NO_PHRASES=true`` 即可


``INITIALS`` 声母风格下,以 ``y``, ``w``, ``yu`` 开头的汉字返回空字符串
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

比如:

.. code:: python
pinyin('火影忍者', style=pypinyin.INITIALS)
[['h'], [''], ['r'], ['zh']]
| A: 因为 ``y``, ``w``, ``yu`` 都不是声母。参考: `hotoo/pinyin#57 <https://github.com/hotoo/pinyin/issues/57>`__, `#22 <https://github.com/mozillazg/python-pinyin/pull/22>`__, `#27 <https://github.com/mozillazg/python-pinyin/issues/27>`__,
`#44 <https://github.com/mozillazg/python-pinyin/issues/44>`__
声母风格(INITIALS)下,“雨”、“我”、“圆”等汉字返回空字符串,因为根据 `《汉语拼音方案》 <http://www.moe.edu.cn/s78/A19/yxs_left/moe_810/s230/195802/t19580201_186000.html>`__ , y,w,ü (yu) 都不是声母,在某些特定韵母无声母时,才加上 y 或 w,而 ü 也有其特定规则。
如果你觉得这个给你带来了麻烦,那么也请小心一些无声母的汉字(如“啊”、“饿”、“按”、“昂”等)。 这时候你也许需要的是首字母风格(FIRST_LETTER)。 —— @hotoo
因为 ``y``, ``w``, ``yu`` 都不是声母。参考:
`hotoo/pinyin#57 <https://github.com/hotoo/pinyin/issues/57>`__,
`#22 <https://github.com/mozillazg/python-pinyin/pull/22>`__,
`#27 <https://github.com/mozillazg/python-pinyin/issues/27>`__,
`#44 <https://github.com/mozillazg/python-pinyin/issues/44>`__

声母风格(INITIALS)下,“雨”、“我”、“圆”等汉字返回空字符串,因为根据
`《汉语拼音方案》 <http://www.moe.edu.cn/s78/A19/yxs_left/moe_810/s230/195802/t19580201_186000.html>`__ ,
y,w,ü (yu) 都不是声母,在某些特定韵母无声母时,才加上 y 或 w,而 ü 也有其特定规则。
如果你觉得这个给你带来了麻烦,那么也请小心一些无声母的汉字(如“啊”、“饿”、“按”、“昂”等)。
这时候你也许需要的是首字母风格(FIRST_LETTER)。 —— @hotoo


自定义了词典,但是结果没用使用自定义词典中的拼音信息?
++++++++++++++++++++++++++++++++++++++++++++++++++++++

自定义的词语在你使用的分词模块(比如:jieba)中没有被切分为一个词语,
可以考虑使用内置的最大匹配分词器来分词或者训练使用的分词模块。

.. code-block:: python
>>> from pypinyin import pinyin, load_phrases_dict
>>> load_phrases_dict({'了局': [['liǎo'], ['']]})
>>> pinyin('了局啊') # 使用 jieba 分词
Building prefix dict from the default dictionary ...
Dumping model to file cache /var/folders/s6/z9r_07h53pj_d4x7qjszwmbw0000gn/T/jieba.cache
Loading model cost 1.175 seconds.
Prefix dict has been built succesfully.
[['le'], [''], ['a']]
>>> from pypinyin.contrib.mmseg import seg, retrain
>>> retrain(seg) # 没有使用 load_phrases_dict 时可以不调用这个函数
>>> pinyin(seg.cut('了局啊')) # 使用内置的最大匹配分词
[['liǎo'], [''], ['a']]
>>>
33 changes: 33 additions & 0 deletions docs/usage.rst
Expand Up @@ -72,6 +72,19 @@
如果需要处理多音字问题,推荐同时安装其他分词模块。

* 同时也内置了一个基于最大匹配分词的分词模块(使用内置的词语拼音库来训练该分词)。

.. code-block:: python
>>> from pypinyin import pinyin, load_phrases_dict
>>> load_phrases_dict({'了局': [['liǎo'], ['']]})
>>> pinyin('了局啊')
[['le'], [''], ['a']]
>>>
>>> from pypinyin.contrib.mmseg import seg
>>> pinyin(seg.cut('了局啊')) # 使用内置的最大匹配分词
[['liǎo'], [''], ['a']]
* | 如果安装了 `jieba <https://github.com/fxsjy/jieba>`__ 分词模块,程序会自动调用,
| 也可以使用经过 ``jieba`` 分词处理的 **字符串列表** 作参数。
Expand Down Expand Up @@ -134,6 +147,26 @@
['ha2i', 'me2i']
**使用内置的最大匹配分词模块**

.. code-block:: python
>>> from pypinyin import pinyin, load_phrases_dict
>>> load_phrases_dict({'了局': [['liǎo'], ['']]})
>>> pinyin('了局啊') # 使用 jieba 分词
Building prefix dict from the default dictionary ...
Dumping model to file cache /var/folders/s6/z9r_07h53pj_d4x7qjszwmbw0000gn/T/jieba.cache
Loading model cost 1.175 seconds.
Prefix dict has been built succesfully.
[['le'], [''], ['a']]
>>> from pypinyin.contrib.mmseg import seg, retrain
>>> retrain(seg) # 没有使用 load_phrases_dict 时可以不调用这个函数
>>> pinyin(seg.cut('了局啊')) # 使用内置的最大匹配分词
[['liǎo'], [''], ['a']]
>>>
自定义拼音风格
----------------

Expand Down
Empty file added pypinyin/contrib/__init__.py
Empty file.
98 changes: 98 additions & 0 deletions pypinyin/contrib/mmseg.py
@@ -0,0 +1,98 @@
# -*- coding: utf-8 -*-
"""最大正向匹配分词"""
from pypinyin.core import PHRASES_DICT


class Seg(object):
"""最大正向匹配分词
:type prefix_set: PrefixSet
"""
def __init__(self, prefix_set):
self._prefix_set = prefix_set

def cut(self, text):
"""分词
:param text: 待分词的文本
:yield: 单个词语
"""
remain = text
while remain:
matched = ''
# 一次加一个字的匹配
for index in range(len(remain)):
word = remain[:index + 1]
if word in self._prefix_set:
matched = word
else:
# 前面的字符串是个词语
if matched:
yield matched
matched = ''
remain = remain[index:]
else: # 前面为空
yield word
remain = remain[index + 1:]
# 有结果了,剩余的重新开始匹配
break
else: # 整个文本就是一个词语
yield remain
break

def train(self, words):
"""训练分词器
:param words: 词语列表
"""
self._prefix_set.train(words)


class PrefixSet(object):
def __init__(self):
self._set = set()

def train(self, word_s):
"""更新 prefix set
:param word_s: 词语库列表
:type word_s: iterable
:return: None
"""
for word in word_s:
# 把词语的每个前缀更新到 prefix_set 中
for index in range(len(word)):
self._set.add(word[:index + 1])

def __contains__(self, key):
return key in self._set


p_set = PrefixSet()
p_set.train(PHRASES_DICT.keys())

#: 基于内置词库的最大正向匹配分词器。使用::
#:
#: >>> from pypinyin.contrib.mmseg import seg
#: >>> text = '你好,我是中国人,我爱我的祖国'
#: >>> seg.cut(text)
#: <generator object Seg.cut at 0x10b2df2b0>
#: >>> list(seg.cut(text))
#: ['你好', ',', '我', '是', '中国人', ',', '我', '爱',
#: '我的', '祖', '国']
#: >>> seg.train(['祖国', '我是'])
#: >>> list(seg.cut(text))
#: ['你好', ',', '我是', '中国人', ',', '我', '爱',
#: '我的', '祖国']
#: >>>
seg = Seg(p_set)


def retrain(seg_instance):
"""重新使用内置词典训练 seg_instance。
比如在增加自定义词语信息后需要调用这个模块重新训练分词器
:type seg_instance: Seg
"""
seg_instance.train(PHRASES_DICT.keys())
1 change: 1 addition & 0 deletions setup.py
Expand Up @@ -19,6 +19,7 @@

packages = [
'pypinyin',
'pypinyin.contrib',
'pypinyin.style',
]

Expand Down
1 change: 1 addition & 0 deletions tests/contrib/__init__.py
@@ -0,0 +1 @@
# -*- coding: utf-8 -*-

0 comments on commit a8aa9bd

Please sign in to comment.