def preprocess(doc, debug=False): """ ドキュメントを引数にとってそれを前処理した上でトークナイズされた文のリストに分割する @param doc 対象のドキュメント @return 前処理されたドキュメントに含まれる文のリスト """ doc = doc.lower() lines = re.split("\n|。", doc) lines = list(filter(lambda x: x != "", map(lambda x: x.strip(), lines))) sentences = copy.deepcopy(lines) lines = list(map(lambda x: mojimoji.zen_to_han(x), lines)) analyzer = Analyzer([ UnicodeNormalizeCharFilter(), RegexReplaceCharFilter(r'[(\)、。「」]', ' ') ], JanomeTokenizer(), [ POSKeepFilter(['名詞', '形容詞', '副詞', '動詞']), ExtractAttributeFilter('base_form') ]) corpus = [' '.join(analyzer.analyze(l)) + '。' for l in lines] if debug: print("\n".join(corpus)) return sentences, corpus
def tense_analyze(self, text, sentences_count): # 1行1文となっているため、改行コードで分離 # sentences = [t for t in text.split('\n')] sentences = [t for t in text.split('。')] # 形態素解析器を作る analyzer = Analyzer( [ UnicodeNormalizeCharFilter(), RegexReplaceCharFilter(r'[(\)「」、。]', ' ') ], # ()「」、。は全>てスペースに置き換える JanomeTokenizer(), [ POSKeepFilter(['名詞', '形容詞', '副詞', '動詞']), ExtractAttributeFilter('base_form') ] # 名詞>・形容詞・副詞・動詞の原型のみ ) # 抽出された単語をスペースで連結 # 末尾の'。'は、この後使うtinysegmenterで文として分離させるため。 corpus = [' '.join(analyzer.analyze(s)) + '。' for s in sentences] # 連結したcorpusを再度tinysegmenterでトークナイズさせる parser = PlaintextParser.from_string(''.join(corpus), Tokenizer('japanese')) # LexRankで要約を2文抽出 summarizer = LexRankSummarizer() summarizer.stop_words = [' '] # スペースも1単語として認識されるため、ストップワードにすることで除外>する summary = summarizer(document=parser.document, sentences_count=sentences_count) return sentences, corpus, summary
def make_corpus(docs, debug=False): """ 複数の文書からコーパスを作成する @docs 文書のリスト @return トークナイズされた文書のリスト """ docs = list( map( lambda d: list( filter(lambda x: x.strip() != "", re.split("\n|。", d.lower())) ), docs)) docs = [ list(map(lambda x: mojimoji.zen_to_han(x), lines)) for lines in docs ] analyzer = Analyzer([ UnicodeNormalizeCharFilter(), RegexReplaceCharFilter(r'[(\)、。「」]', ' ') ], JanomeTokenizer(), [ POSKeepFilter(['名詞', '形容詞', '副詞', '動詞']), ExtractAttributeFilter('base_form') ]) corpus = [ list( itertools.chain.from_iterable( [list(analyzer.analyze(l)) for l in lines])) for lines in docs ] if debug: print("\n".join(corpus)) return corpus
def janome_document_summarize(document): # 形態素解析(単語単位に分割する) analyzer = Analyzer(char_filters=[ UnicodeNormalizeCharFilter(), RegexReplaceCharFilter(r'[(\)「」、。]', ' ') ], tokenizer=JanomeTokenizer(), token_filters=[ POSKeepFilter(['名詞', '形容詞', '副詞', '動詞']), ExtractAttributeFilter('base_form') ]) text = re.findall("[^。]+。?", document.replace('\n', '')) corpus = [' '.join(analyzer.analyze(sentence)) + u'。' for sentence in text] parser = PlaintextParser.from_string(''.join(corpus), Tokenizer('japanese')) summarizer = LexRankSummarizer() summarizer.stop_words = [' ', '。', '\n'] N = int(len(corpus) / 10 * 3) if N <= 0: N = 3 summary = summarizer(document=parser.document, sentences_count=N) rst = '' print('\n要約:') for sentence in summary: print(text[corpus.index(sentence.__str__())]) rst += text[corpus.index(sentence.__str__())] return summary, rst
def fn_start_document_summarize(text): # 形態素解析(単語単位に分割する) tokenizer = JanomeTokenizer('japanese') char_filters=[UnicodeNormalizeCharFilter(), RegexReplaceCharFilter(r'[(\)「」、。]', ' ')] token_filters=[POSKeepFilter(['名詞', '形容詞', '副詞', '動詞']), ExtractAttributeFilter('base_form')] analyzer = Analyzer( char_filters=char_filters, tokenizer=tokenizer, token_filters=token_filters ) corpus = [' '.join(analyzer.analyze(sentence)) + u'。' for sentence in text] #print(corpus, len(corpus)) # 文書要約処理実行 parser = PlaintextParser.from_string(''.join(corpus), Tokenizer('japanese')) # LexRankで要約を原文書の3割程度抽出 summarizer = LexRankSummarizer() summarizer.stop_words = [' '] # 文書の重要なポイントは2割から3割といわれている?ので、それを参考にsentences_countを設定する。 N = 3 summary = summarizer(document=parser.document, sentences_count = N if len(corpus) < 100 else int(len(corpus)/100)) #summary = summarizer(document=parser.document, sentences_count=1) str = '' for sentence in summary: str += (text[corpus.index(sentence.__str__())]) return str
def __init__(self): self.nlp = spacy.load('ja_ginza') self.analyzer = Analyzer( [UnicodeNormalizeCharFilter(), RegexReplaceCharFilter(r'[(\)「」、。]', ' ')], # ()「」、。は全てスペースに置き換える JanomeTokenizer(), [POSKeepFilter(['名詞', '形容詞', '副詞', '動詞']), ExtractAttributeFilter('base_form')] # 名詞・形容詞・副詞・動詞の原型のみ )
def summarize(text): sentences = [t for t in text.split('\n')] analyzer = Analyzer( [ UnicodeNormalizeCharFilter(), RegexReplaceCharFilter(r'[(\)「」、。]', ' ') ], # ()「」、。は全てスペースに置き換える JanomeTokenizer(), [ POSKeepFilter(['名詞', '形容詞', '副詞', '動詞']), ExtractAttributeFilter('base_form') ] # 名詞・形容詞・副詞・動詞の原型のみ ) corpus = [' '.join(analyzer.analyze(s)) + '。' for s in sentences] parser = PlaintextParser.from_string(''.join(corpus), Tokenizer('japanese')) summarizer = LexRankSummarizer() summarizer.stop_words = [' '] summary = summarizer(document=parser.document, sentences_count=3) x = "" for sentence in summary: x += sentences[corpus.index(sentence.__str__())] return x
def get_words(string, keep_pos=None): filters = [] if keep_pos is None: filters.append(POSStopFilter(['記号'])) # 記号を除外 else: filters.append(POSKeepFilter(keep_pos)) # 指定品詞を抽出 filters.append(ExtractAttributeFilter('surface')) a = Analyzer(token_filters=filters) # 後処理を指定 return list(a.analyze(string))
def set_analyzer(self): # 形態素解析器を作る self.analyzer = Analyzer( [ UnicodeNormalizeCharFilter(), RegexReplaceCharFilter(r'[(\)「」、。]', ' ') ], # ()「」、。は全てスペースに置き換える JanomeTokenizer(), [ POSKeepFilter(['名詞', '形容詞', '副詞', '動詞']), ExtractAttributeFilter('base_form') ] # 名詞・形容詞・副詞・動詞の原型のみ )
def get_summary(self): # 1行1文となっているため、改行コードで分離 sentences = [t for t in self._text.split('\n')] for i in range(1): print(sentences[i]) # 形態素解析器を作る analyzer = Analyzer( [ UnicodeNormalizeCharFilter(), RegexReplaceCharFilter(r'[(\)「」、。]', ' ') ], # ()「」、。は全てスペースに置き換える JanomeTokenizer(), [ POSKeepFilter(['名詞', '形容詞', '副詞', '動詞']), ExtractAttributeFilter('base_form') ] # 名詞・形容詞・副詞・動詞の原型のみ ) # 抽出された単語をスペースで連結 # 末尾の'。'は、この後使うtinysegmenterで文として分離させるため。 corpus = [' '.join(analyzer.analyze(s)) + '。' for s in sentences] """ for i in range(2): print(corpus[i]) """ # 転職 Advent Calendar 2016 - Qiita 14 日 目 なる 少し ポエム 含む。 # 今年 11 月 SIer Web サービス 会社 転職 する。 """ from sumy.parsers.plaintext import PlaintextParser from sumy.nlp.tokenizers import Tokenizer from sumy.summarizers.lex_rank import LexRankSummarizer """ # 連結したcorpusを再度tinysegmenterでトークナイズさせる parser = PlaintextParser.from_string(''.join(corpus), Tokenizer('japanese')) # LexRankで要約を2文抽出 summarizer = LexRankSummarizer() summarizer.stop_words = [' '] # スペースも1単語として認識されるため、ストップワードにすることで除外する self.summary = summarizer(document=parser.document, sentences_count=2) # 元の文を表示 for sentence in self.summary: print(sentences[corpus.index(sentence.__str__())])
def test_analyze(self): char_filters = [ UnicodeNormalizeCharFilter(), RegexReplaceCharFilter('蛇の目', 'janome') ] tokenizer = Tokenizer() token_filters = [ CompoundNounFilter(), POSStopFilter(['記号', '助詞']), LowerCaseFilter(), ExtractAttributeFilter('surface') ] a = Analyzer(char_filters=char_filters, tokenizer=tokenizer, token_filters=token_filters) tokens = a.analyze('蛇の目はPure Pythonな形態素解析器です。') self.assertEqual(['janome', 'pure', 'python', 'な', '形態素解析器', 'です'], list(tokens))
def lexrank_sumy(text, lang_number): ''' LexRankを実行する text:要約したい文章 ''' text = text.strip() sentences = re.findall("[^。]+。?", text) analyzer = Analyzer( [ UnicodeNormalizeCharFilter(), RegexReplaceCharFilter(r'[(\)「」、。]', ' ') ], # ()「」、。は全てスペースに置き換える JanomeTokenizer(), [ POSKeepFilter(['名詞', '形容詞', '副詞', '動詞']), ExtractAttributeFilter('base_form') ] # 名詞・形容詞・副詞・動詞の原型のみ ) print(lang_number) if lang_number == '1': corpus = [' '.join(analyzer.analyze(s)) + '。' for s in sentences] parser = PlaintextParser.from_string(''.join(corpus), Tokenizer('japanese')) print("japanese") elif lang_number == '2': corpus = [' '.join(analyzer.analyze(s)) + '. ' for s in sentences] parser = PlaintextParser.from_string(''.join(corpus), Tokenizer('english')) summarizer = LexRankSummarizer() summarizer.stop_words = [' '] summary = summarizer(document=parser.document, sentences_count=3) summary_text = '' for sentence in summary: summary_text = summary_text + sentences[corpus.index( sentence.__str__())] + '\n' return summary_text
def preprocess_target(doc, debug=False): doc = list(filter(lambda x: x.strip() != "", re.split("\n|。", doc.lower()))) sentences = copy.deepcopy(doc) doc = [mojimoji.zen_to_han(line) for line in doc] analyzer = Analyzer([ UnicodeNormalizeCharFilter(), RegexReplaceCharFilter(r'[(\)、。「」]', ' ') ], JanomeTokenizer(), [ POSKeepFilter(['名詞', '形容詞', '副詞', '動詞']), ExtractAttributeFilter('base_form') ]) corpus = [list(analyzer.analyze(line)) for line in doc] if debug: print(corpus) return sentences, corpus
# 1行1文となっているため、改行コードで分離 sentences = [t for t in text.split('\n')] for i in range(2): print(sentences[i]) # 転職 Advent Calendar 2016 - Qiitaの14日目となります。 少しポエムも含みます。 # 今年11月にSIerからWebサービスの会社へ転職しました。 # 形態素解析器を作る analyzer = Analyzer( [UnicodeNormalizeCharFilter(), RegexReplaceCharFilter(r'[(\)「」、。]', ' ')], # ()「」、。は全てスペースに置き換える JanomeTokenizer(), [ POSKeepFilter(['名詞', '形容詞', '副詞', '動詞']), ExtractAttributeFilter('base_form') ] # 名詞・形容詞・副詞・動詞の原型のみ ) # 抽出された単語をスペースで連結 # 末尾の'。'は、この後使うtinysegmenterで文として分離させるため。 corpus = [' '.join(analyzer.analyze(s)) + '。' for s in sentences] for i in range(2): print(corpus[i]) # 転職 Advent Calendar 2016 - Qiita 14 日 目 なる 少し ポエム 含む。 # 今年 11 月 SIer Web サービス 会社 転職 する from sumy.parsers.plaintext import PlaintextParser from sumy.nlp.tokenizers import Tokenizer from sumy.summarizers.lex_rank import LexRankSummarizer
def test_extract_attribute_filter(self): tf = ExtractAttributeFilter('surface') self.assertEqual(['風', '立ち', 'ぬ'], list(tf.apply(self.t.tokenize('風立ちぬ')))) tf = ExtractAttributeFilter('part_of_speech') self.assertEqual(['名詞,一般,*,*', '動詞,自立,*,*', '助動詞,*,*,*'], list(tf.apply(self.t.tokenize('風立ちぬ')))) tf = ExtractAttributeFilter('infl_type') self.assertEqual(['*', '五段・タ行', '不変化型'], list(tf.apply(self.t.tokenize('風立ちぬ')))) tf = ExtractAttributeFilter('infl_form') self.assertEqual(['*', '連用形', '基本形'], list(tf.apply(self.t.tokenize('風立ちぬ')))) tf = ExtractAttributeFilter('base_form') self.assertEqual(['風', '立つ', 'ぬ'], list(tf.apply(self.t.tokenize('風立ちぬ')))) tf = ExtractAttributeFilter('reading') self.assertEqual(['カゼ', 'タチ', 'ヌ'], list(tf.apply(self.t.tokenize('風立ちぬ')))) tf = ExtractAttributeFilter('phonetic') self.assertEqual(['カゼ', 'タチ', 'ヌ'], list(tf.apply(self.t.tokenize('風立ちぬ')))) # invalid attribute name with self.assertRaises(Exception): ExtractAttributeFilter('foo')
# 本文を抽出 (ヘッダとフッタを削除) text = ''.join(text.split('\n')[23:346]).replace(' ', '') # 注釈 ([]) とルビ (《》) を削除 text = re.sub(r'([.*?])|(《.*?》)', '', text) # 神の存在、及び人間の霊魂と肉体との区別を論証する、第一哲学についての省察 ... # pip install Janome from janome.analyzer import Analyzer from janome.charfilter import UnicodeNormalizeCharFilter from janome.tokenizer import Tokenizer from janome.tokenfilter import POSKeepFilter, ExtractAttributeFilter analyzer = Analyzer( [UnicodeNormalizeCharFilter()], Tokenizer(), [POSKeepFilter(['名詞', '動詞', '形容詞', '副詞']), ExtractAttributeFilter('base_form')] ) tokens = [token for token in analyzer.analyze(text)] # ['神', '存在', '人間', '霊魂', '肉体', ... ] with open('./input.txt', 'w') as f: f.write(' '.join(tokens)) with open('./vectors.txt', 'r') as original, open('./gensim_vectors.txt', 'w') as transformed: vocab_count = vectors.shape[0] # 単語数 size = vectors.shape[1] # 次元数 transformed.write(f'{vocab_count} {size}\n') transformed.write(original.read()) # 2行目以降はそのまま出力
# ・・・ (省略) ・・・ だからこそ、有給消化期間はなんとしてでももぎ取るようにしましょう。""" # 1行1文となっているため、改行コードで分離 sentences = [t for t in text.split('\n')] for i in range(2): print(sentences[i]) # 転職 Advent Calendar 2016 - Qiitaの14日目となります。 少しポエムも含みます。 # 今年11月にSIerからWebサービスの会社へ転職しました。 # 形態素解析器を作る analyzer = Analyzer( [UnicodeNormalizeCharFilter(), RegexReplaceCharFilter( r'[(\)「」、。]', ' ')], # ()「」、。は全てスペースに置き換える JanomeTokenizer(), [POSKeepFilter(['名詞', '形容詞', '副詞', '動詞']), ExtractAttributeFilter( 'base_form')] # 名詞・形容詞・副詞・動詞の原型のみ ) # 抽出された単語をスペースで連結 # 末尾の'。'は、この後使うtinysegmenterで文として分離させるため。 corpus = [' '.join(analyzer.analyze(s)) + '。' for s in sentences] for i in range(2): print(corpus[i]) # 転職 Advent Calendar 2016 - Qiita 14 日 目 なる 少し ポエム 含む。 # 今年 11 月 SIer Web サービス 会社 転職 する。 # 連結したcorpusを再度tinysegmenterでトークナイズさせる parser = PlaintextParser.from_string(''.join(corpus), Tokenizer('japanese')) # LexRankで要約を2文抽出
from janome.tokenizer import Tokenizer from janome.analyzer import Analyzer from janome.charfilter import UnicodeNormalizeCharFilter from janome.tokenfilter import ExtractAttributeFilter, POSStopFilter t = Tokenizer(mmap=True) # An analyzer need 3 parameters, which are: char_filters, tokenizer, token_filters a = Analyzer([UnicodeNormalizeCharFilter()], t, [POSStopFilter(['記号']), ExtractAttributeFilter('surface')]) # Split text into words, only remove punctuation. def split_words(text): return list(a.analyze(text))
index = columns[0].split("-")[0] if not index in texts: texts[index] = "" continue texts[index] = texts[index] + columns[1] #形態素解析 char_filters = [ UnicodeNormalizeCharFilter(), RegexReplaceCharFilter('\d+', '0') ] tokenizer = Tokenizer(mmap=True) token_filters = [ POSKeepFilter(["名詞", "形容詞", "副詞", "動詞"]), LowerCaseFilter(), ExtractAttributeFilter("base_form") ] analyzer = Analyzer(char_filters, tokenizer, token_filters) #単語抽出とストップワード stopwords = [] url = "http://svn.sourceforge.jp/svnroot/slothlib/CSharp/Version1/SlothLib/NLP/Filter/StopWord/word/Japanese.txt" with urllib.request.urlopen(url) as response: stopwords = [w for w in response.read().decode().split('\r\n') if w != ""] texts_words = {} for k, v in texts.items(): texts_words[k] = [w for w in analyzer.analyze(v)]