Instagram|InstagramFeed

APIを使用せずInstagramのFeedが取得できるということでInstagramFeedというライブラリが紹介されていた。

少し触ってみたところうまく実装できなかったので色々と検証してみた。まだ把握できていないところは多いが、とりあえずの疑問点と、理解した内容についてメモ。

取得しているのはHTMLソース

現状のInstagramのウェブページはHTMLソースにフィードのJSONデータが含まれているようで、JSONが記述されている箇所の書式に基づいて切り出してJSONを取得している。

var data = xhr.responseText.split("window._sharedData = ")[1].split("<\/script>")[0];

上記コードでwindow._sharedData =から始まり<\/script>で終わる文字列を抽出し、

data = JSON.parse(data.substr(0, data.length - 1));

それをフィードのJSONとしてパースしていると思われる。

ソース中の特定の記述を文字列一致でひっかけて切り出して取得するというかなり限定的な手法なので少しでもソースの記述が変われば取得ができなくなる可能性があり、理解せずに使うのはなかなか危うい気がする。

しかしInstagramはちゃんとAPIつかっててもバンバン仕様変えてきて、ある日突然表示されなくなるなんてのは日常茶飯事なので、理解して使うならこのやり方は全然ありだと思う。

なぜ取得できる?

そもそもInstagramのウェブページはログインしないとページ自体見られないはずと認識していたので、 HTMLソースを取得しているにしてもそれ自体なぜ取得が可能なのか疑問を持ちつつ改めて確認したところ確かに取得できた。

しかし何回か試していたら取得できないようになり、コンソールで確認したところ以下のようなエラーが出ていた。

InstagramFeed: It looks like YOUR network has been temporary banned because of too many requests. See https://github.com/jsanahuja/jquery.instagramFeed/issues/25 4
リクエストが多すぎるため、ネットワークが一時的に禁止されているようです。

おそらく未ログイン状態での単位時間あたりのリクエスト数に制限があるようなイメージなのではないかと思われる。

整理すると

  • 未ログイン状態でもURL直打ちで各ページの閲覧は可能
  • その回数にはネットワーク単位で制限がかかる
  • リンクを踏んだりスクロールしたりするとログインを促される

ということのような気がする。

ちなみに制限は時間の経過により解消されるようで、しばらく経てばまた取得できるようになるが、数回リロード(一回で6リクエスト×2〜3リロード?)したらすぐに取得できなくなる。

はっきりした値についてはよくわからないが10〜20リクエストくらい?いずれにしろ体感的にはちょっと触るとすぐ見えなくなる感じなのでこのライブラリ自体あまり実用的ではないかもしれない。

ただし制限はクライアントのネットワーク単位なので、例えば自分のウェブページにこれを置いた場合に、同じ閲覧者(同じネットワーク)から何度も閲覧しないかぎり大丈夫…なのかもしれない。

また、APIを使ったとしてもリクエストの上限はたしか200リクエスト/時間だったと思うので、それほど大きな違いでもないかもしれない。

access-control-allow-originは?

異なるドメイン間でのhttpリクエストにはCORSの制限がかかるはずで、そのあたりどうなってるのかは未検証。

Instagramはすぐに制限がかかるのでまだその点については検証できず、自分のサーバに向けてこのライブラリでソースの取得を試みたところローカルでもサーバにあげてもいずれも取得自体がCORS制限によりエラーとなる。

自分のサーバについてはaccess-control-allow-origin'*'としたら動くのが確認できたので、普通に動かしたらやはり制限がかかるはず。ではなぜこのライブラリはソースを取得できているのか。

制限が解除されたらInstagramのサーバへのアクセスはどうなっているのか検証したい。