mattak's blog

人生を1ミリ進める

続:声優の名前から出演アニメを出すAPIをつくろう

たまこマーケットいいはなしだった。明日も見に行こう。

今日やること

APIの仕組みはできた。 wikipediaからのスクレイピングがいまいちなので、調整する。

抽出するパターン

wikipediaによく表記されるパターンは以下の通り.

; キャラクター (ふりがな)
: 声 - [[声優名]]

他にも声の部分が "声優|声"になっていたり、"声優名"が"声優名"になっていたり。 ラブライブなんかの説明は以下のようになっていたりする。

 ===== キャラクター =====
 : 声 - [[声優名]]

また1人のキャラに複数の人が声を当てているケースも多々ある。

  : 声 - [[中村悠一]]、[[喜多村英梨]](幼少時代)
  : 声 - [[梁田清之]] / [[小杉十郎太]] / 梁田清之 / [[小野大輔]] / 同左(小学生時代 - [[高森奈津美]])
  : 声 - なし / 同左 / 真殿光昭 / なし / [[長克巳]]

最後の場合は"なし"、"同左"などかなりノイズがある。 完全網羅をめざすのではなく、ある程度のデータを自動でパースすることを目的とするので、とりあえず"声優名"出ないパターンは考えない。

  :; ヒビキ・レイティス
  :: 声 - [[近藤隆]]

また、": 声 -" のパターンで引っかからないものは基本的に無視する。

そのご...

よっしゃー!! 一部キャラをparseできてないけど、とりあえず主要なものは網羅できた! 2014-04のアニメ枠のキャラをとりあえずだいたいOK!

データを登録する

wiki -> データのパースはできた。 データをdbにぶち込みたいけど、生でSQLをたたかずにcurl経由で更新してみる.

$ rails routes
...
programs GET    /programs(.:format)                programs#index
               POST   /programs(.:format)                programs#create
...

上記コマンドで現在のAPIが確認できた。 controllerのprograms#createで更新をしてくれるようだ。

programs_controller.rbをみる

def create
  @program = Program.new(program_params)
  ... 
      if @program.save
  ...
end

ModelのProgramにパラメータを渡して実行しているだけのようだ。 program_paramsがどのようにわたってきているか、どのような仕組みでinjectしているか不明だが、とりあえず気にしない。 変数のcontextが暗黙的すぎて気持ち悪いが、気にしないで規約でかけるのがrailsなのだろう。

Modelのprogramをみてみる。 どこにも変数宣言がない。これまた暗黙的なのだろう。気にしない、

db/schema.rbをみて、Programの宣言を思い出す.

create_table "programs", force: true do |t|
  t.string   "title"
  t.date     "from"
  t.datetime "created_at"
  t.datetime "updated_at"
end

おそらくform[title]=""とform[date]=""な値があれば大丈夫そう.

$ curl -X POST -d "form[title]=test" -d "form[date]=2014-04-05" http://localhost:3000/programs > tmp.html

だめだったorz ActionController::InvalidAuthenticityToken

CSRF対策? - http://maskana-soft.com/rails/pro/body/95

/programs/newのformをみたら、authenticity_tokenがhidden fieldで与えられていた. というか必要なfield値は以下の通りだった。

  • program[title]
  • utf8
  • authenticity_token
  • program[form(1i)]
  • program[form(2i)]
  • program[form(3i)]

ためしに/programs/newで表示されたtokenを入れてためしてみた。 ActionController::InvalidAuthenticityTokenですた。session idなんかと絡めてtokenチェックを入れているのだろうか・・?

skip_before_filter :verify_authenticity_token ,:only=>[:create]

上記メソッドを挿入してpostしたら成功した。

CSRFをすこし調べた。おそらくone time tokenの方法1でrailsの場合は対処しているのか?

modelをいじるタスクをつくる

やっぱ、http経由でCRUDをたたくのは面倒なので、taskをきってmodel経由でDBにinsertする。 Model系のメソッドがわからないので、consoleで調べる。

$ rails console

すべてのレコードを表示

> Program.all

find_byで条件付きレコード検索.

> data = Program.find_by(title: "僕らはみんな河合荘")

レコードを検索or追加する。(2つ目のコマンドでcreate or updateしてくれる)

 > data = Program.find_or_initialize_by(title: "僕らはみんな河合荘")
 > data.update_attributes(from: Date.new(2014,4,1))