Instagram に投稿された画像・動画をダウンロードする CLI ツール「igsv」を作った
Twitter から画像・動画をダウンロードする @neos21/twsv
という npm パッケージを作ったが、それの Instagram 版を作った。その名も igsv。「InstaGram SaVer」の略のつもり。
目次
先に作ったツールの紹介
igsv は Node.js 製の CLI ツール。npm でインストールできる。パッケージ名としては @neos21/igsv
。
$ npm install -g @neos21/igsv
グローバルインストールしたら igsv
コマンドが使えるようになっているので、以下のように Instagram の URL を引数で指定してやる。
# 指定の投稿に紐付く画像・動画を取得する
$ igsv https://www.instagram.com/p/XXXXXXXXXXX/
デフォルトの保存先は、コマンドを実行した時のカレントディレクトリに igsv-downloads/
ディレクトリを作り、その下にファイルを保存する。
保存先ディレクトリを変更する場合は、環境変数か第2引数で指定できる。両方指定されている場合は第2引数が優先される。
# 環境変数で指定して実行
$ export IGSV_SAVE_DIRECTORY='/home/downloads'
$ igsv https://www.instagram.com/p/XXXXXXXXXXX/
# 第2引数で指定して実行
$ igsv https://www.instagram.com/p/XXXXXXXXXXX/ '/home/downloads'
画像はサイズが一番大きいモノを選んで取得している。動画は IGTV でも通常の動画と同様にダウンロードできる。
以降ツールを作るまでの苦労話
自分が Instagram から画像や動画をダウンロードする時は、以下のウェブアプリを使っていた。
UI がイマイチで、複数枚の画像を DL するのが大変だったので、twsv
同様 CLI ツールとして作ることにした。
Instagram の API は登録が面倒で避けたかったので、スクレイピングでなんとかならないか調べてみた。投稿ページを request-promise
で取得し、cheerio
で jQuery ライクなオブジェクトに変換し、ページ内を調べてみた。すると、以下のような script
要素が見つかった。
window._sharedData = { 【大量に連想配列…】 };
この window._sharedData
という変数に代入されている連想配列 (≒ JSON オブジェクト) を紐解いていくと、投稿ページの全データが含まれていることが分かった。そこで、この script
要素内から連想配列部分だけを抜き出し、JSON.parse()
して中を辿っていくことにした。
JSON データの中の、.entry_data.PostPage[0].graphql.shortcode_media
配下に、投稿した画像や動画のデータがある。配下に edge_sidecar_to_children.edges
プロパティがあれば複数枚の投稿、なければ単一の画像や動画の投稿だ。
単一の画像や動画の場合は、.shortcode_media.is_video
プロパティを見ることで、投稿が画像なのか動画なのかが分かる。is_video
が true
なら動画なので、同階層の .video_url
を取得すれば良い。
画像の場合は、.display_resources
プロパティが配列になっていて、様々な解像度のデータが入っている。.config_width
・.config_height
プロパティがピクセルサイズなので、これらを見て、最大解像度の画像を手に入れるようにした。
複数枚投稿の場合は、.edges
配下が配列になっているだけで、各要素からの画像・動画の抜き出し方は単独の場合と同じ。
JSON の構成が難解だったが、とりあえず拾えたので、あとはダウンロードするのみ。保存先ディレクトリのチェックや保存処理などは、@neos21/twsv
とほぼ同じなので割愛。
以上
ページをスクレイピングしているだけなので、非公開アカウントなどは拾えないしユーザのログイン状況などを認識できないが、自分の用途ではコレで十分かな。