{"id":13674174,"url":"https://github.com/lovit/customized_konlpy","last_synced_at":"2026-01-17T18:30:48.006Z","repository":{"id":53676468,"uuid":"94874735","full_name":"lovit/customized_konlpy","owner":"lovit","description":"Customized KoNLPy - Korean Natural Language Processing Toolkit KoNLPy wrapping code","archived":false,"fork":false,"pushed_at":"2018-11-17T17:09:46.000Z","size":951,"stargazers_count":126,"open_issues_count":9,"forks_count":24,"subscribers_count":7,"default_branch":"master","last_synced_at":"2026-01-07T17:08:23.087Z","etag":null,"topics":["konlpy","korean-nlp","korean-text-processing"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lovit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-06-20T09:38:10.000Z","updated_at":"2024-01-28T12:25:12.000Z","dependencies_parsed_at":"2022-09-09T22:40:46.455Z","dependency_job_id":null,"html_url":"https://github.com/lovit/customized_konlpy","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/lovit/customized_konlpy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lovit%2Fcustomized_konlpy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lovit%2Fcustomized_konlpy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lovit%2Fcustomized_konlpy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lovit%2Fcustomized_konlpy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lovit","download_url":"https://codeload.github.com/lovit/customized_konlpy/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lovit%2Fcustomized_konlpy/sbom","scorecard":{"id":600227,"data":{"date":"2025-08-11","repo":{"name":"github.com/lovit/customized_konlpy","commit":"2d2dc8a3ee74b7b0d035d8b6b30d3afbbe785575"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.2,"checks":[{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":1,"reason":"Found 3/21 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: GNU General Public License v3.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 13 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-21T00:13:26.121Z","repository_id":53676468,"created_at":"2025-08-21T00:13:26.121Z","updated_at":"2025-08-21T00:13:26.121Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28515730,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T18:28:00.501Z","status":"ssl_error","status_checked_at":"2026-01-17T18:28:00.150Z","response_time":85,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["konlpy","korean-nlp","korean-text-processing"],"created_at":"2024-08-02T11:00:42.409Z","updated_at":"2026-01-17T18:30:47.969Z","avatar_url":"https://github.com/lovit.png","language":"Python","funding_links":[],"categories":["GitHub"],"sub_categories":[],"readme":"# customized KoNLPy\n\n한국어 자연어처리를 할 수 있는 파이썬 패키지, KoNLPy의 customized version입니다. \n\ncustomized_KoNLPy는 확실히 알고 있는 단어들에 대해서는 라이브러리를 거치지 않고 주어진 어절을 아는 단어들로 토크나이징 / 품사판별을 하는 기능을 제공합니다. 이를 위해 template 기반 토크나이징을 수행합니다.\n\n    사전: {'아이오아이': 'Noun', '는': 'Josa'}\n    탬플릿: Noun + Josa\n\n위와 같은 단어 리스트와 탬플릿이 있다면 '아이오아이는' 이라는 어절은 [('아이오아이', 'Noun'), ('는', 'Josa')]로 분리됩니다.\n\n## Install\n\n    $ git clone https://github.com/lovit/customized_konlpy.git\n    \n    $ pip install customized_konlpy\n\n### Requires\n\n- JPype \u003e= 0.6.1\n- KoNLPy \u003e= 0.4.4\n\n## Usage\n\n### Part of speech tagging\n\nKoNLPy와 동일하게 Twitter.pos(phrase)를 입력합니다. 각 어절별로 사용자 사전에 알려진 단어가 인식되면 customized_tagger로 어절을 분리하며, 사용자 사전에 알려지지 않은 단어로 구성된 어절은 트위터 형태소 분석기로 처리합니다. \n\n```python\ntwitter.pos('우리아이오아이는 이뻐요')\n```\n\n    [('우리', 'Noun'), ('아이오', 'Noun'), ('아이', 'Noun'), ('는', 'Josa'), ('이뻐', 'Adjective'), ('요', 'Eomi')] \n\n'아이오아이'가 알려진 단어가 아니었기 때문에 트위터 분석기에서 단어를 제대로 인식하지 못합니다. 아래의 사용자 사전으로 단어 추가를 한 뒤 동일한 작업을 수행하면 아래와 같은 결과를 얻을 수 있습니다. \n\n```python\ntwitter.pos('우리아이오아이는 이뻐요')\n``` \n\n    [('우리', 'Modifier'), ('아이오아이', 'Noun'), ('는', 'Josa'), ('이뻐', 'Adjective'), ('요', 'Eomi')]\n\n```python\ntwitter.pos('트와이스tt는 좋아요')\n```\n    [('트와이스', 'Noun'), ('tt', 'Noun'), ('는', 'Josa'), ('좋', 'Adjective'), ('아요', 'Eomi')]\n\n### Add words to dictioanry\n\nckonlpy.tag의 Twitter는 add_dictionary를 통하여 str 혹은 list of str 형식의 사용자 사전을 추가할 수 있습니다. \n\n```python\nfrom ckonlpy.tag import Twitter\n\ntwitter.add_dictionary('아이오아이', 'Noun')\ntwitter.add_dictionary(['트와이스', 'tt'], 'Noun')\n```\n\n트위터 한국어 분석기에서 이용하지 않는 품사 (단어 클래스)를 추가하고 싶을 경우에는 반드시 force=True로 설정해야 합니다. \n\n```python\ntwitter.add_dictionary('lovit', 'Name', force=True)\n```\n\n### Add template to customized tagger\n\n현재 사용중인 탬플릿 기반 토크나이저는 코드 사용 중 탬플릿을 추가할 수 있습니다. 현재 사용중인 탬플릿의 리스트는 아래처럼 확인할 수 있습니다. \n\n```python\ntwitter.template_tagger.templates\n```\n\n    [('Noun', 'Josa'), ('Modifier', 'Noun'), ('Modifier', 'Noun', 'Josa')]\n\n탬플릿은 tuple of str 형식으로 입력합니다. \n\n```python\ntwitter.template_tagger.add_a_template(('Noun', 'Noun', 'Josa'))\n```\n\n### Set templates tagger selector\n\nTemplates를 이용하여도 후보가 여러 개 나올 수 있습니다. 여러 개 후보 중에서 best 를 선택하는 함수를 직접 디자인 할 수 도 있습니다. 이처럼 몇 개의 점수 기준을 만들고, 각 기준의 weight를 부여하는 방식은 트위터 분석기에서 이용하는 방식인데, 직관적이고 튜닝 가능해서 매우 좋은 방식이라 생각합니다.\n\n```python\nmy_weights = [\n    ('num_nouns', -0.1),\n    ('num_words', -0.2),\n    ('no_noun', -1),\n    ('len_sum_of_nouns', 0.2)\n]\n\ndef my_evaluate_function(candidate):\n    num_nouns = len([word for word, pos, begin, e in candidate if pos == 'Noun'])\n    num_words = len(candidate)\n    has_no_nouns = (num_nouns == 0)\n    len_sum_of_nouns = 0 if has_no_nouns else sum(\n        (len(word) for word, pos, _, _ in candidate if pos == 'Noun'))\n\n    scores = (num_nouns, num_words, has_no_nouns, len_sum_of_nouns)\n    score = sum((score * weight for score, (_, weight) in zip(scores, my_weights)))\n    return score\n```\n\n위의 예제처럼 my_weights 와 my_evaluate_function 함수를 정의하여 twitter.set_evaluator()에 입력하면, 해당 함수 기준으로 best candidate를 선택합니다.\n\n```python\ntwitter.set_evaluator(my_weights, my_evaluate_function)\n```\n\n### Postprocessor\n\npasswords, stopwords, passtags, 단어 치환을 위한 후처리를 할 수 있습니다. \n\npasswords 에 등록된 단어, (단어, 품사)만 출력됩니다.\n\n```python\nfrom ckonlpy.tag import Postprocessor\n\npasswords = {'아이오아이', ('정말', 'Noun')}\npostprocessor = Postprocessor(twitter, passwords = passwords)\npostprocessor.pos('우리아이오아이는 정말 이뻐요')\n# [('아이오아이', 'Noun'), ('정말', 'Noun')]\n```\n\nstopwords 에 등록된 단어, (단어, 품사)는 출력되지 않습니다. \n\n```python\nstopwords = {'는'}\npostprocessor = Postprocessor(twitter, stopwords = stopwords)\npostprocessor.pos('우리아이오아이는 정말 이뻐요')\n# [('우리', 'Modifier'), ('아이오아이', 'Noun'), ('정말', 'Noun'), ('이뻐', 'Adjective'), ('요', 'Eomi')]\n```\n\n특정 품사를 지정하면, 해당 품사만 출력됩니다. \n\n```python\npasstags = {'Noun'}\npostprocessor = Postprocessor(twitter, passtags = passtags)\npostprocessor.pos('우리아이오아이는 정말 이뻐요')\n# [('아이오아이', 'Noun'), ('정말', 'Noun')]\n```\n\n치환할 단어, (단어, 품사)를 dict 형식으로 정의하면 tag 에서 단어가 치환되어 출력됩니다.\n\n```python\nreplace = {'아이오아이': '아이돌', ('이뻐', 'Adjective'): '예쁘다'}\npostprocessor = Postprocessor(twitter, replace = replace)\npostprocessor.pos('우리아이오아이는 정말 이뻐요')\n# [('우리', 'Modifier'), ('아이돌', 'Noun'), ('는', 'Josa'), ('정말', 'Noun'), ('예쁘다', 'Adjective'), ('요', 'Eomi')]\n```\n\n연속된 단어를 하나의 단어루 묶기 위해서 nested tuple 이나 tuple of str 형식의 ngram 을 입력할 수 있습니다. tuple of str 의 형식으로 입력된 ngram 은 Noun 으로 인식됩니다.\n\n```python\nngrams = [(('미스', '함무라비'), 'Noun'), ('바람', '의', '나라')]\npostprocessor = Postprocessor(twitter, ngrams = ngrams)\npostprocessor.pos('미스 함무라비는 재밌는 드라마입니다')\n# [('미스 - 함무라비', 'Noun'), ('는', 'Josa'), ('재밌는', 'Adjective'), ('드라마', 'Noun'), ('입니', 'Adjective'), ('다', 'Eomi')]\n```\n\n### Loading wordset\n\nutils 에는 stopwords, passwords, replace word pair 를 파일로 저장하였을 경우, 이를 손쉽게 불러오는 함수가 있습니다.\n\nload_wordset 은 set of str 혹은 set of tuple 을 return 합니다. 예시의 passwords.txt 의 내용은 아래와 같습니다. 단어의 품사는 한 칸 띄어쓰기로 구분합니다. stopwords.txt 도 동일한 포멧입니다.\n\n    아이오아이\n    아이오아이 Noun\n    공연\n\nload_wordset 을 이용하는 예시코드 입니다.\n\n```python\nfrom ckonlpy.utils import load_wordset\n\npasswords = load_wordset('./passwords.txt')\nprint(passwords) # {('아이오아이', 'Noun'), '아이오아이', '공연'}\n\nstopwords = load_wordset('./stopwords.txt')\nprint(stopwords) # {'은', '는', ('이', 'Josa')}\n```\n\n치환할 단어쌍은 tap 구분이 되어있습니다. 치환될 단어에 품사 태그가 있을 경우 한 칸 띄어쓰기로 구분합니다.\n\n    str\\tstr\n    str str\\tstr\n\n아래는 replacewords.txt 의 예시입니다.\n\n    아빠\t아버지\n    엄마 Noun\t어머니\n\nload_replace_wordpair 을 이용하는 예시코드 입니다.\n\n```python\nfrom ckonlpy.utils import load_replace_wordpair\n\nreplace = load_replace_wordpair('./replacewords.txt')\nprint(replace) # {'아빠': '아버지', ('엄마', 'Noun'): '어머니'}\n```\n\nngram 단어들의 각 단어는 한 칸 띄어쓰기로, ngram 의 품사는 tap 으로 구분되어 있습니다.\n\n    str str\n    str str\\tstr\n\n아래는 ngrams.txt 의 예시입니다.\n\n    바람 의 나라\n    미스 함무라비\tNoun\n\nload_ngram 을 이용하는 예시코드 입니다.\n\n```python\nfrom ckonlpy.utils import load_ngram\n\nngrams = load_ngram('./ngrams.txt')\nprint(ngrams) # [('바람', '의', '나라'), (('미스', '함무라비'), 'Noun')]\n```\n\n## 0.0.6+ vs 0.0.5x\n\n0.0.5x 에서의 변수와 함수의 이름, 변수의 타입 일부를 변경하였습니다.\n\n| 변경 전 | 변경 후 |\n| --- | --- |\n| ckonlpy.tag.Twitter._loaded_twitter_default_dictionary | ckonlpy.tag.Twitter.use_twitter_dictionary |\n| ckonlpy.tag.Twitter._dictionary | ckonlpy.tag.Twitter.dictionary |\n| ckonlpy.tag.Twitter._customized_tagger | ckonlpy.tag.Twitter.template_tagger |\n| ckonlpy.tag.Postprocessor.tag | ckonlpy.tag.Postprocessor.pos |\n| ckonlpy.custom_tag.SimpleSelector | ckonlpy.custom_tag.SimpleEvalator |\n| ckonlpy.custom_tag.SimpleSelector.score | ckonlpy.custom_tag.SimpleEvalator.evaluate |\n| ckonlpy.tag.Twitter.set_selector | ckonlpy.tag.AbstractTagger.set_evaluator |\n| ckonlpy.custom_tag.SimpleSelector.weight | ckonlpy.custom_tag.SimpleEvaluator.weight |\n\n| 변경 후 | 변경 이유 |\n| --- | --- |\n| ckonlpy.tag.Twitter.use_twitter_dictionary | konlpy.tag.Twitter 의 사전 사용 유무 |\n| ckonlpy.tag.Twitter.dictionary | public 으로 변환하였습니다 |\n| ckonlpy.tag.Twitter.template_tagger | Template 기반으로 작동하는 tagger 임을 명시하고, public 으로 변환하였습니다 |\n| ckonlpy.tag.Postprocessor.pos | 기본 tagger 의 결과를 후처리하는 기능이기 때문에 동일한 함수명으로 통일하였습니다 |\n| ckonlpy.custom_tag.SimpleEvalator | 클래스 이름을 Selector 에서 Evaluator 로 변경하였습니다 |\n| ckonlpy.custom_tag.SimpleEvalator.evaluate | 품사열 후보의 점수 계산 부분을 score --\u003e evaluate 로 함수명을 변경하였습니다 |\n| ckonlpy.tag.AbstractTagger.set_evaluator | 품사열 후보의 점수 계산 함수를 설정하는 함수의 이름을 변경하였습니다. 해당 함수는 ckonlpy.tag.Twitter 에서 ckonlpy.tag.AbstractTagger 로 이동하였습니다 |\n| ckonlpy.custom_tag.SimpleEvaluator.weight | {str:float} 형식의 weight 를 [(str, float)] 형식으로 변경하였습니다 |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flovit%2Fcustomized_konlpy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flovit%2Fcustomized_konlpy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flovit%2Fcustomized_konlpy/lists"}