MextractrAPIを使ってみた。

 文章を渡すとそこから地名や日付を抽出してくれる、Mextractr WebAPIというAPIがあります。

WEBにある文章から、そこに書かれている日付や場所、金額などが抽出できると、その内容をカレンダーに転記するとか、金額だったらうまい棒○本分に換算して表示するとか、いろいろとワクワクする展開が考えられますよね。



実は、自分も過去に同じようなことを考えて、未踏ソフトウェア創造事業に提案させていただいたことがあります。このときは、やり方にあまり斬新さがなかったので未踏的じゃない、ということでNGだったのですけど。



解析機能を提供していただけるのであれば、実現したいアプリケーションのアイデアはいくつもあるので、早速使ってみました。

使ってみた

 サンプルコードまで出していただいているので、使うのは難しくありません。

Mextractr_api_url = 'http://api.emetadata.net/mextractr?text=[[text]]&out=[[out]]&apikey=[[apikey]]'
#解析して欲しい文字列をエンコードして
text_encoded = CGI.escape( CGI.escapeHTML(text.toutf8) )
#Mextractr APIを呼び出す
uri = URI.parse( Mextractr_api_url.gsub('[[text]]',text_encoded).gsub('[[out]]','atom').gsub('[[apikey]]',@apikey) )
response = nil
Net::HTTP.start(uri.host,uri.port){|http|
response = http.post(uri.path,uri.query)
}

で、帰ってきた結果をrexmlで解析してあげればOKです。



サンプルコードでは、結果をGETでとってきていたのですけど、URLに解析対象の文字列を丸ごと含むのはきついと思うので、POSTするようにしました。試しに投げてみたら値が帰ってきているので、きっとこれでOKです(笑)



ということで、結果のxmlをハッシュに変換するところまでで一つのクラスにまとめてみました。クラスを作って、parseメソッドにテキストを渡したら結果が帰ってきます。

mextractrAPI.rb

[名前] MextractrAPI
[概要] Mextractrサービス(http://api.emetadata.net/)をrubyから使うためのラッパークラス
[作成] 2008-08-27 古川大輔(mogya at mogya.com)
[用法] http://api.emetadata.net/からAPIキーを取得しておく必要があります。
#取得したAPIキーをつかってMextractrAPIクラスを生成
api = MextractrAPI.new('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
#解析したいテキストを渡す
result = api.parse(text)
結果がどのように格納されているかは、 pp result して見てください。

Mashup Awards 4に応募しようと思っている方もそれ以外の方も、自由にお使いください(^^)

気づいたこと

複数の要素を検知したときに、重要度とか確からしさをつけて欲しい。


 文章中に日付とか場所が複数あった場合、それらは並列されて帰ってきます。

"where"=>
[{"georss:point"=>"42 -104.1", "valueString"=>"沖縄"},
{"georss:point"=>"13.15 144.5", "valueString"=>"グアム"},
{"georss:point"=>"13.15 144.5", "valueString"=>"グアム"}],
"when"=>
[{"valueString"=>"27日", "startTime"=>"2008-08-27"},
{"valueString"=>"2009年度", "startTime"=>"2009-01-01"}],

 個人情報フィルタではこれでいいのだと思いますけど、文章からメタデータを取り出す上では、どれか一個、代表値が欲しいです。

たとえば、「日時:」で始まるデータは重要度が高いとか、日付の後ろに時刻まで書いてあったら確からしさが高いとか、そういう情報を付加していただけると嬉しいです。



whenで時刻は検知してくれないの?


 今のところ、whenとして帰ってくるのは日付だけみたいです。

「来る5月23日10時から、定時株主総会を墨田区の弊社本店A会議室にて開催いたします。」と渡しても、2009/5/23までしか見ていただけません。

日付しか返さないのだったらstartTimeじゃなくてstartDateのような。



バージョンアップして時刻も対応していただけることを期待しております(^^)


gcalapiで”Invalid date/time value”(GoogleCalendar::EventInsertFailed)

rubyからGoogleCalendarにアクセスできるgcalapiを使ったアプリケーションを書いているのですが、こんなエラーが出て苦労しました。


/usr/lib/ruby/gems/1.8/gems/gcalapi-0.1.1/lib/googlecalendar/event.rb:130:in `save!’: [Line 8, Column 106, element gd:when] Invalid date/time value. (GoogleCalendar::EventInsertFailed)

from mail2gcal.rb:87:in `from_mail’

from mail2gcal.rb:102

from /usr/lib/ruby/1.8/net/pop.rb:528:in `each’

from /usr/lib/ruby/1.8/net/pop.rb:528:in `each_mail’

from mail2gcal.rb:97

要するに、GoogleCalendarにポストしたら “Invalid date/time value”といわれました、ということらしい。

Googleのドキュメントをあさると、

Invalid date/time value

The value you entered is not a valid date/time. Please enter a date and time in the correct format: YYYY-MM-DDThh:mm:ss. For example, “1975-09-25T06:20:00” is a valid date/time value, but “June 2005 5pm” is not.

(Invalid date/time value | Google Base Help Centre)

というのを発見。



「DateTimeは”1975-09-25T06:20:00″のフォーマットで渡してね」ということ。

そんなこと言われてもgcalapiにはDate型を渡しているし、うまくいく場合もあるからgcalapi側が変な形式のデータを渡しているとは考えにくい。ソース見ても、dt.iso8601 ってやっているし。





 試行錯誤した結果、 event.enを渡さないとエラーになるらしいことが判明。

event.st = Time.parse(yaml[“st”].to_s) if yaml.has_key?(“st”)

# event.en = Time.parse(yaml[“en”].to_s) if yaml.has_key?(“en”)



 gcalapiのサンプルについているmail2gcalに対して、

st: 2008-09-06 19:20:36

title: title of an event

desc: description of an event

where: location of an event

というメールを投げると再現します。



gcalapiとしては、開発者が渡したデータを適切に変換してGoogleCalendarに渡して、その結果帰ってきたエラーを適切に報告していただけているのだから、別にgcalapiが悪いわけじゃないと思うのですが。はまったので一応メモということで。



こういうのを調べるとき、原因がgcalapiや自分のアプリにあるのか、それともGoogleCalendarにあるのか切り分けるために、gcalapiがポストしたデータを見る方法ってないものでしょうか。パケットキャプチャ以外で。