8月後半から10日間、ヨーロッパ旅行に行ってきました。
目的はもちろん、ARIAとごちうさ1の聖地巡礼です。
とはいえここはQiita。
旅行記ではなく技術に関する記事を書かねばなりません。
この記事では、長期間インターネッツが不便な世界に行く前に、
その間の不安を技術によって解決し、心置きなく心ぴょんぴょんした事例を紹介します。
よってこの記事は旅行記ではありません。2
不安とはなにか
さて、その不安というのは普段やってるある習慣に関係しています。
その習慣とは「niconicoでMMD艦これのタグの動画を見ること」です。
島風のMMDモデルが投稿されたあの日から現在まで、投稿された26000以上のMMD艦これ動画を、全て目を通(そうと)しています。
世界でもっとも美しい場所 サン・マルコ広場
MMDのステージとしても非常に高い人気があり実物を見てその再現度の高さを思い知った
日陰を求めてカフェの席が移動している様子はなかった
ただ、かなり人気のあるジャンルであり、日々の投稿数も非常に多いので、消化が間に合いません。
ここで問題になるのは「niconicoの検索は50ページ以上さかのぼれない」という糞仕様です。
もともと仕事中にずっと見ててギリギリ50ページ内に収まるようになんとか消化できるくらいのスピード感だったので、10日間海外に行くとなると確実に見れない動画が発生します。
作中にも登場するカッフェ・フローリアン
カフェラッテ発祥の店として有名
結構良いお値段するけど生演奏と共にカフェラッテを楽しむ時間というものは人生に必要なものである
3年続けた習慣をここで終わらせるのも忍びない。
なんとかして毎日の検索結果を保存しようということになりました。
しかし、ただ単純に検索結果を保存しても意味がありません。
再生リストに一括登録できなければならないのです。
死を避けよう
通常こういうことをするなら適当にコードを書いてcronに設定すれば事足ります。
しかし、10日もインターネッツが不自由な環境に行くとなると話は違ってきます。
何かあった時に対処できないのです。
おしえてください
この世に生きとし生けるものの
すべての生命に限りがあるのならば
プロセスは死にますか サーバは死にますか
ネットワークはどうですか データセンターもそうですか
おしえてください
自宅マシンでも、VPSでも、クラウドでも、コンピュータである以上必ず止まる可能性があります。
再起動することもままならないという状況では、止まってしまうこと自体を避けなければなりません。
やはりこういう場合に取りうる選択肢はAWS Lambda以外にありえません。
なので使う言語はJavaScriptに決定です。
検索の仕様を調べる
さて検索の仕様を調べていきましょう。
適当な動画ページでDevToolを開きNetworkタブを表示した状態でタグをクリックします。
画面が検索に切り替わり、Networkタブには大量の通信ログが流れているはずです。
その大量の通信の中から検索APIを叩いてるのを探しましょう。
http://riapi.nicovideo.jp/api/search/tag?sort=n&...
というまさにそのまんまなログが見つかるはずです。
さて次はこのリクエストがどこから呼ばれているか探しましょう。
DevToolのSourcesタブを見てみるとうんざりするほど大量のファイルを読み込んでいることがわかります。
しかしniconicoのリソース配布ドメインはres.nimg.jp
だと知っているので、一目散に目的のファイルを探すことができます。
それっぽいディレクトリを掘っていくと res.nimg.jp/js/watch/watch/watch.js
というファイルが見つかります。(このファイル名付けたやつアホなんじゃないの・・・)
先ほどのriapiというドメイン名でファイルを検索すると、this._watchConfig.riapiBaseURL
のような変数が大量に使われているのが発見できます。
さらにこのriapiBaseURL
で検索すると、その中のひとつに this.tagSearchAPILoader.setBaseURL(a.riapiBaseURL);
という1行があり、これがまさにタグ検索APIに関係するコードだと予想できます。
そしてsetBaseURLを使えば任意のドメインを検索対象にできるかもしれないと期待できそうです。
任意のドメインで検索できるのなら、再生リスト登録の部分は元からあるものが完全に動作するので面倒なことを考えなくても良くなります。
検索APIを叩こう
さてここまで判ったらあとは http://riapi.nicovideo.jp/api/search/tag
を叩いて保存しておけば楽勝!!! とはいきません。
この検索エンドポイントにはかなり厳しめのRate Limitが掛けられており、人力の遅さでページめくりしていても頻繁にRate Limitにぶち当たるわけで、機械的なアクセスはまず無理だと思ったほうがいいでしょう。
なのでniconicoにひっそり用意されているコンテンツ検索API V2を使います。
まず手始めに、この検索APIを叩くライブラリsugoi-searchを作ってnpmに公開しました。
おそらく2期最終話でアリア社長が転がしてた雪玉に押しつぶされた橋
Blu-ray Boxを見ながら写真を選定している際に気がついた
Serverlessを使おう
ヴェネツィアンガラス職人が技術流出しないように隔離された住む島 ムラーノ島
灯里ちゃんが初めて依頼された仕事はこのヴェネツィアンガラスを運ぶ仕事でした
AWS Lambdaを直接使うのはだいぶめんどくさいので、Serverlessを使います。
ServerlessはAWS Lambdaのフレームワークで、コードだけでなくイベントの設定、API Gatewayの設定、IAMの設定、zipにしてデプロイなどAWS Lambdaを使う上で必要なだいたいのことをやってくれます。1.0以降かなりすっきりして便利になりました。
インストールやチュートリアルは公式サイトを見ましょう。とても簡単です。
できあがったコードはGithubにあります。
handler.js
には、キッカーとなるregister
、検索した結果をs3に保存するfetch
、s3からデータを取ってきて本物の検索APIと同じ出力をする server
の3つのメソッドが登録されています。
serverless.yml
には、それぞれのメソッドがどのようなイベントから呼ばれるか設定されています。
これをコマンド一発でデプロイするとAWS Lambdaには3つの別々のFunctionが登録されますが、Serverlessを使えばそういう面倒なのは考えなくていいので楽です。
sls invoke -f register
を叩きしばらく待って、s3に検索結果のjsonがずらっと並んだら成功です。
ムラーノ島より更に遠くにあるレース職人の島 ブラーノ島 紛らわしい
カラフルな建物は隣の家と同じ色で塗ってはいけないというルールになっている
実際に使ってみる
watch.js
のthis.tagSearchAPILoader.setBaseURL
を検索し後ろにブレイクポイントを設定し、リロードします。
止まったところでsetBaseURL
にAPI GatewayのURLを登録します。
watch.js側でBaseURLに /tag?...
を付けるので、
'https://hogehoge.execute-api.us-east-1.amazonaws.com/dev/2016-10-01/'
のようなURLで指定すればよいでしょう。
適当なタグを選択したら保存された過去の検索結果が表示されるはずです。
これで無限に動画を積むことができるようになりました。
他人がコスト払ってくれる無限のストレージほど最高なものはありませんね。
![]()
火星猫がいないどころか この旅で見た猫はブラーノ島の猫と本島の雑貨屋の猫の2匹だけだった
ヨーロッパの他の都市でも一切見なかった 寂しい
おまけ
ひとつのタグを全部見るというのは多分変わったniconicoの使い方だと思います。
変な需要を満たすためいくつかChrome Extensionを公開しています。
橋が少ない代わりにトラゲットという渡し船があり2ユーロで乗れる
ウンディーネゴンドリエーレは屈強な男の仕事だ
現実は甘くない
- 検索のページ送りがめんどくさいので、テキストでページ数を指定して一気に飛べる niconico direct pagination (というか今作った)
- ブラウザのHistoryを見て、視聴済みの動画を除外して再生リストに突っ込む nico-play-all。
- 家と会社のChromeでHistoryを共有することができる sync-visited
![]()
ヴェネツィア内はカッレ(小道)と呼ばれる非常に細い道が張り巡らされている
ケット・シーの世界に迷い込んでしまうのも無理はない
特に夜のカッレは最高だ
まとめ
ネオヴェネツィアに住みたい
なお、アリスちゃんが好きです。
-
タイトルに反して紙面の都合でごちうさの聖地は紹介できなかったので、この旅の同行者であるラビットハウス社の@gomi_ningenが冬コミで出すごちうさ聖地巡礼本をお求めください。 ↩
-
旅行中撮ったすべての写真がGoogleDriveに上がっています。 ↩