diff --git a/CHANGELOG.md b/CHANGELOG.md index 49627594..a9f83245 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## 0.9.0 (???) +- Added support for Hebrew language [#150](https://github.com/miso-belica/sumy/issues/150). + ## 0.8.1 (2019-05-19) - Open files for `PlaintextParser` in UTF-8 encoding [#123](https://github.com/miso-belica/sumy/pull/123) diff --git a/setup.py b/setup.py index c5e64e02..62a9645f 100644 --- a/setup.py +++ b/setup.py @@ -55,6 +55,7 @@ "Japanese": ["tinysegmenter"], "Chinese": ["jieba"], "Korean": ["konlpy"], + "Hebrew": ["hebrew_tokenizer"], }, packages=find_packages(), package_data={"sumy": [ @@ -84,6 +85,7 @@ "Natural Language :: Portuguese", "Natural Language :: Slovak", "Natural Language :: Spanish", + "Natural Language :: Hebrew", "Topic :: Education", "Topic :: Internet", diff --git a/sumy/data/stopwords/hebrew.txt b/sumy/data/stopwords/hebrew.txt new file mode 100644 index 00000000..e2f84fd3 --- /dev/null +++ b/sumy/data/stopwords/hebrew.txt @@ -0,0 +1,194 @@ +אבל +או +אולי +אותה +אותו +אותי +אותך +אותם +אותן +אותנו +אז +אחר +אחרות +אחרי +אחריכן +אחרים +אחרת +אי +איזה +איך +אין +איפה +איתה +איתו +איתי +איתך +איתכם +איתכן +איתם +איתן +איתנו +אך +אל +אלה +אלו +אם +אנחנו +אני +אס +אף +אצל +אשר +את +אתה +אתכם +אתכן +אתם +אתן +באיזומידה +באמצע +באמצעות +בגלל +בין +בלי +במידה +במקוםשבו +ברם +בשביל +בשעהש +בתוך +גם +דרך +הוא +היא +היה +היכן +היתה +היתי +הם +הן +הנה +הסיבהשבגללה +הרי +ואילו +ואת +זאת +זה +זות +יהיה +יוכל +יוכלו +יותרמדי +יכול +יכולה +יכולות +יכולים +יכל +יכלה +יכלו +יש +כאן +כאשר +כולם +כולן +כזה +כי +כיצד +כך +ככה +כל +כלל +כמו +כן +כפי +כש +לא +לאו +לאיזותכלית +לאן +לבין +לה +להיות +להם +להן +לו +לי +לכם +לכן +למה +למטה +למעלה +למקוםשבו +למרות +לנו +לעבר +לעיכן +לפיכך +לפני +מאד +מאחורי +מאיזוסיבה +מאין +מאיפה +מבלי +מבעד +מדוע +מה +מהיכן +מול +מחוץ +מי +מכאן +מכיוון +מלבד +מן +מנין +מסוגל +מעט +מעטים +מעל +מצד +מקוםבו +מתחת +מתי +נגד +נגר +נו +עד +עז +על +עלי +עליה +עליהם +עליהן +עליו +עליך +עליכם +עלינו +עם +עצמה +עצמהם +עצמהן +עצמו +עצמי +עצמם +עצמן +עצמנו +פה +רק +שוב +של +שלה +שלהם +שלהן +שלו +שלי +שלך +שלכה +שלכם +שלכן +שלנו +שם +תהיה +תחת diff --git a/sumy/nlp/stemmers/__init__.py b/sumy/nlp/stemmers/__init__.py index ee186fd3..183dd8a6 100644 --- a/sumy/nlp/stemmers/__init__.py +++ b/sumy/nlp/stemmers/__init__.py @@ -20,9 +20,10 @@ class Stemmer(object): SPECIAL_STEMMERS = { 'czech': czech_stemmer, 'slovak': czech_stemmer, + 'hebrew': null_stemmer, 'chinese': null_stemmer, 'japanese': null_stemmer, - 'korean': null_stemmer + 'korean': null_stemmer, } def __init__(self, language): diff --git a/sumy/nlp/tokenizers.py b/sumy/nlp/tokenizers.py index 9a696388..bbc30030 100644 --- a/sumy/nlp/tokenizers.py +++ b/sumy/nlp/tokenizers.py @@ -4,6 +4,7 @@ from __future__ import division, print_function, unicode_literals import re +import string import zipfile import nltk @@ -13,10 +14,30 @@ class DefaultWordTokenizer(object): + """NLTK tokenizer""" def tokenize(self, text): return nltk.word_tokenize(text) +class HebrewWordTokenizer: + """https://github.com/iddoberger/awesome-hebrew-nlp""" + _TRANSLATOR = str.maketrans("", "", string.punctuation) + + @classmethod + def tokenize(cls, text): + try: + from hebrew_tokenizer import tokenize + from hebrew_tokenizer.groups import Groups + except ImportError: + raise ValueError("Hebrew tokenizer requires hebrew_tokenizer. Please, install it by command 'pip install hebrew_tokenizer'.") + + text = text.translate(cls._TRANSLATOR) + return [ + word for token, word, _, _ in tokenize(text) + if token in (Groups.HEBREW, Groups.HEBREW_1, Groups.HEBREW_2) + ] + + class JapaneseWordTokenizer: def tokenize(self, text): try: @@ -73,15 +94,17 @@ class Tokenizer(object): } SPECIAL_SENTENCE_TOKENIZERS = { + 'hebrew': nltk.RegexpTokenizer(r'\.\s+', gaps=True), 'japanese': nltk.RegexpTokenizer('[^ !?。]*[!?。]'), 'chinese': nltk.RegexpTokenizer('[^ !?。]*[!?。]'), - 'korean': KoreanSentencesTokenizer() + 'korean': KoreanSentencesTokenizer(), } SPECIAL_WORD_TOKENIZERS = { + 'hebrew': HebrewWordTokenizer(), 'japanese': JapaneseWordTokenizer(), 'chinese': ChineseWordTokenizer(), - 'korean': KoreanWordTokenizer() + 'korean': KoreanWordTokenizer(), } def __init__(self, language): @@ -102,10 +125,11 @@ def _get_sentence_tokenizer(self, language): try: path = to_string("tokenizers/punkt/%s.pickle") % to_string(language) return nltk.data.load(path) - except (LookupError, zipfile.BadZipfile): + except (LookupError, zipfile.BadZipfile) as e: raise LookupError( - "NLTK tokenizers are missing. Download them by following command: " - '''python -c "import nltk; nltk.download('punkt')"''' + "NLTK tokenizers are missing or the language is not supported.\n" + """Download them by following command: python -c "import nltk; nltk.download('punkt')"\n""" + "Original error was:\n" + str(e) ) def _get_word_tokenizer(self, language):