Instagram の写真や動画を保存するブックマークレット

Instagram の写真や動画をサクッと保存したいなと思い、ブックマークレットを作ってみた。

対象とするのは、以下のような1つの投稿を表示するページ。

写真と動画を複数まとめてアップした投稿ページについては後述する。

写真の保存方法

ブラウザの開発者ツールで調べてみると、写真が投稿されているページの場合、div._jjzlb の配下に img#pImage_0 という要素があり、この src 属性値が表示されている画像 = フルサイズの画像ということが分かる。そこで、この src 属性値を location.href に設定すれば、画像を直接ブラウザで表示し、保存することができる。

// これで動く
javascript:(function() { location.href = document.getElementById('pImage_0').src; })();
javascript:(function(){location.href=document.getElementById('pImage_0').src})()
// スペースや書かなくても良いセミコロンを除去

で、最近のブラウザ (Firefox 54 で検証) だと、ネイティブで ES2015 の記法も解釈できるので、さらにブックマークレットを短く書ける。

javascript:(() => {location.href=document.getElementById('pImage_0').src})()
javascript:(()=>{location.href=document.getElementById('pImage_0').src})()
javascript:{location.href=document.getElementById('pImage_0').src}

無名関数はアロー関数にできる。さらに、引数を取らないアロー関数は単に {} で囲むだけで良いようだ。

…と、ここまで書いておいてアレだが、location.href なら直接叩けば良かった。

javascript:location.href=document.getElementById('pImage_0').src

とりあえずこれで動作する。

動画の保存方法

写真の場合は img#pImage_0 という要素があったが、動画のページの場合は、video._c8hkj という要素で動画を表示している。クラス名はランダム文字列なのかと思っていたが、どうもこれで固定のようだ。同じように location.href にして動画を直接表示してみる。

javascript:location.href=document.getElementsByClassName('_c8hkj')[0].src

動画の場合、リンクを作って右クリックから「リンク先を保存」した方が楽かな?と思い、リンクをページ左上に追加するようにしてみた。

javascript:((d)=>{d.body.innerHTML+=`<a href="${d.getElementsByClassName('_c8hkj')[0].src}" style="position:absolute;top:0">Video</a>`})(document)

ES2015 の記法である、アロー関数、テンプレートリテラル、プレースホルダー (テンプレートリテラル内の ${}) を使ってみたがちゃんと動いた。

複数の写真・動画を投稿したページの場合

複数の写真・動画をまとめて1つに投稿したページの場合、画像と動画はカルーセルで1つずつ表示するようになっていて、カルーセルを移動する度に表示欄の要素をまるごと取り替えている。よって、実際にその画像を表示するまでは画像の URL が分からない。手間だが、保存したい画像を表示してはブックマークレットを実行、次の画像を表示してはブックマークレットを実行、としないといけなさそう。

そして、画像の場合は img#pImage_0 という ID なのは1枚目だけで、2枚目以降は #pImage_1#pImage_2…と ID が変わっていく。つまり先程の #pImage_0 を特定するやり方では取得できない画像があるのだ。そこで、画像の場合に必ず img 要素を囲んでいる div._jjzlb から img 要素を特定するように書き換えた。つまり、複数投稿にも対応した画像保存のブックマークレットは以下のようになる。

javascript:location.href=d.getElementsByClassName('_jjzlb')[0].getElementsByTagName('img')[0].src

複数投稿にも対応・写真でも動画でもリンクを作るブックマークレット

そんなこんなで、写真の場合でも動画の場合でも、さらには複数投稿の場合でも対応している1つのブックマークレットを作ってみた。これを投稿ページで使うと、画面左上に「Image」もしくは「Video」のリンクを追加する。

javascript:((d,c)=>{i=d[c]('_jjzlb')[0],v=d[c]('_c8hkj')[0];if(!i&&!v)return;d.body.innerHTML+=`<a href="${(i?i.getElementsByTagName('img')[0]:v).src}" style="position:absolute;top:0">${i?'Image':'Video'}</a>`})(document,'getElementsByClassName')

長いので整形して説明する。

javascript:((d,c) => {
  i = d[c]('_jjzlb')[0],
  v = d[c]('_c8hkj')[0];
  if(!i && !v) return;
  d.body.innerHTML += `<a href="${(i ? i.getElementsByTagName('img')[0] : v).src}" style="position:absolute;top:0">${i ? 'Image' : 'Video'}</a>`
})(document, 'getElementsByClassName')
let href;
if(i) {
  href = i.getElementsByTagName('img')[0].src;
}
else {
  href = v.src;
}

以上。これでサクッと写真や動画が保存できる。