非プログラマーのためのインフォマティクス入門。(仮)

非プログラマーがインフォマティクスについて勉強したことを記録します。主にKNIMEというソフトを使用しています。

非プログラマーのためのインフォマティクス入門。(仮)

KNIMEで明日の天気を調べよう! 〜REST APIの活用〜

今回はKNIMEを使って、明日の天気予報を調べてみようと思います。

…このこと自体に大して意味はありません。

ポイントは

KNIMEはweb上の情報も取得することができる

という点です。

 

 色んな方法があるのですが、今回はわりと分かりやすい「REST API」を活用した方法を紹介しようと思います*1

例として取り上げる題材は、無料&内容が分かりやすいLivedoor天気情報を利用させていただくことにします。

weather.livedoor.com

 

上リンクの内容を確認していただくと次のような記述があります。

(例)「福岡県・久留米の天気」を取得する場合

下記URLにアクセスしてJSONデータを取得します。
基本URL + 久留米のID(400040)

 REST APIという方法の正確な解説は私にはちょっと難しいですが、ざっくりと言うと

Livedoorさん!(http://weather.livedoor.com/***/)、JSONという形式で(json/v1/)、久留米(?city=400040)のお天気情報を教えてください」

という呪文を詠唱すると、希望通りの情報を召喚できるというものです。

 

呪文の唱え方としては、例えばwebブラウザのアドレスバーににhttp://*****/400040を入力してgoすると次のように久留米のお天気情報が返ってきます。

f:id:sumtat:20170902095152p:plain

文字コードの関係で、ちょっと見苦しいキャプチャですが、こんな感じです。一見汚そうに見えますが、これはJSONという形式で書かれた綺麗な情報です(後述)!この中から、必要な情報をKNIMEを使って抜き取れば良いということです。

 

ということで、全国分の明日のお天気をKNIMEを使ってgetしてみようと思います。

フローの全体像としては次の通りです。

f:id:sumtat:20170902100233p:plain

 

上下の2つに分岐していますが、やっていることは同じです。両方とも紹介します。

それでは最初から順を追って解説していきます。

 XML Reader

名前の通り、xml形式のファイルを読み込むためのノードです。

まずは全国分の都市IDを取得するために

http://weather.livedoor.com/forecast/rss/primary_area.xml

を読み込みます。

f:id:sumtat:20170902101352p:plain 

 この作業からも、既にわかると思いますが、KNIMEではweb上の情報にアクセスすることが可能です。実行結果を見てみます。

f:id:sumtat:20170902101923p:plain

「うわー、なにこれー」と感じる方もいるかもしれません。でも、ちょっと我慢して内容を見てください。

このxmlファイルにはまず【道北】というカテゴリがあって、その中に【稚内旭川・留萌】という都市がある。そして、その都市IDは【011000・012010・012020】であることがわかります。

また【道東】というカテゴリもあって、その中には【網走・北見etc】という都市があり、その都市IDは【013010・013020 etc】であるということもわかります。

 

そうなんです。とっても綺麗なデータです!(JSONも似たような感じです)

 

 私も初めてみたときは難しそうだなと思いましたが、少し読んでみると、パズルみたいでなんだか面白いなーと思うようになりました。

「私はこういうのはちょっと…」みたいなおじさま方は食わず嫌いなところがあります。自分の知らない・理解できない新しいことに対して否定的であったり、壁を作ったりする傾向があります(少なくとも私の周りでは。場合によっては潰しにかかることも)。

偉そうですが、私からのメッセージです。

〜まずはひとくち食べてみて下さい。世界が変わりますよ〜

 

さて、話が脱線しましたが、このxmlの中身の欲しい部分を抜き出していこうと思います。

 

XPath 

xml内の必要な部分を抽出するためのノードです。お手軽xmlパーサー的な感じでしょうか?使い方に少し慣れが必要ですが、便利です。設定画面を見てみましょう。

 

f:id:sumtat:20170902105755p:plain

 処理対象となるxmlが記述されているカラムを画面上部のXML columnで指定します。すると、画面下部にxmlの中身がプレビューされます。

 まずは先ほどの【道北・道東】のようなカテゴリごとにxmlの内容をぶった切ろうと思いますので、プレビュー内でprefの部分をクリックします。すると画面中段のSelect XPathの部分に緑色でパスが表示されます。*2

続けてAdd XPathをクリックすると新たな設定画面が開きます。

 XPath data typeをNode cellとしました。これは各カテゴリ(pref : 道北・道東など)に分割した内容を再度xmlとして吐き出させ、もう一度XPathを通してID部分を抜き出すためです。本質的には不要な部分ですが、XPathの振る舞いを理解するのには、こういう感じにするとわかり易いかな?と考えたため載せました。

 また、Multiple tag optionsはMutiple Rowsにしました。これはぶった切った内容を新たな行として(縦方向)に並べるという設定です。

 キャプチャではチェックが入っていませんが、画面上部のRemove source columnにチェックを入れて実行すると次のようになります。

 

f:id:sumtat:20170902110808p:plain

もとのxmlが小分けのxmlになりましたね。

 

では本質である、都市IDの取得をします。再度XPathノードをつなげます。

 

f:id:sumtat:20170902111157p:plain

 

今度はidの部分を選択し、String cellとして書き出します(Multiple Rowsとして)*3

おまけで、titleも同様な設定で追加しました。この設定で実行すると次のようになります。

f:id:sumtat:20170902111448p:plain

全国の142都市の名前と都市IDがテーブルにまとまりました。

それでは冒頭で紹介したように、天気情報を取得するための呪文

http://weather.livedorr.com/forcast/webservice/json/v1?city= + 都市ID

String Manipulationを使って作成します。

f:id:sumtat:20170902141510p:plain

 

作成した内容はtargetというカラム名にして吐き出させました。

f:id:sumtat:20170902142802p:plain

このテーブルを1行ずつ変数にして、targetをwebに投げてやる必要があります。

sumtat.hatenablog.com

を読んでいただければ、Chunk loop start, Table row to variableに関してはご理解いただけるものと思います。

 

JSON Reader

返ってくる天気情報はJSON形式なので、JSON Readerを使います。

f:id:sumtat:20170902143434p:plain

これも過去記事通りではありますが、読み込むJSON(今回はwebに投げるクエリ)である変数:targetを指定して実行します。

 

まずは上段です。

JSON Path

XPathJSON版ですね。実行して得られた天気情報(JSON形式)から所望の場所を抜き出します。

f:id:sumtat:20170902144621p:plain

 

使い方はXPathとほぼ同じです。

f:id:sumtat:20170902145320p:plain

今度は、値の部分をクリックします。つまり、道北をクリックするとグレーに反転するので、この状態でAdd single queryをクリックします。マウスオンすると対象となるパスを見ることができます。今回は続けて、【北海道】【稚内】【明日】【曇り】【13(最低気温℃として)】【17(最高気温℃として)】を更に追加し、次のようにしました。

f:id:sumtat:20170902145752p:plain

 

この設定で実行すると次のような結果になります。

f:id:sumtat:20170902145915p:plain

さて、loop endまで実行させて、全国分の明日の予報をゲットします。*4

結果はこうなります。

f:id:sumtat:20170902150315p:plain

どやぁ!

登録されてる142都市の明日の天気と最高・最低気温が一挙に取得できました。

 

JSON Path使って切り出すのがめんどくせぇ。そんな方には下段のフローも参考にしてみて下さい。

 

JSON to Table

これを使うと、JSON形式で書かれた内容を勝手にテーブルに変換してくれます。

今回の場合はこんな感じになります。

f:id:sumtat:20170902151101p:plain

 

 67個のカラムを持つテーブルが出来上がりました。この状態にしてからcolumn filterを使って必要なカラムだけに絞ればOKという考え方です。

 また、必要な部分のみを残すという作業を加えないと、Loop Endにたどり着くデータ(カラムの数・内容)がループの周回によって異なる場合があります。その場合Loop処理が止まってしまいますので、必ず同じ項目がLoop Endにたどり着くためにも、この位置にColumn filterが必要となります。

f:id:sumtat:20170902151421p:plain

 

 必要な部分だけをEnforce inclusionとして指定しました。この設定でLoop Endまでまわしますよー!

f:id:sumtat:20170902151616p:plain

最後に気を利かせてカラムの順番くらい変えてみましょう。

Column Resorter

これも名前の通り。カラムの順番を変えることができます。

f:id:sumtat:20170902151748p:plain

右側のupとかdownとかを使って、いいかんじにして下さい。

これで、上段フローの結果と同じものを作ることができるはずです。

 

ちょっと長くなりましたが、いかがでしたか?

例えば稚内だけ、ピンポイントで情報が欲しければこんなことをしても全く意味ありません。むしろ効率が悪いです。

関連する情報を網羅的に取得し、それを自分で解析しながら活用する

そんな使い方をするときに効果を発揮すると思います。

 

 私の場合は、新しい研究テーマに着手するときなどに文献情報をこんな感じで取得することがあります。狭い分野&今回の内容とほぼ同様の話になりますが、近いうちに、chemblからの情報の取り方を紹介してみます。

 

 取得した文献情報と自然言語処理を組み合わせることができるようになるといいなと思って個人的には勉強をしているところです。

 

 最初のテスト投稿を除けば、今回は30記事目になります。KNIMEに興味を持っていただけた方がいらっしゃれば嬉しいです。

 今後もできる範囲で更新していこうと思います。コメントなどもお待ちしております! 

 

ではまた!

 

 

*1:webページのhtmlをそのまま取ってきたり、SPARQLのEndpointに繋いだり、できることはたくさんありますよ!

*2:もしここが赤字の場合はパスとしては不適切な部分が選択されていますので見直して下さい。

*3:繰り返しになりますが、本当は元のxmlに対して、この処理だけすればIDを取得できます。また都市名もRESTを使うのには本来は不要ですから、titleを取得する必要はないです。

*4:time outエラーになって途中で止まるかもしれませんが、続けてexecuteすれば処理を続きから再開してくれます