山内長承「Pythonによるテキストマイニング入門」のMeCabの扱いと、クラスAozoraについてのメモ


はじめに

山内長承「Pythonによるテキストマイニング入門」第4章でMeCabを使うが、詳しいインストール方法が書かれていない。別のサイトを参考にMeCabをインストールした上で、山内の著書内にある引数を変更したのでメモをしておく。
また、本書で使われる、青空文庫にあるファイルをタグ抜きに変換するAozoraクラスについても、メモをしておく。

開発環境

windows10

セットアップ

[文章生成]MeCabをインストールして分かち書きを試してみよう
https://www.atmarkit.co.jp/ait/articles/2102/05/news027.html

を参考にして、インストールをした。

上記の方法でインストールした場合は、p124「リスト4-2」の10行目にある
m = MeCab.Tagger("-Ochasen")
は、引数を付けずに、
m = MeCab.Tagger()
として実行する必要がある。

出版社のサイトにあるサンプルコードの、aozora.pyについて

なお、出版社のサイトにあるサンプルコードのaozora.pyでは、48行目で、aozora = Aozora("wagahaiwa_nekodearu.txt")とファイル名が直打ちされているので、第4章で使う時には、47行目以降はコメントアウトしておく必要がある。

コメントアウトしておかないと、aozora.pyを読み込む、list-4-2_word-frequency-countl-wagahai.pyや、list-4-3_word-per-sentense-wagahai.pyなどを実行すると、実行ファイルで分析するテキストファイルを別に指定しても、wagahaiwa_nekodearu.txtが読みに行かれてしまう。
ファイルがなければエラーになるし、あっても、aozora.pyの51行目のprint文が実行されて、指定されたwagahaiwa_nekodearu.txtが表示された後で、本来指定したファイルの分析結果が出る、という状況になっている。

メモ。aozoraクラスの役割

引数として与えられたテキストファイルを読み込み、青空文庫のフォーマットに基づきタグなどを削除し、プレーンテキストへ変換して、内部変数であるcleanedparagraphsに、単語を成分としたリストを持つまでの処理が、初期処理で行われる。
read()メソッドにより、cleanedparagraphsにある、単語を成分としたリストを返す。

同じread()メソッドでも、
Pythonの一般的なテキストファイル処理の
with open(path) as f:
s = f.read()
はstring typeが返ってくるが、aozora.read()はlist typeを返すので、注意が必要。

aozora = Aozora("テキストファイル")で作られるインスタンスはAozoraで定義されたものであり、print(aozora)とかしても、文章は出力されない。

メモ。p68のプログラムの変数stringのtypeの変化について

p68の、それぞれの文の長さを数えるプログラムで、使われている変数stringの型が途中で変わり戸惑ってしまったので、メモとして書いておく。

aozora.read()は、上に書いた通り、引数として指定されたテキストファイルを品詞で分解したものを成分としたリスト。

最初に出てくるstring変数は、aozora.read()を改行でjoinして得られるstr型で、これに元のテキストの文章が1つながりで入っている。

次のstring変数は、テキストに含まれる全角スペースを削除するだけで、str typeのまま。

3番目のstring変数は、句点などで改行し、一文毎が成分となるlist typeとなる。
この正規表現については、下に記す「p68、p116の、青空文庫のテキストを編集する際に行う、re.split('。(?!」)|\n,string)処理について」を参照。
なお、3番目のstring編集の処理で、1つ上の行と同じre.sub(' ', '', string)が出てくるが、おそらく誤植。単なる重複処理なので、このままでも問題は起こらないが。
同じような処理である、p116では、2行目と3行目の処理は、1つにまとめられている。

メモ。p116のプログラムの変数stringのtypeの変化について

処理そのものは、上のp68と同じだが、微妙に処理が違うので戸惑う。

aozora.read()は、上に書いた通り、引数として指定されたテキストファイルを品詞で分解したものを成分としたリスト。

最初に出てくるstring変数は、aozora.read()を改行でjoinして得られるstr型で、これに元のテキストの文章が1つながりで入っている。

その次の、splitによって、句点と改行で分割して得られるstringはlist型で、さきほどのaozora.read()と同様、1つの文章が1つずつの要素として入っている
この正規表現については、下に記す「p68、p116の、青空文庫のテキストを編集する際に行う、re.split('。(?!」)|\n,string)処理について」を参照。

メモ。p68、p116の、青空文庫のテキストを編集する際に行う、re.split('。(?!」)|\n',re.sub(' ', '', string)処理について

Pythonとしての正規表現の話と、日本語テキスト処理の話が一緒になっていて戸惑ったのでメモをしておく。
この処理では、基本的には、句点”。”、もしくは改行(\n)があれば、その度に文字列を分割し、リストの要素として、変数stringに入れられる。
句点と改行を、|で区切った、new_strings = re.split('。|\n',old_string)、という意味合いである。
しかし、青空文庫のテキストでは、鍵括弧で囲まれた台詞の末尾に、句点”。”が来ることがある。本書で扱っている「吾輩は猫である」では、”。」”の表記は1か所だけなのだが、「走れメロス」は、台詞の末尾すべてが、”。」”となっている。
この”。」”に対して、句点で改行の処理をしてしまうと、”」”だけの一文が大量に発生してしまうので、re.splitの処理で、”。」”に対しては、”(?!」)”を入れることで、除外するようにしている。
本書では、第4章p116のコメントには”。」の。は改行しない」とあるのだが、第3章p68では、そのコメントが漏れてしまっている。

なお、ここで使われている正規表現については、
先読みと後読みを使ったパターン 3.否定先読み
https://www.javadrive.jp/regex-basic/writing/index2.html#section3
が参考になる。

日本語テキスト処理の話を続ける。本書の内容を理解するだけなら、この節の以下の話は読み飛ばして良い。
台詞の末尾が、”。」”となっている理由は、青空文庫だから、ではない。作者の意向でもない。書式をどうするかは、出版社によって異なっており、青空文庫が定本とした本では、”。」”が使われているから、というのが理由である。太宰の他に、芥川などもそうしてあり、それが当時の出版慣例であった。
現在の出版慣例では、台詞の末尾には句点は付けない。ただ、「走れメロス」について言えば、青空文庫が定本にしているちくま文庫版では、”。」”は今でも使われているが、新潮文庫版では、台詞末尾の句点は省かれている。
著作権が消滅した古いテキストを扱う時には、現在の出版慣例との表記の違いにも留意する必要がある。
”。」”の扱いについては、テキスト解析の段階で行うのではなく、前処理段階で、”。」”は”」”に変換しておいた方が、分かりやすいだろう。

初心者向けメモ。Counterクラスの引数は文字列でもリストでも良いことについて

第4章で使う、Counterクラスは、p108にあるように、文字列でもリストでも良い。本書では、
文字列は、p108、p109など
リストは、p110、p114など
で使われている。同じクラスに対して、引数が文字列でもリストも入ることについては、私を含めたPython初学者は、
str = "吾輩は猫である"
for i in str: print(i)

list = ["吾輩", "は", "猫", "で", "ある"]
for j in list: print(j)
の実行結果を考えると、既存の知識と、このCounterクラスの動きとの結びつきが見えてくるだろう。