自分で書いた会話シミュレーションだけでは面白くない。そこで、自分も知らない言葉や単語を聞かれたときは、ウィキペディア(wikipedia)の膨大なフリー百科事典で検索してみることにした。例えば、ラピロに質問してみる「外傷って何ですか?」(いや、知っているよ。知っているけれど、サンプルとして聞いただけ)。そしたら、ラピロは、こう答える「外傷とは、身体を構成している組織の生理的な連続性が断たれた状態のこと。機械的外力(力学的外力)による損傷。目視可能な損傷、比較的軽度な損傷などの俗称。の事ですよ」。ね、ラピロのIQが一気に100を超えそうな気がしませんか?
インターネットのウィキペディアを検索するには、wikipediaのpythonライブラリをインストールします。
$ sudo pip install wikipedia # Wikipediaライブラリをインストール Downloading wikipedia-1.4.0.tar.gz
2017年7月時点では、version1.4.9のwikiライブラリがダウンロード、インストールされました。
pythonインタプリタを実行して、コマンドラインでwikiを検索して動作を確認する。ひえええー。本当にこの3行だけでWikiサイトからデータを取得出来ちゃったよ。
pi@raspberrypi:~$ python >>> import wikipedia >>> wikipedia.set_lang("ja") >>> print wikipedia.summary("外傷") 外傷とは 身体を構成している組織の生理的な連続性が断たれた状態のこと。本項で詳述する。 機械的外力(力学的外力)による損傷。目視可能な損傷、比較的軽度な損傷などの俗称。 外傷(がいしょう、英: injury, trauma)とは、外的要因による組織または臓器の損傷の総称。 通常、怪我(けが)と呼ばれ、外傷を負うことを負傷(ふしょう)といい、外傷を負った者を 負傷者(ふしょうしゃ)という。なお、死亡と外傷をあわせて死傷(ししょう)といい、死亡 した者と外傷を負った者とを合せて死傷者(ししょうしゃ)という。精神医学において、心理 的外傷を単に外傷と呼ぶことがある→心的外傷(トラウマ)を参照。身体的外傷の場合、広義 には、物理的あるいは化学的な外的要因による損傷すべてを指すが、通常は機械的外力(力学 的外力)による損傷を指す。
でも説明長い。ラピロに喋らせるには少々面倒です。ここで戻値の文章の数を指定できます。
pi@raspberrypi:~$ python >>> import wikipedia >>> wikipedia.set_lang("ja") >>> print wikipedia.summary("外傷", sentences=1) 外傷とは 身体を構成している組織の生理的な連続性が断たれた状態のこと。
知りたい単語の意味を説明するには不十分なので、2~3文は必要かも。
ラピロのメインスクリプトに組み込む前の最終テストとして、小さいスクリプト(wikitest.py)を書いてみた。例えば「外傷」を聞くなら、[python wikitest.py 外傷]を実行する。すると、ラピロがインターネットのwikipediaで調べた結果を、前回までに作ったjtalkスクリプトで音声合成して喋ってくれる。
▽ スクリプト
#!/usr/bin/env python # -*- coding: utf-8 -*- # wikitest.py import wikipedia import sys import os # Wikiの検索 def main_wiki( strText ): # 単語のサマリーを取得。 print( strText + "ですね。ちょっとお待ちください。" ) wikipedia.set_lang("ja") #print wikipedia.summary( strText ) try: strReturn = wikipedia.summary( strText, sentences=1 ).encode("utf-8") except: print( "いっぱい考えたけど、思い出せなかっです。" ) finally: print( strReturn ) strReturn = strReturn + "の事です。" strCMD = "./jtalk.sh '" + strReturn + "' 'normal'" os.system( strCMD ) # タイトルの取得。 #print( "▼タイトル" ) #ny = wikipedia.page( strText ) #print( ny.title ) # 単語の詳細情報を取得。 #print( "▼詳細情報" ) #print( ny.content ) とても口語で喋るには情報量が多すぎるのでコメントアウト。 # 初期設定 if __name__ == '__main__': if (len(sys.argv) <= 1): print("Syntax: python wikitest.py '[text]'") sys.exit() else: main_wiki( sys.argv[1] )
▽ 実行結果
# python wikitest.py 外傷 外傷ですね。ちょっとお待ちください。 外傷とは 身体を構成している組織の生理的な連続性が断たれた状態のこと。の事です。
何を聞いても回答してくれる。ラピロが凄く頭良くなった。
Wikipediaの別の使い方として、wikiにはダウンロード用のデータファイルが用意されている。これはwikiのwebサイトをクローリングしてデータを取り出しちゃおうという人が増えてWebサイトの負荷が高まってしまうことを避ける目的と思われる。wikiのデータ(jawiki-latest-pages-articles.xml)は解凍後で10GBを超える巨大なファイルだった。SQLなどで検索するには、XMLファイルをRDBなどに変換した方がいい。下記pythonスクリプトで直接XMLファイルを検索することも出来たが、検索に58秒かかった。
考察の結果としては、簡単にwikiを実装するならインターネットwikiを検索する方が、(1)速い (2)簡単:インストール不要 (3)最新の辞書データを参照できる。ダウンロードした時の利点は、(1)オフラインでも使える (2){あり得ないだろうけれど}将来wikiがサービス終了になったりしても使い続けられる だろうか。
▽ スクリプト
#!/usr/bin/python # -*- coding: utf-8 -*- # Wikipediaから記事をパースする import xml.sax import xml.sax.handler import sys import string glbTitle = False glbSearch = False glbComment = False glbKeyword = "" glbCount = 0 class Handler( xml.sax.handler.ContentHandler ): def startElement(self, name, attrs): global glbTitle, glbComment if( name == "title" ): glbTitle = True if( name == "text" ): glbComment = True def endElement(self, name): global glbTitle, glbComment if( name == "title" ): glbTitle = False if( name == "text" ): glbComment = False if( glbSearch == True and name == "text" ): sys.exit() def characters(self, content): global glbSearch, glbCount if( glbTitle == True ): #print "Title:" + content #if( string.find(content, glbKeyword ) != -1 ): if( content == glbKeyword ): glbSearch = True if( glbSearch == True and glbComment == True ): if( glbCount < 10 ): print content glbCount = glbCount + 1 return def main( strKeyword ): global glbKeyword glbKeyword = strKeyword print( "<" + strKeyword + ">" ) # SAX XMLReaderオブジェクトを生成する parser = xml.sax.make_parser() # XMLReaderにイベントのハンドラーを設定する。 parser.setContentHandler( Handler() ) # XMLReaderが、入力ソースを使ってSAXイベントを発生させる。 parser.parse(open("jawiki-latest-pages-articles.xml","r")) return if __name__=="__main__": if ( len(sys.argv) < 1 ): print( "Syntax: python try_readxml.py" ) else: main( sys.argv[1].decode("utf-8") )
▽ 実行結果
# python try_readxml.py 外傷 <外傷> {{otheruses|身体的外傷|心理的外傷|心的外傷}} '''外傷'''とは #身体を構成している組織の生理的な連続性が断たれた状態のこと。本項で詳述する。 #[[機械]]的外力([[力学]]的外力)による損傷。目視可能な損傷、比較的軽度な損傷などの俗称。 ----
Pythonのwikipediaライブラリを使うと、最小、僅か3行のスクリプトを追加するだけで、インターネットのフリー百科事典を検索してデータを取得することができた。ラピロに組み込むことで、自分でWikiを検索できる、とっても頭のいいロボットになった。意外なことにインターネットの日本語ブログなどで「Pythonのwikipediaライブラリ」を使った事例が掲載されていないので、ついつい、wiki全項目のデータダウンロードを最初に試してしまい2日間くらい余計な作業をしてしまったけど、オンライン版wiki検索ライブラリはお薦め。