みなさんさようなら.
また,新たに痛いサービスを作りました.
声優を起点にしてアニメを見たい
俺は阿澄佳奈なんだけど,とりあえず阿澄佳奈が出演するアニメを見たい.
まぁ面白くないアニメもいっぱいあるし,そんなに継続してみているものは少ないけど,たとえゲストであろうと出るなら一度は見たい.
そんな思いに答えるべく,いかにして出演情報を探ろうかと日々奮闘している.
Wikipediaってすげーよ
もちろん季が変わるときには,新作アニメのまとめをいろんなところで出している. そういうところを見れば,出演声優はわかるんだけど,そうじゃない.
声優を軸にしてアニメを探したいんだ.
そういうので,一番早く,フォーマットが統一されていて,まぁまっとうな情報が上がってくるのは,やっぱりwikipediaだった.
wikipediaいいけど,まとめないとつらい
wikipediaはとても良いんだけど,問題もある.
- 複数声優を追う場合にはすべてのwikipediaページを毎回見に行かないと行けない
- どの項目が新規追加項目なのかわからん
最近だと,佐倉綾音のwikipediaページも見たいんだけど,そんなに1日になんページも巡回していられない.
そして,巡回して,「あれ?これって前見た時も書いてあったっけ?」となってしまう. ぶっちゃけ,そこまで詳細にwikipediaのページ内容を覚えてないので,新しく追加された出演情報がどれなのかわからない.
過去の作品でも追加で編集されたりするしね.
まぁ,wikipediaには差分を見られる機能もあるので,そこで見ればいいんだけど,それ人数分チェックするのか…….
というわけで全部まとめてみよう
と思って作りました. そんなに高機能ではありません.
基本的な機能
大きく以下の機能に分類されます.
- 声優の新規登録
- 差分チェックと更新
新規登録
好きな声優を新たに登録することができます. 阿澄佳奈だけじゃないよ!
追加できる声優は,wikipediaにて「日本の女性声優」「日本の男性声優」に所属している項目のみです. なんと今回は男性も許可している.
新規登録すると,裏でwikipediaのページをスクレイピングして所属カテゴリをチェックします.
所属していなかった場合には,残念ですが無言のまま登録されません.
まぁ非同期チェックにしているので,通知のしようもないのですが.
差分チェックと更新
これは登録完了している声優に対して,wikipediaの編集履歴をチェックし,前回チェック時との差分を計算させます.
まぁこのへんはいろいろ調節して複雑なAPIの叩き方をしているんですが,最終的には,一週間以内に更新があった項目のみを差分として保存しておく ようになってます. ちなみに更新チェック自体は日次で行います.
裏側の話
全部elixir(phoenix)です. 表側はそんなにリッチなUIいらないかと思って,単純にeexによるhtmlテンプレートをレンダリングしています.
差分のところだけちょっとめんどくさいので,wikipediaのAPI側で提供される差分をhtml化し,そのまま表示しています. cssとかはいじって色が付くようにしてある.
泣き所
elixirによる泣き所っていうのはあんまりない気がします.
言語といよりは仕様的な部分で,差分チェックのところはやはり相当な泣き所でした. 現状,これしか方法がなかった…….
当初はwikipediaのページコンテンツ自体をまるごと保存し,パースして構造解析して差分を出そうと思っていんたですが,難易度がかなり高い.
そもそもwikipediaのページって,htmlがあまり構造化されていなくて,ちゃんとツリー構造になっていないため,今見ている項目の親がどれなのかが辿れないんです. 横並びのものを再帰でたどって親を探すというトリッキーなことをしてみたんだけど,それをやるとどこが差分なのかが計算できなくなりました.
それなりに自由に編集できてしまうものなので,差分をちゃんと追うのは結構むずかしいんですよね…….
文字列やhtmlのまま差分を計算してみるというのもやってみたんですけど,構造の情報を落とさずに差分を取るのは難しい. 単純な文字列差分では,どの位置に追加・削除があったのかを追跡できなくなってしまうんです.
この辺もうちょっとgitを見習ったらいい感じに差分が出るのかもしれないけどなぁ…….
というわけで諦めて差分を提供してくれるAPIを使いました. APIで事足りるとは思うんだけど,これの場合,今度は差分行の親項目がどれなのかの情報が抜け落ちていしまいます.
本当は出演作品の項目だけがほしいんですが,結局これは今でも解決に至っていません.
嬉しいこと
elixirはパターンマッチで本領発揮してくるので,パースとかスクレイピングとか,めちゃくちゃ使いやすかったです. 個々のパースロジックを小さい関数に落としていくと,if文ほとんど使わずにほしい項目をパースできます.
同じ項目で構造が変わるような場合でも,関数の引数にマップがかけるので,構造ごとに呼び出す関数を変えたり出来ます.
これはすごく便利.
あとは,基本的にAPI叩くような処理はすべて非同期にしたかったのでOTPに乗っかりました. 速い.
このへんはelixirの得意分野ですね.
発端
1年にひとつくらいは痛いサービスを作らないと,落ち着かない気がしたので,ネタを探したんですが, たにさんからアイディアを募り,実装しました.
割と使える形にはなったので,公開.
要望はこちらに.
まぁこんな気持ち悪いサービス,日本語以外で表現できないだろうと思って,issueも全部日本語で行きます.