diff --git a/.travis.yml b/.travis.yml index 5edc832d1..a44fee55c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,17 +3,21 @@ language: python python: - - "2.7" - "3.4" - "3.5" - "3.6" # command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors -install: pip install -U tox +install: + - pip install -r requirements-travis.txt + - pip install coveralls os: - linux # command to run tests, e.g. python setup.py test -script: python setup.py test +script: + coverage run --source=pythainlp setup.py test +after_success: + coveralls # After you create the Github repo and add it to Travis, run the # travis_pypi_setup.py script to finish PyPI deployment setup diff --git a/AUTHORS.rst b/AUTHORS.rst index 1f70fce22..842282fe7 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -7,6 +7,11 @@ Development Lead * Wannaphong Phatthiyaphaibun +TCC & THAI SOUNDEX CODE +------------ + +* Korakot Chaovavanich + Contributors ------------ diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst deleted file mode 100644 index 5ecdb094c..000000000 --- a/CONTRIBUTING.rst +++ /dev/null @@ -1,114 +0,0 @@ -.. highlight:: shell - -============ -Contributing -============ - -Contributions are welcome, and they are greatly appreciated! Every -little bit helps, and credit will always be given. - -You can contribute in many ways: - -Types of Contributions ----------------------- - -Report Bugs -~~~~~~~~~~~ - -Report bugs at https://github.com/wannaphongcom/pythainlp/issues. - -If you are reporting a bug, please include: - -* Your operating system name and version. -* Any details about your local setup that might be helpful in troubleshooting. -* Detailed steps to reproduce the bug. - -Fix Bugs -~~~~~~~~ - -Look through the GitHub issues for bugs. Anything tagged with "bug" -and "help wanted" is open to whoever wants to implement it. - -Implement Features -~~~~~~~~~~~~~~~~~~ - -Look through the GitHub issues for features. Anything tagged with "enhancement" -and "help wanted" is open to whoever wants to implement it. - -Write Documentation -~~~~~~~~~~~~~~~~~~~ - -PyThai-NLP could always use more documentation, whether as part of the -official PyThai-NLP docs, in docstrings, or even on the web in blog posts, -articles, and such. - -Submit Feedback -~~~~~~~~~~~~~~~ - -The best way to send feedback is to file an issue at https://github.com/wannaphongcom/pythainlp/issues. - -If you are proposing a feature: - -* Explain in detail how it would work. -* Keep the scope as narrow as possible, to make it easier to implement. -* Remember that this is a volunteer-driven project, and that contributions - are welcome :) - -Get Started! ------------- - -Ready to contribute? Here's how to set up `pythainlp` for local development. - -1. Fork the `pythainlp` repo on GitHub. -2. Clone your fork locally:: - - $ git clone git@github.com:your_name_here/pythainlp.git - -3. Install your local copy into a virtualenv. Assuming you have virtualenvwrapper installed, this is how you set up your fork for local development:: - - $ mkvirtualenv pythainlp - $ cd pythainlp/ - $ python setup.py develop - -4. Create a branch for local development:: - - $ git checkout -b name-of-your-bugfix-or-feature - - Now you can make your changes locally. - -5. When you're done making changes, check that your changes pass flake8 and the tests, including testing other Python versions with tox:: - - $ flake8 pythainlp tests - $ python setup.py test or py.test - $ tox - - To get flake8 and tox, just pip install them into your virtualenv. - -6. Commit your changes and push your branch to GitHub:: - - $ git add . - $ git commit -m "Your detailed description of your changes." - $ git push origin name-of-your-bugfix-or-feature - -7. Submit a pull request through the GitHub website. - -Pull Request Guidelines ------------------------ - -Before you submit a pull request, check that it meets these guidelines: - -1. The pull request should include tests. -2. If the pull request adds functionality, the docs should be updated. Put - your new functionality into a function with a docstring, and add the - feature to the list in README.rst. -3. The pull request should work for Python 2.6, 2.7, 3.3, 3.4 and 3.5, and for PyPy. Check - https://travis-ci.org/wannaphongcom/pythainlp/pull_requests - and make sure that the tests pass for all supported Python versions. - -Tips ----- - -To run a subset of tests:: - - - $ python -m unittest tests.test_pythainlp diff --git a/README.md b/README.md index 638cd5dd5..73ac0d84c 100644 --- a/README.md +++ b/README.md @@ -2,18 +2,85 @@ [![PyPI Downloads](https://img.shields.io/pypi/dm/pythainlp.png)] [![pypi](https://img.shields.io/pypi/v/pythainlp.svg)](https://pypi.python.org/pypi/pythainlp) [![Build Status](https://travis-ci.org/wannaphongcom/pythainlp.svg?branch=develop)](https://travis-ci.org/wannaphongcom/pythainlp) -[![Build status](https://ci.appveyor.com/api/projects/status/uxerymgggp1uch0p?svg=true)](https://ci.appveyor.com/project/wannaphongcom/pythainlp) +[![Build status](https://ci.appveyor.com/api/projects/status/uxerymgggp1uch0p?svg=true)](https://ci.appveyor.com/project/wannaphongcom/pythainlp)[![Code Issues](https://www.quantifiedcode.com/api/v1/project/7f699ed4cad24be18d0d24ebd60d7543/badge.svg)](https://www.quantifiedcode.com/app/project/7f699ed4cad24be18d0d24ebd60d7543)[![Coverage Status](https://coveralls.io/repos/github/wannaphongcom/pythainlp/badge.svg?branch=pythainlp1.4)](https://coveralls.io/github/wannaphongcom/pythainlp?branch=pythainlp1.4) +## English -Homepages :[https://sites.google.com/view/pythainlp/home](https://sites.google.com/view/pythainlp/home) +Thai natural language processing in Python. + +PyThaiNLP is python module like nltk , but It's working with thai language. + +It's support python 3.4 +. + +### Project status + +Developing + +### Version + +1.4 + +### Capability + +- Thai segment +- Thai wordnet +- Thai Character Clusters (TCC) and ETCC +- Thai stop word +- Thai meta sound +- Thai soundex +- Thai postaggers +- Thai romanization +- Check the wrong words in Thai. + +and much more. + +### Install + +**using pip.** + +```sh +$ pip install pythainlp +``` + +**Install in Windows** + +download pyicu from [http://www.lfd.uci.edu/~gohlke/pythonlibs/#pyicu](http://www.lfd.uci.edu/~gohlke/pythonlibs/#pyicu) than install pyicu. install pythainlp using pip. + +``` +pip install pythainlp +``` + +**Install in MacOS** + +```sh +$ brew install icu4c --force +$ brew link --force icu4c +$ CFLAGS=-I/usr/local/opt/icu4c/include LDFLAGS=-L/usr/local/opt/icu4c/lib pip install pythainlp +``` + +### Documentation + +Read on https://github.com/wannaphongcom/pythainlp/blob/pythainlp1.4/docs/pythainlp-1-4-eng.md + +### License + +Apache Software License 2.0 + +## ภาษาไทย + +[![PyPI Downloads](https://img.shields.io/pypi/dm/pythainlp.png)] +[![pypi](https://img.shields.io/pypi/v/pythainlp.svg)](https://pypi.python.org/pypi/pythainlp) +[![Build Status](https://travis-ci.org/wannaphongcom/pythainlp.svg?branch=develop)](https://travis-ci.org/wannaphongcom/pythainlp) +[![Build status](https://ci.appveyor.com/api/projects/status/uxerymgggp1uch0p?svg=true)](https://ci.appveyor.com/project/wannaphongcom/pythainlp)[![Code Issues](https://www.quantifiedcode.com/api/v1/project/7f699ed4cad24be18d0d24ebd60d7543/badge.svg)](https://www.quantifiedcode.com/app/project/7f699ed4cad24be18d0d24ebd60d7543)[![Coverage Status](https://coveralls.io/repos/github/wannaphongcom/pythainlp/badge.svg?branch=pythainlp1.4)](https://coveralls.io/github/wannaphongcom/pythainlp?branch=pythainlp1.4) ประมวลภาษาธรรมชาติภาษาไทยในภาษา Python -Natural language processing หรือ การประมวลภาษาธรรมชาติ โมดูล PyThaiNLP เป็นโมดูลที่ถูกพัฒนาขึ้นเพื่องานวิจัยและพัฒนาการประมวลภาษาธรรมชาติภาษาไทยในภาษา Python +Natural language processing หรือ การประมวลภาษาธรรมชาติ โมดูล PyThaiNLP เป็นโมดูลที่ถูกพัฒนาขึ้นเพื่อพัฒนาการประมวลภาษาธรรมชาติภาษาไทยในภาษา Python และ**มันฟรี (ตลอดไป) เพื่อคนไทยและชาวโลกทุกคน !** + +> เพราะโลกขับเคลื่อนต่อไปด้วยการแบ่งปัน รองรับ Python 3.4 ขึ้นไป - - เอกสารการใช้งาน : [https://sites.google.com/view/pythainlp/home](https://sites.google.com/view/pythainlp/home) - หน้าหลัก GitHub : [https://github.com/wannaphongcom/pythainlp](https://github.com/wannaphongcom/pythainlp) ### สถานะโครงการ @@ -21,7 +88,15 @@ Natural language processing หรือ การประมวลภาษา กำลังพัฒนา ### Version -1.3 +1.4 + +### สิ่งใหม่ที่เพิ่มเข้ามาใน PyThaiNLP 1.4 + +- รองรับ Thai Character Clusters (TCC) และ ETCC +- Thai WordNet ตัวใหม่ +- เพิ่มหลักเกณฑ์การถอดอักษรไทยเป็นอักษรโรมัน ฉบับราชบัณฑิตยสถาน +- เพิ่ม Meta Sound ภาษาไทย +- เพิ่ม Thai Soundex ### ความสามารถ - ตัดคำภาษาไทย @@ -31,9 +106,14 @@ Natural language processing หรือ การประมวลภาษา - เรียงจำนวนคำของประโยค - แก้ไขปัญหาการพิมพ์ลืมเปลี่ยนภาษา - เช็คคำผิดในภาษาไทย + - รองรับ Thai Character Clusters (TCC) และ ETCC + - Thai WordNet + - Stop Word ภาษาไทย + - Meta Sound ภาษาไทย + - Thai Soundex - และอื่น ๆ -# ติดตั้ง +### ติดตั้ง รองรับ Python 3.4 ขึ้นไป @@ -70,9 +150,9 @@ $ CFLAGS=-I/usr/local/opt/icu4c/include LDFLAGS=-L/usr/local/opt/icu4c/lib pip i ข้อมูลเพิ่มเติม [คลิกที่นี้](https://medium.com/data-science-cafe/install-polyglot-on-mac-3c90445abc1f#.rdfrorxjx) -# เอกสารการใช้งานเบื้องต้น +### เอกสารการใช้งาน -อ่านได้ที่ https://github.com/wannaphongcom/pythainlp/blob/master/docs/pythainlp-1-3-thai.md +อ่านได้ที่ https://github.com/wannaphongcom/pythainlp/blob/pythainlp1.4/docs/pythainlp-1-4-thai.md ### License diff --git a/References.md b/References.md new file mode 100644 index 000000000..1e29854a3 --- /dev/null +++ b/References.md @@ -0,0 +1,5 @@ +# References + +Snae & Brückner. (2009). Novel Phonetic Name Matching Algorithm with a Statistical Ontology for Analysing Names Given in Accordance with Thai Astrology. Retrieved from https://pdfs.semanticscholar.org/3983/963e87ddc6dfdbb291099aa3927a0e3e4ea6.pdf + +T. Teeramunkong, V. Sornlertlamvanich, T. Tanhermhong and W. Chinnan, “Character cluster based Thai information retrieval,” in IRAL '00 Proceedings of the fifth international workshop on on Information retrieval with Asian languages, 2000. \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index 51d87df9e..c9efefcc9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,97 +1,20 @@ -environment: - global: - # SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the - # /E:ON and /V:ON options are not enabled in the batch script intepreter - # See: http://stackoverflow.com/a/13751649/163740 - CMD_IN_ENV: "cmd /E:ON /V:ON /C .\\appveyor\\run_with_env.cmd" +build: false +environment: matrix: - # Pre-installed Python versions, which Appveyor may upgrade to - # a later point release. - # See: http://www.appveyor.com/docs/installed-software#python - - - PYTHON: "C:\\Python27" - PYTHON_VERSION: "2.7.x" # currently 2.7.9 - PYTHON_ARCH: "32" - - - PYTHON: "C:\\Python27-x64" - PYTHON_VERSION: "2.7.x" # currently 2.7.9 - PYTHON_ARCH: "64" - - - PYTHON: "C:\\Python34" - PYTHON_VERSION: "3.4.x" # currently 3.4.3 - PYTHON_ARCH: "32" + - PYTHON: "C:/Python35" + - PYTHON: "C:/Python36" - - PYTHON: "C:\\Python34-x64" - PYTHON_VERSION: "3.4.x" # currently 3.4.3 - PYTHON_ARCH: "64" - - - PYTHON: "C:\\Python35" - PYTHON_VERSION: "3.5.x" # currently 3.4.3 - PYTHON_ARCH: "32" - - - PYTHON: "C:\\Python35-x64" - PYTHON_VERSION: "3.5.x" # currently 3.4.3 - PYTHON_ARCH: "64" +init: + - "ECHO %PYTHON%" + - ps: "ls C:/Python*" install: - # If there is a newer build queued for the same PR, cancel this one. - # The AppVeyor 'rollout builds' option is supposed to serve the same - # purpose but it is problematic because it tends to cancel builds pushed - # directly to master instead of just PR builds (or the converse). - # credits: JuliaLang developers. - - ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod ` - https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | ` - Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { ` - throw "There are newer queued builds for this pull request, failing early." } - - ECHO "Filesystem root:" - - ps: "ls \"C:/\"" - - - ECHO "Installed SDKs:" - - ps: "ls \"C:/Program Files/Microsoft SDKs/Windows\"" - - # Install Python (from the official .msi of http://python.org) and pip when - # not already installed. - - ps: if (-not(Test-Path($env:PYTHON))) { & appveyor\install.ps1 } - - # Prepend newly installed Python to the PATH of this build (this cannot be - # done from inside the powershell script as it would require to restart - # the parent CMD process). - - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" - - # Check that we have the expected version and architecture for Python - - "python --version" - - "python -c \"import struct; print(struct.calcsize('P') * 8)\"" - - # Upgrade to the latest version of pip to avoid it displaying warnings - # about it being out of date. - - "pip install --disable-pip-version-check --user --upgrade pip" - - # Install the build dependencies of the project. If some dependencies contain - # compiled extensions and are not provided as pre-built wheel packages, - # pip will build them from source using the MSVC compiler matching the - # target Python version and architecture - - "%CMD_IN_ENV% pip install -r dev-requirements.txt" - -build_script: - # Build the compiled extension - - "%CMD_IN_ENV% python setup.py build" + # FIXME: updating pip fails with PermissionError + # - "%PYTHON%/Scripts/pip.exe install -U pip setuptools" + - "%PYTHON%/Scripts/pip.exe install -e ." test_script: - # Run the project tests - - "%CMD_IN_ENV% python setup.py nosetests" - -after_test: - # If tests are successful, create binary packages for the project. - - "%CMD_IN_ENV% python setup.py bdist_wheel" - - "%CMD_IN_ENV% python setup.py bdist_wininst" - - "%CMD_IN_ENV% python setup.py bdist_msi" - - ps: "ls dist" - -artifacts: - # Archive the generated packages in the ci.appveyor.com build report. - - path: dist\* - -#on_success: -# - TODO: upload the content of dist/*.whl to a public wheelhouse -# + - "%PYTHON%/Scripts/pip.exe --version" + - "%PYTHON%/Scripts/http.exe --debug" + - "%PYTHON%/python.exe setup.py test" diff --git a/docs/pythainlp-1-4-eng.md b/docs/pythainlp-1-4-eng.md new file mode 100644 index 000000000..656e29480 --- /dev/null +++ b/docs/pythainlp-1-4-eng.md @@ -0,0 +1,307 @@ +# User manual PyThaiNLP 1.4 + +## API + +### Thai segment + +```python +from pythainlp.tokenize import word_tokenize +word_tokenize(text,engine) +``` +**text** is thai text. + +**engine** is thai segment system have 6 engine + +1. icu - using pyicu. (default) +2. dict - using dict . returns False if the message can not be wrapped. +3. mm - using Maximum Matching algorithm in thai segment. +4. newmm - using Maximum Matching algorithm in thai segment. credit Korakot Chaovavanich from https://www.facebook.com/groups/408004796247683/permalink/431283740586455/ +5. pylexto using LexTo in thai segment. +6. deepcut using deepcut from https://github.com/rkcosmos/deepcut in thai segment. + +returns ''list'' ex. ['แมว','กิน'] + +**ตัวอย่าง** + +```python +from pythainlp.tokenize import word_tokenize +text='ผมรักคุณนะครับโอเคบ่พวกเราเป็นคนไทยรักภาษาไทยภาษาบ้านเกิด' +a=word_tokenize(text,engine='icu') # ['ผม', 'รัก', 'คุณ', 'นะ', 'ครับ', 'โอ', 'เค', 'บ่', 'พวก', 'เรา', 'เป็น', 'คน', 'ไทย', 'รัก', 'ภาษา', 'ไทย', 'ภาษา', 'บ้าน', 'เกิด'] +b=word_tokenize(text,engine='dict') # ['ผม', 'รัก', 'คุณ', 'นะ', 'ครับ', 'โอเค', 'บ่', 'พวกเรา', 'เป็น', 'คนไทย', 'รัก', 'ภาษาไทย', 'ภาษา', 'บ้านเกิด'] +c=word_tokenize(text,engine='mm') # ['ผม', 'รัก', 'คุณ', 'นะ', 'ครับ', 'โอเค', 'บ่', 'พวกเรา', 'เป็น', 'คนไทย', 'รัก', 'ภาษาไทย', 'ภาษา', 'บ้านเกิด'] +d=word_tokenize(text,engine='pylexto') # ['ผม', 'รัก', 'คุณ', 'นะ', 'ครับ', 'โอเค', 'บ่', 'พวกเรา', 'เป็น', 'คนไทย', 'รัก', 'ภาษาไทย', 'ภาษา', 'บ้านเกิด'] +e=word_tokenize(text,engine='newmm') # ['ผม', 'รัก', 'คุณ', 'นะ', 'ครับ', 'โอเค', 'บ่', 'พวกเรา', 'เป็น', 'คนไทย', 'รัก', 'ภาษาไทย', 'ภาษา', 'บ้านเกิด'] +``` + +### Thai postaggers + +```python +from pythainlp.tag import pos_tag +pos_tag(list,engine='old') +``` + +engine + +1. old is UnigramTagger (default) +2. artagger is RDR POS Tagger. + +### Thai romanization + +```python +from pythainlp.romanization import romanization +romanization(str,engine='pyicu') +``` +It's have 2 engine + +- pyicu +- royin + +data : + +input ''str'' + +returns ''str'' + +**Example** + +```python +from pythainlp.romanization import romanization +romanization("แมว") # 'mæw' +``` + +### Check the wrong word + +Before using this ability. Install hunspell and hunspell-th first. + +```python +from pythainlp.spell import * +a=spell("สี่เหลียม") +print(a) # ['สี่เหลี่ยม', 'เสียเหลี่ยม', 'เหลี่ยม'] +``` +### pythainlp.number + +```python +from pythainlp.number import * +``` +- nttn(str) - To convert thai numbers to numbers. +- nttt(str) - Thai Numbers to text. +- ntnt(str) - numbers to thai numbers. +- ntt(str) - numbers to text. +- ttn(str) - text to numbers. +- numtowords(float) - Read thai numbers (Baht) input ''float'' returns 'str' + +### Sorting List of Thai Information in List + +```python +from pythainlp.collation import collation +print(collation(['ไก่','ไข่','ก','ฮา'])) # ['ก', 'ไก่', 'ไข่', 'ฮา'] +``` + +input list + +returns list + +### Get current time in Thai + +```python +from pythainlp.date import now +now() # '30 พฤษภาคม 2560 18:45:24' +``` +### Thai WordNet + +import + +```python +from pythainlp.corpus import wordnet +``` + +**Use** + +It's like nltk. + +- wordnet.synsets(word) +- wordnet.synset(name_synsets) +- wordnet.all_lemma_names(pos=None, lang="tha") +- wordnet.all_synsets(pos=None) +- wordnet.langs() +- wordnet.lemmas(word,pos=None,lang="tha") +- wordnet.lemma(name_synsets) +- wordnet.lemma_from_key(key) +- wordnet.path_similarity(synsets1,synsets2) +- wordnet.lch_similarity(synsets1,synsets2) +- wordnet.wup_similarity(synsets1,synsets2) +- wordnet.morphy(form, pos=None) +- wordnet.custom_lemmas(tab_file, lang) + +**Example** + +```python +>>> from pythainlp.corpus import wordnet +>>> print(wordnet.synsets('หนึ่ง')) +[Synset('one.s.05'), Synset('one.s.04'), Synset('one.s.01'), Synset('one.n.01')] +>>> print(wordnet.synsets('หนึ่ง')[0].lemma_names('tha')) +[] +>>> print(wordnet.synset('one.s.05')) +Synset('one.s.05') +>>> print(wordnet.synset('spy.n.01').lemmas()) +[Lemma('spy.n.01.spy'), Lemma('spy.n.01.undercover_agent')] +>>> print(wordnet.synset('spy.n.01').lemma_names('tha')) +['สปาย', 'สายลับ'] +``` + +### Find words with the most usage. + +```python +from pythainlp.rank import rank +rank(list) +``` + +returns dict + +**Example** + +```python +>>> rank(['แมง','แมง','คน']) +Counter({'แมง': 2, 'คน': 1}) +``` + +### Solve printing problems forget to change language + +```python +from pythainlp.change import * +``` + +- texttothai(str) - eng to thai. +- texttoeng(str) - thai to eng. + +### Thai Character Clusters (TCC) + +TCC : Mr.Jakkrit TeCho + +grammar : Wittawat Jitkrittum (https://github.com/wittawatj/jtcc/blob/master/TCC.g) + +Code : Korakot Chaovavanich + +**Example** + +```python +>>> from pythainlp.tokenize import tcc +>>> tcc.tcc('ประเทศไทย') +'ป/ระ/เท/ศ/ไท/ย' +``` + +### Enhanced Thai Character Cluster (ETCC) + +**Example** + +```python +>>> from pythainlp.tokenize import etcc +>>> etcc.etcc('คืนความสุข') +'/คืน/ความสุข' +``` + +### Thai Soundex + +credit Korakot Chaovavanich (from https://gist.github.com/korakot/0b772e09340cac2f493868da035597e8) + +- LK82 +- Udom83 + +**Example** + +```python +>>> from pythainlp.soundex import LK82 +>>> print(LK82('รถ')) +ร3000 +>>> print(LK82('รด')) +ร3000 +>>> print(LK82('จัน')) +จ4000 +>>> print(LK82('จันทร์')) +จ4000 +>>> print(Udom83('รถ')) +ร800000 +``` + +### Thai meta sound + +``` +Snae & Brückner. (2009). Novel Phonetic Name Matching Algorithm with a Statistical Ontology for Analysing Names Given in Accordance with Thai Astrology. Retrieved from https://pdfs.semanticscholar.org/3983/963e87ddc6dfdbb291099aa3927a0e3e4ea6.pdf +``` + +**Example** + +```python +>>> from pythainlp.MetaSound import * +>>> MetaSound('คน') +'15' +``` + +### Thai sentiment analysis + +using data from [https://github.com/wannaphongcom/lexicon-thai/tree/master/ข้อความ/](https://github.com/wannaphongcom/lexicon-thai/tree/master/ข้อความ/) + +```python +from pythainlp.sentiment import sentiment +sentiment(str) +``` + +input str returns pos , neg or neutral + +### Util + +using + +```python +from pythainlp.util import * +``` + +#### ngrams + +for building ngrams + +```python +ngrams(token,num) +``` + +- token - list +- num - ngrams + +### Corpus + +#### Thai stopword + +```python +from pythainlp.corpus import stopwords +stopwords = stopwords.words('thai') +``` + +#### Thai country name + +```python +from pythainlp.corpus import country +country.get_data() +``` + +#### Tone in Thai + +```python +from pythainlp.corpus import tone +tone.get_data() +``` + +#### Consonant in thai + +```python +from pythainlp.corpus import alphabet +alphabet.get_data() +``` + +#### Word list in thai + +```python +from pythainlp.corpus.thaiword import get_data # old data +get_data() +from pythainlp.corpus.newthaiword import get_data # new data +get_data() +``` diff --git a/docs/pythainlp-1-4-thai.md b/docs/pythainlp-1-4-thai.md new file mode 100644 index 000000000..35a3f7f97 --- /dev/null +++ b/docs/pythainlp-1-4-thai.md @@ -0,0 +1,373 @@ +# คู่มือการใช้งาน PyThaiNLP 1.4 + +Natural language processing หรือ การประมวลภาษาธรรมชาติ โมดูล PyThaiNLP เป็นโมดูลที่ถูกพัฒนาขึ้นเพื่อพัฒนาการประมวลภาษาธรรมชาติภาษาไทยในภาษา Python และ**มันฟรี (ตลอดไป) เพื่อคนไทยและชาวโลกทุกคน !** + +> เพราะโลกขับเคลื่อนต่อไปด้วยการแบ่งปัน + +รองรับเฉพาะ Python 3.4 ขึ้นไปเท่านั้น + +ติดตั้งใช้คำสั่ง + +``` +pip install pythainlp +``` + +**วิธีติดตั้งสำหรับ Windows** + +ให้ทำการติดตั้ง pyicu โดยใช้ไฟล์ .whl จาก [http://www.lfd.uci.edu/~gohlke/pythonlibs/#pyicu](http://www.lfd.uci.edu/~gohlke/pythonlibs/#pyicu) + +หากใช้ python 3.5 64 bit ให้โหลด PyICU‑1.9.7‑cp35‑cp35m‑win_amd64.whl แล้วเปิด cmd ใช้คำสั่ง + +``` +pip install PyICU‑1.9.7‑cp35‑cp35m‑win_amd64.whl +``` + +แล้วจึงใช้ + +``` +pip install pythainlp +``` + +**ติดตั้งบน Mac** + +```sh +$ brew install icu4c --force +$ brew link --force icu4c +$ CFLAGS=-I/usr/local/opt/icu4c/include LDFLAGS=-L/usr/local/opt/icu4c/lib pip install pythainlp +``` + +ข้อมูลเพิ่มเติม [คลิกที่นี้](https://medium.com/data-science-cafe/install-polyglot-on-mac-3c90445abc1f#.rdfrorxjx) + +## API + +### ตัดคำไทย + +สำหรับการตัดคำไทยนั้น ใช้ API ดังต่อไปนี้ + +```python +from pythainlp.tokenize import word_tokenize +word_tokenize(text,engine) +``` +text คือ ข้อความในรูปแบบสตริง str เท่านั้น + +engine คือ ระบบตัดคำไทย ปัจจุบันนี้ PyThaiNLP ได้พัฒนามี 6 engine ให้ใช้งานกันดังนี้ + +1. icu - engine ตัวดั้งเดิมของ PyThaiNLP (ความแม่นยำต่ำ) และเป็นค่าเริ่มต้น +2. dict - เป็นการตัดคำโดยใช้พจานุกรมจาก thaiword.txt ใน corpus (ความแม่นยำปานกลาง) จะคืนค่า False หากข้อความนั้นไม่สามารถตัดคำได้ +3. mm - ใช้ Maximum Matching algorithm ในการตัดคำภาษาไทย - API ชุดเก่า +4. newmm - ใช้ Maximum Matching algorithm ในการตัดคำภาษาไทย โค้ดชุดใหม่ โดยใช้โค้ดคุณ Korakot Chaovavanich จาก https://www.facebook.com/groups/408004796247683/permalink/431283740586455/ มาพัฒนาต่อ +5. pylexto ใช้ LexTo ในการตัดคำ +6. deepcut ใช้ deepcut จาก https://github.com/rkcosmos/deepcut ในการตัดคำภาษาไทย + +คืนค่าเป็น ''list'' เช่น ['แมว','กิน'] + +**ตัวอย่าง** + +```python +from pythainlp.tokenize import word_tokenize +text='ผมรักคุณนะครับโอเคบ่พวกเราเป็นคนไทยรักภาษาไทยภาษาบ้านเกิด' +a=word_tokenize(text,engine='icu') # ['ผม', 'รัก', 'คุณ', 'นะ', 'ครับ', 'โอ', 'เค', 'บ่', 'พวก', 'เรา', 'เป็น', 'คน', 'ไทย', 'รัก', 'ภาษา', 'ไทย', 'ภาษา', 'บ้าน', 'เกิด'] +b=word_tokenize(text,engine='dict') # ['ผม', 'รัก', 'คุณ', 'นะ', 'ครับ', 'โอเค', 'บ่', 'พวกเรา', 'เป็น', 'คนไทย', 'รัก', 'ภาษาไทย', 'ภาษา', 'บ้านเกิด'] +c=word_tokenize(text,engine='mm') # ['ผม', 'รัก', 'คุณ', 'นะ', 'ครับ', 'โอเค', 'บ่', 'พวกเรา', 'เป็น', 'คนไทย', 'รัก', 'ภาษาไทย', 'ภาษา', 'บ้านเกิด'] +d=word_tokenize(text,engine='pylexto') # ['ผม', 'รัก', 'คุณ', 'นะ', 'ครับ', 'โอเค', 'บ่', 'พวกเรา', 'เป็น', 'คนไทย', 'รัก', 'ภาษาไทย', 'ภาษา', 'บ้านเกิด'] +e=word_tokenize(text,engine='newmm') # ['ผม', 'รัก', 'คุณ', 'นะ', 'ครับ', 'โอเค', 'บ่', 'พวกเรา', 'เป็น', 'คนไทย', 'รัก', 'ภาษาไทย', 'ภาษา', 'บ้านเกิด'] +``` + +### Postaggers ภาษาไทย + +```python +from pythainlp.tag import pos_tag +pos_tag(list,engine='old') +``` + +list คือ list ที่เก็บข้อความหลังผ่านการตัดคำแล้ว + +engine คือ ชุดเครื่องมือในการ postaggers มี 2 ตัวดังนี้ + +1. old เป็น UnigramTagger (ค่าเริ่มต้น) +2. artagger เป็น RDR POS Tagger ละเอียดยิ่งกว่าเดิม รองรับเฉพาะ Python 3 เท่านั้น + +### แปลงข้อความเป็น Latin + +```python +from pythainlp.romanization import romanization +romanization(str,engine='pyicu') +``` +มี 2 engine ดังนี้ + +- pyicu ส่งค่า Latin +- royin ใช้หลักเกณฑ์การถอดอักษรไทยเป็นอักษรโรมัน ฉบับราชบัณฑิตยสถาน (**หากมีข้อผิดพลาด ให้ใช้คำอ่าน เนื่องจากตัว royin ไม่มีตัวแปลงคำเป็นคำอ่าน**) + +data : + +รับค่า ''str'' ข้อความ + +คืนค่าเป็น ''str'' ข้อความ + +**ตัวอย่าง** + +```python +from pythainlp.romanization import romanization +romanization("แมว") # 'mæw' +``` + +### เช็คคำผิด + +ก่อนใช้งานความสามารถนี้ ให้ทำการติดตั้ง hunspell และ hunspell-th ก่อน + +**วิธีติดตั้ง** สำหรับบน Debian , Ubuntu + +``` +sudo apt-get install hunspell hunspell-th +``` + +บน Mac OS ติดตั้งตามนี้ [http://pankdm.github.io/hunspell.html](http://pankdm.github.io/hunspell.html) + +ให้ใช้ pythainlp.spell ตามตัวอย่างนี้ + +```python +from pythainlp.spell import * +a=spell("สี่เหลียม") +print(a) # ['สี่เหลี่ยม', 'เสียเหลี่ยม', 'เหลี่ยม'] +``` +### pythainlp.number + +```python +from pythainlp.number import * +``` +จัดการกับตัวเลข โดยมีดังนี้ + +- nttn(str) - เป็นการแปลงเลขไทยสู่เลข +- nttt(str) - เลขไทยสู่ข้อความ +- ntnt(str) - เลขสู่เลขไทย +- ntt(str) - เลขสู่ข้อความ +- ttn(str) - ข้อความสู่เลข +- numtowords(float) - อ่านจำนวนตัวเลขภาษาไทย (บาท) รับค่าเป็น ''float'' คืนค่าเป็น 'str' + +### เรียงลำดับข้อมูลภาษาไทยใน List + +```python +from pythainlp.collation import collation +print(collation(['ไก่','ไข่','ก','ฮา'])) # ['ก', 'ไก่', 'ไข่', 'ฮา'] +``` + +รับ list คืนค่า list + +### รับเวลาปัจจุบันเป็นภาษาไทย + +```python +from pythainlp.date import now +now() # '30 พฤษภาคม 2560 18:45:24' +``` +### WordNet ภาษาไทย + +เรียกใช้งาน + +```python +from pythainlp.corpus import wordnet +``` + +**การใช้งาน** + +API เหมือนกับ NLTK โดยรองรับ API ดังนี้ + +- wordnet.synsets(word) +- wordnet.synset(name_synsets) +- wordnet.all_lemma_names(pos=None, lang="tha") +- wordnet.all_synsets(pos=None) +- wordnet.langs() +- wordnet.lemmas(word,pos=None,lang="tha") +- wordnet.lemma(name_synsets) +- wordnet.lemma_from_key(key) +- wordnet.path_similarity(synsets1,synsets2) +- wordnet.lch_similarity(synsets1,synsets2) +- wordnet.wup_similarity(synsets1,synsets2) +- wordnet.morphy(form, pos=None) +- wordnet.custom_lemmas(tab_file, lang) + +**ตัวอย่าง** + +```python +>>> from pythainlp.corpus import wordnet +>>> print(wordnet.synsets('หนึ่ง')) +[Synset('one.s.05'), Synset('one.s.04'), Synset('one.s.01'), Synset('one.n.01')] +>>> print(wordnet.synsets('หนึ่ง')[0].lemma_names('tha')) +[] +>>> print(wordnet.synset('one.s.05')) +Synset('one.s.05') +>>> print(wordnet.synset('spy.n.01').lemmas()) +[Lemma('spy.n.01.spy'), Lemma('spy.n.01.undercover_agent')] +>>> print(wordnet.synset('spy.n.01').lemma_names('tha')) +['สปาย', 'สายลับ'] +``` + +### หาคำที่มีจำนวนการใช้งานมากที่สุด + +```python +from pythainlp.rank import rank +rank(list) +``` + +คืนค่าออกมาเป็น dict + +**ตัวอย่างการใช้งาน** + +```python +>>> rank(['แมง','แมง','คน']) +Counter({'แมง': 2, 'คน': 1}) +``` + +### แก้ไขปัญหาการพิมพ์ลืมเปลี่ยนภาษา + +```python +from pythainlp.change import * +``` + +มีคำสั่งดังนี้ + +- texttothai(str) แปลงแป้นตัวอักษรภาษาอังกฤษเป็นภาษาไทย +- texttoeng(str) แปลงแป้นตัวอักษรภาษาไทยเป็นภาษาอังกฤษ + +คืนค่าออกมาเป็น str + +### Thai Character Clusters (TCC) + +PyThaiNLP 1.4 รองรับ Thai Character Clusters (TCC) โดยจะแบ่งกลุ่มด้วย / + +**เดติด** + +TCC : Mr.Jakkrit TeCho + +grammar : คุณ Wittawat Jitkrittum (https://github.com/wittawatj/jtcc/blob/master/TCC.g) + +โค้ด : คุณ Korakot Chaovavanich + +**การใช้งาน** + +```python +>>> from pythainlp.tokenize import tcc +>>> tcc.tcc('ประเทศไทย') +'ป/ระ/เท/ศ/ไท/ย' +``` + +### Enhanced Thai Character Cluster (ETCC) + +นอกจาก TCC แล้ว PyThaiNLP 1.4 ยังรองรับ Enhanced Thai Character Cluster (ETCC) โดยแบ่งกลุ่มด้วย / + +**การใช้งาน** + +```python +>>> from pythainlp.tokenize import etcc +>>> etcc.etcc('คืนความสุข') +'/คืน/ความสุข' +``` + +### Thai Soundex ภาษาไทย + +เดติด คุณ Korakot Chaovavanich (จาก https://gist.github.com/korakot/0b772e09340cac2f493868da035597e8) + +กฎที่รองรับในเวชั่น 1.4 + +- กฎการเข้ารหัสซาวน์เด็กซ์ของ วิชิตหล่อจีระชุณห์กุล และ เจริญ คุวินทร์พันธุ์ - LK82 +- กฎการเข้ารหัสซาวน์เด็กซ์ของ วรรณี อุดมพาณิชย์ - Udom83 + +**การใช้งาน** + +```python +>>> from pythainlp.soundex import LK82 +>>> print(LK82('รถ')) +ร3000 +>>> print(LK82('รด')) +ร3000 +>>> print(LK82('จัน')) +จ4000 +>>> print(LK82('จันทร์')) +จ4000 +>>> print(Udom83('รถ')) +ร800000 +``` + +### Meta Sound ภาษาไทย + +``` +Snae & Brückner. (2009). Novel Phonetic Name Matching Algorithm with a Statistical Ontology for Analysing Names Given in Accordance with Thai Astrology. Retrieved from https://pdfs.semanticscholar.org/3983/963e87ddc6dfdbb291099aa3927a0e3e4ea6.pdf +``` + +**การใช้งาน** + +```python +>>> from pythainlp.MetaSound import * +>>> MetaSound('คน') +'15' +``` + +### Sentiment analysis ภาษาไทย + +ใช้ข้อมูลจาก [https://github.com/wannaphongcom/lexicon-thai/tree/master/ข้อความ/](https://github.com/wannaphongcom/lexicon-thai/tree/master/ข้อความ/) + +```python +from pythainlp.sentiment import sentiment +sentiment(str) +``` + +รับค่า str ส่งออกเป็น pos , neg หรือ neutral + +### Util + +การใช้งาน + +```python +from pythainlp.util import * +``` + +#### ngrams + +สำหรับสร้าง ngrams + +```python +ngrams(token,num) +``` + +- token คือ list +- num คือ จำนวน ngrams + +### Corpus + +#### stopword ภาษาไทย + +```python +from pythainlp.corpus import stopwords +stopwords = stopwords.words('thai') +``` + +#### ชื่อประเทศ ภาษาไทย + +```python +from pythainlp.corpus import country +country.get_data() +``` + +#### ตัววรรณยุกต์ในภาษาไทย + +```python +from pythainlp.corpus import tone +tone.get_data() +``` + +#### ตัวพยัญชนะในภาษาไทย + +```python +from pythainlp.corpus import alphabet +alphabet.get_data() +``` + +#### รายการคำในภาษาไทย + +```python +from pythainlp.corpus.thaiword import get_data # ข้อมูลเก่า +get_data() +from pythainlp.corpus.newthaiword import get_data # ข้อมูลใหม่ +get_data() +``` + +เขียนโดย นาย วรรณพงษ์ ภัททิยไพบูลย์ \ No newline at end of file diff --git "a/docs/\340\270\247\340\270\264\340\270\230\340\270\265\340\270\225\340\270\264\340\270\224\340\270\225\340\270\261\340\271\211\340\270\207 PyThaiNLP \340\271\200\340\270\247\340\270\212\340\270\261\340\271\210\340\270\231\340\270\245\340\271\210\340\270\262\340\270\252\340\270\270\340\270\224\340\270\210\340\270\262\340\270\201 GitHub.md" "b/docs/\340\270\247\340\270\264\340\270\230\340\270\265\340\270\225\340\270\264\340\270\224\340\270\225\340\270\261\340\271\211\340\270\207 PyThaiNLP \340\271\200\340\270\247\340\270\212\340\270\261\340\271\210\340\270\231\340\270\245\340\271\210\340\270\262\340\270\252\340\270\270\340\270\224\340\270\210\340\270\262\340\270\201 GitHub.md" new file mode 100644 index 000000000..2357c6ccb --- /dev/null +++ "b/docs/\340\270\247\340\270\264\340\270\230\340\270\265\340\270\225\340\270\264\340\270\224\340\270\225\340\270\261\340\271\211\340\270\207 PyThaiNLP \340\271\200\340\270\247\340\270\212\340\270\261\340\271\210\340\270\231\340\270\245\340\271\210\340\270\262\340\270\252\340\270\270\340\270\224\340\270\210\340\270\262\340\270\201 GitHub.md" @@ -0,0 +1,7 @@ +# วิธีติดตั้ง PyThaiNLP เวชั่นล่าสุดจาก GitHub + +ใช้คำสั่งนี้ในคอมมาไลน์ + +``` +pip install -U https://github.com/wannaphongcom/pythainlp/archive/pythainlp1.4.zip +``` \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml deleted file mode 100644 index 2e032ab23..000000000 --- a/mkdocs.yml +++ /dev/null @@ -1,8 +0,0 @@ -site_name: PyThaiNLP -theme: readthedocs -pages: -- Home: index.md -- Install: install.md -- Docs: docs.md -- License: license.md -- About: about.md \ No newline at end of file diff --git a/pythainlp/MetaSound.py b/pythainlp/MetaSound.py new file mode 100644 index 000000000..af708dc98 --- /dev/null +++ b/pythainlp/MetaSound.py @@ -0,0 +1,52 @@ +''' +MetaSound + +References + +Snae & Brückner. (2009). Novel Phonetic Name Matching Algorithm with a Statistical Ontology for Analysing Names Given in Accordance with Thai Astrology. Retrieved from https://pdfs.semanticscholar.org/3983/963e87ddc6dfdbb291099aa3927a0e3e4ea6.pdf +''' +import re +def MetaSound(name): + ''' + MetaSound(str) + ''' + name1=list(name) + count=len(name1) + word=[] + i=0 + while i Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.” Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at [creativecommons.org/policies](http://creativecommons.org/policies), Creative Commons does not authorize the use of the trademark “Creative Commons” or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses. +> +> Creative Commons may be contacted at creativecommons.org + diff --git a/pythainlp/corpus/make-stopword.tool b/pythainlp/corpus/make-stopword.tool new file mode 100755 index 000000000..20ef0b137 --- /dev/null +++ b/pythainlp/corpus/make-stopword.tool @@ -0,0 +1,54 @@ +''' +โปรแกรมรวบรวมคำศัพท์เพื่อสร้าง dict +=================== +เขียนโดย นาย วรรณพงษ์ ภัททิยไพบูลย์ + +29/5/2560 +22:45 น. +''' +import codecs +def data(template_file): + ''' + เปิดไฟล์แล้วอ่านทีละบรรทัดส่งออกเป็น list + ''' + with codecs.open(template_file, 'r',encoding='utf-8-sig') as f: + lines = f.read().splitlines() + f.close() + return lines +def list1list(list1,list2): + ''' + ทำการเปรียบเทียบ 2 list + ''' + i=0 + list2=list2 + list1=list1 + while i 20: - for data in self.trie.keys(word[0:longest]): - if(len(data) > longest): - if data in word[0:len(data)]: - wordLength = 0 - longest = len(data) - maxData = data - - - if maxData: - try: - # Special check for case like ๆ - if word[len(maxData)] == u'ๆ': - return word[0:(len(maxData) + 1)] - else: - return maxData - except: - return maxData - else: - return -1 - - def transform(self, wordArray): - for dd in self.stopdict: - try: - if self.caseSensitive: - wordArray.remove(dd) - else: - wordArray.remove(dd.lower()) - except ValueError: - pass - - return wordArray - - # c = sentence which represent as char - # N = number of character - def find_segment(self, c): - i = 0 - N = len(c) - arr = [] - while(i < N): - j = self.searchTrie(c[i:N]) - if(j == -1): - if(self.removeRepeat is False or c[i] != c[i - 1]): - arr.append(c[i]) - i = i + 1 - else: - i = i + 1 - else: - k = j - if self.negation: - if self.onNegation: - k = 'NOT_' + j - - if j in self.negationDict: - self.onNegation = True - - arr.append(k) - i = i + len(j) - return arr - - def find_ngrams(self, input_list, n): - return zip(*[input_list[i:] for i in range(n)]) - - def segment(self, c): - result = self.find_segment(c) - if self.stopword: - result = self.transform(result) - - result = [x for x in result if self.determine(x)] - - lastresult = [] - for x in range(self.ngram[0], self.ngram[1]+1): - for r in self.find_ngrams(result, x): - match = re.search(u"[A-Za-z\d]+", ''.join(r)) - if not match: - lastresult.append(''.join(r)) - else: - if self.negation: - lastresult.append(''.join(r)) - else: - lastresult.append(' '.join(r)) - return lastresult -def segment(text): - pt = wordcut(stopNumber=False, removeNonCharacter=True, caseSensitive=False, negation=True, removeRepeat=True) - return pt.segment(text) \ No newline at end of file diff --git a/pythainlp/sentiment/__init__.py b/pythainlp/sentiment/__init__.py index c2535f447..1b6559a9a 100644 --- a/pythainlp/sentiment/__init__.py +++ b/pythainlp/sentiment/__init__.py @@ -9,7 +9,17 @@ import pythainlp import os from pythainlp.tokenize import word_tokenize -import dill +try: + import dill +except ImportError: + import pip + pip.main(['install','dill']) + try: + import dill + except ImportError: + print("Error ! using 'pip install dill'") + sys.exit(0) + templates_dir = os.path.join(os.path.dirname(pythainlp.__file__), 'sentiment') def sentiment(text): """ diff --git a/pythainlp/sentiment/build_pythainlp.py b/pythainlp/sentiment/build_pythainlp.tool similarity index 100% rename from pythainlp/sentiment/build_pythainlp.py rename to pythainlp/sentiment/build_pythainlp.tool diff --git a/pythainlp/soundex.py b/pythainlp/soundex.py new file mode 100644 index 000000000..702bc8b9c --- /dev/null +++ b/pythainlp/soundex.py @@ -0,0 +1,80 @@ +''' +Thai soundex + +โค้ดพัฒนาโดย คุณ Korakot Chaovavanich (จาก https://gist.github.com/korakot/0b772e09340cac2f493868da035597e8) +''' +import re +def LK82(s): + ''' + LK82 - กฎการเข้ารหัสซาวน์เด็กซ์ของ วิชิตหล่อจีระชุณห์กุล และ เจริญ คุวินทร์พันธุ์ + LK82(str) + ''' + t1 = str.maketrans("กขฃคฅฆงจฉชฌซศษสญยฎดฏตณนฐฑฒถทธบปผพภฝฟมรลฬฤฦวหฮอ","กกกกกกงจชชชซซซซยยดดตตนนททททททบปพพพฟฟมรรรรรวหหอ") + t2 = str.maketrans("กขฃคฅฆงจฉชซฌฎฏฐฑฒดตถทธศษสญณนรลฬฤฦบปพฟภผฝมำยวไใหฮาๅึืเแโุูอ","1111112333333333333333333444444445555555667777889AAABCDEEF") + res = [] + s = re.sub("[่-๋]", "", s) # 4.ลบวรรณยุกต์ + s = re.sub('จน์|มณ์|ณฑ์|ทร์|ตร์|[ก-ฮ]์|[ก-ฮ][ะ-ู]์', "", s) # 4.ลบตัวการันต์ + s = re.sub("[็ํฺๆฯ]", "", s) # 5.ทิ้งไม้ไต่คู่ ฯลฯ + # 6.เข้ารหัสตัวแรก + if 'ก'<=s[0]<='ฮ': + res.append(s[0].translate(t1)) + s = s[1:] + else: + s = s[1:] + res.append(s[0].translate(t2)) + s = s[2:] + # เข้ารหัสตัวที่เหลือ + i_v = None # ตำแหน่งตัวคั่นล่าสุด (สระ) + for i,c in enumerate(s): + if c in "ะัิี": # 7. ตัวคั่นเฉยๆ + i_v = i + res.append('') + elif c in "าๅึืู": # 8.คั่นและใส่ + i_v = i + res.append(c.translate(t2)) + elif c == 'ุ': # 9.สระอุ + i_v = i + if i==0 or (s[i-1] not in "ตธ"): + res.append(c.translate(t2)) + else: + res.append('') + elif c in 'หอ' and (i+1 (3,3): self.assertEqual(pos_tag(word_tokenize("ผมรักคุณ"),engine='artagger'),[('ผม', 'PPRS'), ('รัก', 'VSTA'), ('คุณ', 'PPRS')]) if __name__ == '__main__': diff --git a/pythainlp/tokenize/__init__.py b/pythainlp/tokenize/__init__.py index 80b446515..c48f49d58 100644 --- a/pythainlp/tokenize/__init__.py +++ b/pythainlp/tokenize/__init__.py @@ -1,19 +1,47 @@ # -*- coding: utf-8 -*- -from __future__ import absolute_import,division,unicode_literals +from __future__ import absolute_import,division,unicode_literals,print_function def word_tokenize(text,engine='icu'): """ ระบบตัดคำภาษาไทย word_tokenize(text,engine='icu') engine มี - - icu - - dict - - mm ใช้ Maximum Matching algorithm + - icu - engine ตัวดั้งเดิมของ PyThaiNLP (ความแม่นยำต่ำ) และเป็นค่าเริ่มต้น + - dict - ใช้ dicu ในการตัดคำไทย จะคืนค่า False หากไม่สามารถตัดคำไทย + - mm ใช้ Maximum Matching algorithm - โค้ดชุดเก่า + - newmm - ใช้ Maximum Matching algorithm ในการตัดคำภาษาไทย โค้ดชุดใหม่ + - pylexto ใช้ LexTo ในการตัดคำ + - deepcut ใช้ Deep Neural Network ในการตัดคำภาษาไทย """ if engine=='icu': - from pythainlp.segment.pyicu import segment + ''' + ตัดคำภาษาไทยโดยใช้ icu ในการตัดคำ + ''' + from .pyicu import segment elif engine=='dict': - from pythainlp.segment.dict import segment + ''' + ใช้ dicu ในการตัดคำไทย + จะคืนค่า False หากไม่สามารถตัดคำไทย + ''' + from .dictsegment import segment elif engine=='mm': - from pythainlp.segment.mm import segment - return segment(text) \ No newline at end of file + ''' + ใช้ Maximum Matching algorithm - โค้ดชุดเก่า + ''' + from .mm import segment + elif engine=='newmm': + ''' + ใช้ Maximum Matching algorithm ในการตัดคำภาษาไทย โค้ดชุดใหม่ + ''' + from .newmm import mmcut as segment + elif engine=='pylexto': + ''' + ใช้ LexTo ในการตัดคำ + ''' + from .pylexto import segment + elif engine=='deepcut': + ''' + ใช้ Deep Neural Network ในการตัดคำภาษาไทย + ''' + from .deepcut import segment + return segment(text) diff --git a/pythainlp/tokenize/deepcut.py b/pythainlp/tokenize/deepcut.py new file mode 100644 index 000000000..0eb3fae8d --- /dev/null +++ b/pythainlp/tokenize/deepcut.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import,unicode_literals +import sys +try: + import deepcut +except ImportError: + ''' + ในกรณ๊ที่ยังไม่ติดตั้ง deepcut ในระบบ + ''' + import pip + pip.main(['install','deepcut']) + try: + from pylexto import LexTo + except ImportError: + sys.exit('Error ! using pip install deepcut') +def segment(text): + return deepcut.tokenize(text) \ No newline at end of file diff --git a/pythainlp/segment/dict.py b/pythainlp/tokenize/dictsegment.py similarity index 100% rename from pythainlp/segment/dict.py rename to pythainlp/tokenize/dictsegment.py diff --git a/pythainlp/tokenize/etcc.py b/pythainlp/tokenize/etcc.py new file mode 100644 index 000000000..5a7b599a0 --- /dev/null +++ b/pythainlp/tokenize/etcc.py @@ -0,0 +1,60 @@ +''' +โปรแกรม ETCC ใน Python + +พัฒนาโดย นาย วรรณพงษ์ ภัททิยไพบูลย์ + +19 มิ.ย. 2560 + +วิธีใช้งาน +etcc(คำ) +คืนค่า โดยมี / แบ่งกลุ่มคำ +''' +import re +C=['ก','ข','ฃ','ค','ฅ','ฆ','ง','จ','ฉ','ช','ฌ','ซ','ศ','ษ','ส','ญ','ฎ','ฑ','ด','ฏ','ต','ฐ','ฑ','ฒ','ถ','ท','ธ','ณ','น','บ','ป','ผ','พ','ภ','ฝ','ฟ','ม','ย','ร','ล','ฬ','ว','ห','ฮ'] +UV=['็','ี','ื','ิ'] +UV1=['ั','ี'] +LV=['ุ','ู'] +c='['+''.join(C)+']' +uv2='['+''.join(['ั','ื'])+']' +def etcc(text): + """ + Enhanced Thai Character Cluster (ETCC) + คั่นด้วย / + รับ str + ส่งออก str + """ + if (re.search('[เแ]'+c+'['+''.join(UV)+']'+'\w',text,re.U)): + search=re.findall('[เแ]'+c+'['+''.join(UV)+']'+'\w',text,re.U) + for i in search: + text=re.sub(i, '/'+i+'/', text) + if (re.search(c+'['+''.join(UV1)+']'+c+c+'ุ'+'์',text,re.U)): + search=re.findall(c+'['+''.join(UV1)+']'+c+c+'ุ'+'์',text,re.U) + for i in search: + text=re.sub(i, '//'+i+'/', text) + if (re.search(c+uv2+c,text,re.U)): + search=re.findall(c+uv2+c,text,re.U) + for i in search: + text=re.sub(i, '/'+i+'/', text) + re.sub('//','/',text) + if (re.search('เ'+c+'า'+'ะ',text,re.U)): + search=re.findall('เ'+c+'า'+'ะ',text,re.U) + for i in search: + text=re.sub(i, '/'+i+'/', text) + if (re.search('เ'+'\w\w'+'า'+'ะ',text,re.U)): + search=re.findall('เ'+'\w\w'+'า'+'ะ',text,re.U) + for i in search: + text=re.sub(i, '/'+i+'/', text) + text=re.sub('//','/',text) + if (re.search(c+'['+''.join(UV1)+']'+c+c+'์',text,re.U)): + search=re.findall(c+'['+''.join(UV1)+']'+c+c+'์',text,re.U) + for i in search: + text=re.sub(i, '/'+i+'/', text) + if (re.search('/'+c+''.join(['ุ', '์'])+'/',text,re.U)): + '''แก้ไขในกรณี พัน/ธุ์''' + search=re.findall('/'+c+''.join(['ุ', '์'])+'/',text,re.U) + for i in search: + ii=re.sub('/','', i) + text=re.sub(i,ii+'/', text) + return re.sub('//','/',text) +if __name__ == '__main__': + print(etcc('พันธุ์เด็กเปียเสือเงินพังมือเพราะเกาะเอาะยีนส์เพราะเรือดีเพราะ')) \ No newline at end of file diff --git a/pythainlp/segment/isthai.py b/pythainlp/tokenize/isthai.py.old similarity index 100% rename from pythainlp/segment/isthai.py rename to pythainlp/tokenize/isthai.py.old diff --git a/pythainlp/tokenize/mm.py b/pythainlp/tokenize/mm.py new file mode 100644 index 000000000..28fbf1cb7 --- /dev/null +++ b/pythainlp/tokenize/mm.py @@ -0,0 +1,296 @@ +# -*- coding: utf-8 -*- + +''' +based on algorithm from +http://www.aclweb.org/anthology/E14-4016 + +fork from https://github.com/narongdejsrn/pythaiwordcut +License: MIT +''' + +from __future__ import print_function +from six.moves import range,zip +import codecs +import re +from .thai import newdata # load dictionary +from pythainlp.corpus import stopwords # load stopwords +import marisa_trie + +class wordcut(object): + """ + ตัดคำภาษาไทยด้วย Maximum Matching algorithm + """ + def __init__(self, removeRepeat=True, keyDictionary="", stopDictionary="", removeSpaces=True, minLength=1, stopNumber=False, removeNonCharacter=False, caseSensitive=True, ngram=(1,1), negation=False): + d = newdata() # load dictionary + # load negation listdir + self.negationDict = [] + if negation: + self.negationDict = ['ไม่','แต่'] + self.stopword = False + self.stopdict = [] + if(stopDictionary is not ""): + self.stopword = True + with codecs.open(stopDictionary, 'r',encoding='utf8') as f: + for line in f: + self.stopdict.append(line) + else: + self.stopdict = stopwords.words('thai') + self.keyword = False + self.keydict = [] + if(keyDictionary is not ""): + self.keyword = True + with codecs.open(keyDictionary, 'r',encoding='utf8') as f: + for line in f.read().splitlines(): + self.keydict.append(line) + + self.trie = marisa_trie.Trie(d) + self.removeRepeat = removeRepeat + self.stopNumber = stopNumber + self.removeSpaces = removeSpaces + self.minLength = minLength + self.removeNonCharacter = removeNonCharacter + self.caseSensitive = caseSensitive + self.ngram = ngram + self.negation = negation + self.onNegation = False + + def determine(self, word): + if self.stopNumber and word.isdigit(): + return False + + if self.removeSpaces and word.isspace(): + return False + + if len(word) < self.minLength: + return False + + if self.removeNonCharacter: + match = re.search(u"[0-9A-Za-z\u0E00-\u0E7F]+", word,re.U) + if not match: + return False + + return True + + # Find maximum matching in Trie if match return id else return -1 + def search_trie(self, word): + # remove negation if see a space + if(word[0:1] == " "): + self.onNegation = False + + # check latin words + match = re.search(u"[A-Za-z\d]*", word,re.U) + if match.group(0): + if not self.caseSensitive: + return match.group(0).lower() + else: + return match.group(0) + + # check number + match = re.search(u"[\d]*", word,re.U) + if match.group(0): + return match.group(0) + + longest = 0 + max_data = None + + for x in range(20): + if word[0:x] in self.trie: + longest = len(word[0:x]) + max_data = word[0:x] + + if longest > 20: + for data in self.trie.keys(word[0:longest]): + if len(data) > longest and data in word[0:len(data)]: + longest = len(data) + max_data = data + + + if max_data: + try: + # Special check for case like ๆ + if word[len(max_data)] == 'ๆ': + return word[0:(len(max_data) + 1)] + else: + return max_data + except: + return max_data + else: + return -1 + + def transform(self, wordArray): + for dd in self.stopdict: + try: + if self.caseSensitive: + wordArray.remove(dd) + else: + wordArray.remove(dd.lower()) + except ValueError: + pass + + return wordArray + + def extract_keyword(self, wordArray): + """ + ใช้ในการหาคำสำคัญ + """ + result_array = [] + for dd in wordArray: + try: + if self.caseSensitive and dd in self.keydict: + result_array.append(dd) + else: + if dd.lower() in self.keydict: + result_array.append(dd) + except ValueError: + pass + + return result_array + # c = sentence which represent as char + # N = number of character + def find_segment(self, c): + i = 0 + N = len(c) + arr = [] + while(i < N): + j = self.search_trie(c[i:N]) + if(j == -1): + if(self.removeRepeat is False or c[i] != c[i - 1]): + arr.append(c[i]) + i = i + 1 + else: + i = i + 1 + else: + k = j + if self.negation: + if self.onNegation: + k = 'NOT_' + j + + if j in self.negationDict: + self.onNegation = True + + arr.append(k) + i = i + len(j) + return arr + + def find_ngrams(self, input_list, n): + return zip(*[input_list[i:] for i in range(n)]) + + def segment(self, c): + ''' + ตัดคำใช้ฟังก์ชัน segment + ''' + result = self.find_segment(c) + if self.stopword: + result = self.transform(result) + + result = [x for x in result if self.determine(x)] + + lastresult = [] + for x in range(self.ngram[0], self.ngram[1]+1): + for r in self.find_ngrams(result, x): + match = re.search(u"[A-Za-z\d]+", ''.join(r),re.U) + if not match: + lastresult.append(''.join(r)) + else: + if self.negation: + lastresult.append(''.join(r)) + else: + lastresult.append(' '.join(r)) + return lastresult +def mergelistlen(listdata,lennum): + ''' + แก้ Bug ที่เกิดจาก mm + ''' + i=0 + listlen=len(listdata) + while i(listlen-1) or i+1==listlen: + ''' + ถ้า i เกินความยาว list ให้ออกจากการลูป + ''' + break + elif re.search(r'[0-9]',listdata[i]): + ''' + ถ้าหาก listdata[i] เป็นตัวเลขให้ข้ามไป + ''' + pass + elif re.search(r'[ะา]',listdata[i]) and (len(listdata[i])==lennum and len(listdata[i+1])==lennum): + ''' + ถ้าหาก listdata[i] คือ ะ/า ซึ่งเปนสระที่ไว้ข้างหลังได้เท่านั้น และ listdata[i] กับ listdata[i+1] ยาวเท่า lennum + จึงนำ listdata[i] ไปรวมกับ listdata[i-1] แล้วลบ listdata[i] ออก + ''' + listdata[i-1]+=listdata[i] + del listdata[i] + i-=1 + elif re.search(r'[ก-ฮ]',listdata[i]) and re.search(r'[0-9]',listdata[i+1]): + ''' + กันปัญหา ก-ฮ ตัวต่อมาเป็น 0-9 มีความยาวเท่ากัน ให้ ก-ฮ ไปรวมกับตัวก่อนหน้า + ''' + listdata[i-1]+=listdata[i] + del listdata[i] + i-=1 + elif len(listdata[i])==lennum and len(listdata[i+1])==lennum: + ''' + ถ้าหาก list มีความยาวเท่ากันอยู่ติดกัน + ''' + #print(listdata,'99') + T=True + num=1 + while T==True: + if (i+num)>=listlen: + ii=i + num2=1 + TT=True + while TT==True: + if (i+num2)<=(listlen-1): + listdata[i]+=listdata[i+num2] + num2+=1 + elif (i+num2)>(listlen-1): + num2-=1 + TT=False + TT=True + while TT==True: + if (i+num2) != i: + del listdata[i+num2] + num2-=1 + else: + TT=False + T=False + elif len(listdata[i+(num-1)])!=len(listdata[i+num]): #and re.search(r'[0-9]',listdata[i+(num-1)])==False:# and isThai(listdata[i+(num-1)])==True: + ii=1+i + while ii<(i+num) and ii<(len(listdata)-1): + listdata[i]+=listdata[ii] + ii+=1 + ii=i+num-1 + while ii>i: + del listdata[ii] + ii-=1 + T=False + num+=1 + del T,ii + elif len(listdata[i])==lennum and len(listdata[i+1])!=lennum: + ''' + ในกรณีที่ list ความยาวที่กำหนด แต่ตัวต่อไปยาวไม่เท่า ให้ยุบรวมกัน + ''' + if re.search(r'[เแโใไ]',listdata[i]): + ''' + ถ้าหากเป็นสระต้นคำ ให้รวมกัน + ''' + listdata[i]+=listdata[i+1] + del listdata[i+1] + elif re.search(r'[ก-ฮ]',listdata[i]) or re.search(r'[ะา]',listdata[i]): + ''' + หากเป็นแค่พยัญชนะให้รวมกับตัวหลัง + ''' + listdata[i-1]+=listdata[i] + del listdata[i] + i-=1 + listlen=len(listdata) + i+=1 + return listdata +def segment(text): + ''' + ใช้ในการตัดตำ segment(str) คืนค่า list + ''' + pt = wordcut(stopNumber=False, removeNonCharacter=True, caseSensitive=False,removeRepeat=True) + return mergelistlen(pt.segment(text),1) \ No newline at end of file diff --git a/pythainlp/tokenize/newmm.py b/pythainlp/tokenize/newmm.py new file mode 100644 index 000000000..b300e0e34 --- /dev/null +++ b/pythainlp/tokenize/newmm.py @@ -0,0 +1,114 @@ +''' +ตัดคำภาษาไทยโดยใช้ Maximum Matching algorithm +เดติดโค้ดต้นฉบับ คุณ Korakot Chaovavanich +จาก https://www.facebook.com/groups/408004796247683/permalink/431283740586455/ +''' +from marisa_trie import Trie +from collections import Counter, defaultdict +from pythainlp.corpus.thaiword import get_data +class LatticeString(str): + def __new__(cls, value, multi=None, in_dict=True): + ''' Return a string instance + ''' + return str.__new__(cls, value) + + def __init__(self, value, multi=None, in_dict=True): + self.unique = True + if multi: + self.multi = list(multi) + if len(self.multi) > 1: + self.unique = False + else: + self.multi = [value] + + self.in_dict = in_dict # บอกว่าเป็นคำมีในดิกหรือเปล่า + + def suggest(self): + return [] +def serialize(p, p2): + for w in words_at[p]: + p_ = p + len(w) + if p_== p2: + yield w + elif p_ < p2: + for path in serialize(p_, p2): + yield w+'/'+path +# มี jigsaw พร้อมแล้ว ต่อไปก็ลองเขียน tcut ใหม่ +def tcut(text): + #global last_p, i, q, ww # for debug + trie = Trie(get_data()) + words_at = defaultdict(list) # main data structure + + def serialize(p, p2): # helper function + for w in words_at[p]: + p_ = p + len(w) + if p_== p2: + yield w + elif p_ < p2: + for path in serialize(p_, p2): + yield w+'/'+path + + q = {0} + last_p = 0 # last position for yield + while min(q) < len(text): + p = min(q) + q -= {p} # q.pop, but for set + + for w in trie.prefixes(text[p:]): + words_at[p].append(w) + q.add(p+len(w)) + + if len(q)==1: + q0 = min(q) + yield LatticeString(text[last_p:q0], serialize(last_p, q0)) + last_p = q0 + + # กรณี len(q) == 0 คือ ไม่มีใน dict + if len(q)==0: + # skip น้อยที่สุด ที่เป็นไปได้ + for i in range(p, len(text)): + ww = trie.prefixes(text[i:]) + if ww: + break + else: + i = len(text) + w = text[p:i] + w = w.replace(' ','') # ลบค่าที่ว่าง + words_at[p].append(w) + yield LatticeString(w, in_dict=False) + last_p = i + q.add(i) +def mmcut(text): + ''' + ใช้ Maximum Matching algorithm ในการตัดคำภาษาไทย + ''' + res = [] + for w in tcut(text): + if w.unique: + res.append(w) + else: + mm = min(w.multi, key=lambda x: x.count('/')) + res.extend(mm.split('/')) + return res +def combine(ww): + if ww == []: + yield "" + else: + w = ww[0] + for tail in combine(ww[1:]): + if w.unique: + yield w+"|"+tail + else: + for m in w.multi: + yield m.replace("/","|")+"|"+tail + +def listcut(text): + ''' + ใช้ในการหา list ที่สามารถตัดคำได้ทั้งหมด + ''' + ww = list(tcut(text)) + return list(combine(ww)) +if __name__ == "__main__": + text='ผมรักคุณนะครับโอเคบ่พวกเราเป็นคนไทยรักภาษาไทยภาษาบ้านเกิด' + print(mmcut(text)) + print(listcut(text)) \ No newline at end of file diff --git a/pythainlp/segment/pyicu.py b/pythainlp/tokenize/pyicu.py similarity index 60% rename from pythainlp/segment/pyicu.py rename to pythainlp/tokenize/pyicu.py index 91539b01d..0a1d2a8ef 100644 --- a/pythainlp/segment/pyicu.py +++ b/pythainlp/tokenize/pyicu.py @@ -1,36 +1,48 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import,print_function,unicode_literals from itertools import groupby -import PyICU +from langdetect import detect +import re +import icu def isEnglish(s): - try: - try: - s.encode('ascii') - except UnicodeEncodeError: - return False - else: - return True - except: - try: - s.decode('ascii') - except UnicodeDecodeError: - return False - else: - return True + ''' + เช็คว่าตัวอักษรเป็นภาษาอังกฤษหรือไม่ + ''' + try: + try: + s.encode('ascii') + except UnicodeEncodeError: + return False + else: + return True + except: + try: + s.decode('ascii') + except UnicodeDecodeError: + return False + else: + return True def isThai(chr): - if isEnglish(chr): - return False - try: - cVal = ord(chr) - if(cVal >= 3584 and cVal <= 3711): - return True - return False - except: - return False + ''' + เช็คตัวอักษรว่าใช่ภาษาไทยไหม + ''' + if isEnglish(chr): + return False + try: + '''cVal = ord(chr) + if(cVal >= 3584 and cVal <= 3711): + return True''' + if detect(chr)=='th': + return True + else: + return False + except: + return False def segment(txt): """รับค่า ''str'' คืนค่าออกมาเป็น ''list'' ที่ได้มาจากการตัดคำโดย ICU""" - bd = PyICU.BreakIterator.createWordInstance(PyICU.Locale("th")) - bd.setText(txt.replace(' ', '')) + bd = icu.BreakIterator.createWordInstance(icu.Locale("th")) + pattern = re.compile(r'\s+') + bd.setText(re.sub(pattern, '', txt)) breaks = list(bd) result=[txt[x[0]:x[1]] for x in zip([0]+breaks, breaks)] result1=[] @@ -62,3 +74,5 @@ def segment(txt): print(segment('ทดสอบระบบตัดคำด้วยไอซียู')) print(segment('ผมชอบพูดไทยคำ English')) print(segment('ผมชอบพูดไทยคำEnglishคำ')) + print(segment('ผมชอบพูดไทยคำEnglish540 บาท')) + print(segment('ประหยัด ไฟเบอห้า')) diff --git a/pythainlp/tokenize/pylexto.py b/pythainlp/tokenize/pylexto.py new file mode 100644 index 000000000..92ecb8158 --- /dev/null +++ b/pythainlp/tokenize/pylexto.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import,unicode_literals +import sys +try: + from pylexto import LexTo +except ImportError: + import pip + pip.main(['install','https://github.com/wannaphongcom/pylexto/archive/master.zip']) + try: + from pylexto import LexTo + except ImportError: + sys.exit('Error ! using pip install https://github.com/wannaphongcom/pylexto/archive/master.zip') +def segment(text): + lexto = LexTo() + words, types = lexto.tokenize(text) + return words \ No newline at end of file diff --git a/pythainlp/tokenize/tcc.py b/pythainlp/tokenize/tcc.py new file mode 100644 index 000000000..59086b0d3 --- /dev/null +++ b/pythainlp/tokenize/tcc.py @@ -0,0 +1,70 @@ +""" +โปรแกรม TCC ภาษาไทย +เดติด +TCC : Mr.Jakkrit TeCho +grammar : คุณ Wittawat Jitkrittum (https://github.com/wittawatj/jtcc/blob/master/TCC.g) +โค้ด : คุณ Korakot Chaovavanich +""" +import re +pat_list = """\ +เc็c +เcctาะ +เccีtยะ +เccีtย(?=[เ-ไก-ฮ]|$) +เccอะ +เcc็c +เcิc์c +เcิtc +เcีtยะ? +เcืtอะ? +เc[ิีุู]tย(?=[เ-ไก-ฮ]|$) +เctา?ะ? +cัtวะ +c[ัื]tc[ุิะ]? +c[ิุู]์ +c[ะ-ู]t +c็ +ct[ะาำ]? +แc็c +แcc์ +แctะ +แcc็c +แccc์ +โctะ +[เ-ไ]ct +ๆ +ฯลฯ +ฯ +""".replace('c','[ก-ฮ]').replace('t', '[่-๋]?').split() +''' +def tcc(w): + p = 0 # position + while p=3.2.2 +future>=0.16.0 +six +marisa_trie +langdetect diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..d4f03bec2 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +pyicu +nltk>=3.2.2 +future>=0.16.0 +six +marisa_trie +langdetect diff --git a/setup.py b/setup.py index 0659102e4..e3eea66a3 100644 --- a/setup.py +++ b/setup.py @@ -6,11 +6,10 @@ 'pyicu', 'nltk>=3.2.2', 'future>=0.16.0', - 'six' + 'six', + 'marisa_trie', + 'langdetect' ] -if sys.version_info >= (3,4): - requirements.append('artagger') - requirements.append('dill') test_requirements = [ # TODO: put package test requirements here @@ -18,14 +17,14 @@ setup( name='pythainlp', - version='1.3', + version='1.4', description="Thai NLP in python package.", author='Wannaphong Phatthiyaphaibun', author_email='wannaphong@yahoo.com', url='https://github.com/wannaphongcom/pythainlp', packages=find_packages(), test_suite='pythainlp.test', - package_data={'pythainlp.corpus':['thaipos.json','thaiword.txt','LICENSE_THA_WN','tha-wn.db','new-thaidict.txt','negation.txt'],'pythainlp.sentiment':['vocabulary.data','sentiment.data']}, + package_data={'pythainlp.corpus':['stopwords-th.txt','thaipos.json','thaiword.txt','corpus_license.md','tha-wn.db','new-thaidict.txt','negation.txt'],'pythainlp.sentiment':['vocabulary.data','sentiment.data']}, include_package_data=True, install_requires=requirements, license='Apache Software License 2.0', @@ -38,4 +37,4 @@ 'Natural Language :: Thai', 'Topic :: Text Processing :: Linguistic', 'Programming Language :: Python :: Implementation'], -) \ No newline at end of file +)