以下、スクリプトの解説が中心です。Windows で手軽に使いたい方は berryjack/win32 をダウンロードしてください。
数年前、知人より「Twitterの特定アカウントで公開されている画像ファイルを一括ダウンロードするスクリプトがないかな」と相談を受けて、Perl でNet::Twitter::Lite
を使ってがりがりコーディングしました。そして、今年になってから Ruby を使う機会が増えたため、そのコードを Ruby で書き直してみました。
機能に対した差はなく、いずれも Twitter API 経由でタイムラインを取得していき、オブジェクト化されたツイートを舐めていくだけのものでしたが、画像ファイルのダウンロードに加え、発言やプロフィール情報の保存などなどをやっているうちにコードが増えてしまって、Perl で 343 行、書き直した Ruby でも 203 行と少し行数が増えてしまいました。
速度や行数に厳しい要求じゃないので、別にまあ良いのですが、Perl で書いていた頃から Twitter API がなんだか大掛かりすぎる感がありました。コンシューマキーやらアクセストークンやら、タイムラインの遡って取得していく方法や…、とタイムラインを取ってくるだけでも色々なバックエンドを知りつつ、リファレンスと睨めっこしなければなりません。
そんな時 Twitter をWWWブラウザで眺めていると、メディアの取得は JavaScript を使って非同期的に要求・表示していることに気付きました。いや、それ自体は一応前から知ってたんですが、昨今のダイナミックに動きまくる大手ウェブサービスの暗号みたいなソースを見るのにちょっと億劫になっていて、挙動と中でやっている事の予想はついていたものの、まともに調べたことがありませんでした。タイムライン取得はどのサイトを見ても Twitter API 経由が定石のようですし…。
Twitter 側が提示している正規のアクセス方法はあくまでも Twitter API 経由でのアクセスですが、使わせてようとしているわりには使いづらかったり、何かと制限がついてきたりとなかなか良いイメージがありません。 その Twitter API も大掛かりすぎて、ちょっとだけ食傷気味になっていましたので、HTTPリクエストと返ってくるJSON情報だけでなんとかなるはずだと思って、シェルスクリプトで書いてみました。
Twitter をブラウザでアクセスした際に表示される「画像 / 動画」ページは、下にスクロールしていくと、非同期的にサーバにクエリを投げて画像 URL を含む JSON データを取得しています。Firefox の 開発ツールを開いて JavaScript でクエリーを投げている URL を検知すると、
https://twitter.com/i/profiles/show/[Twitterアカウント名]/media_timeline[パラメータ]
にアクセスしていることが分かります。
ここから、まずパラメータを省略してアクセスしてみると最新のツイートから遡って20件前後のツイートを取得しているようでした。さらにこの取得したツイートのIDを用いて、さらに古いツイートを取得するためのパラメータを生成すれば良さそうです。
つまり、最初のアクセスはパラメータなし。2回目以降は、直前のアクセスで取得した情報を基に URL を生成、そこにアクセス。というパターンです。
いくつかパラメータを投げることができるみたいですが、最低限必要なパラメータはcontextual_tweet_id
とmax_id
のようです。前者は、直前に取得した tweet ID の一番若い番号、後者はその番号をマイナス1した値みたいです。Tweet ID は全世界的に一意である整数値番号で、Perl ではMath::BigInt
を使わないと扱えないくらい大きい桁数になっています。
そのことを踏まえ、適当にパターンマッチさせて書いてやると、次のような感じになりました。
初回アクセス時にはparam
が空になって、最新のツイートを取得します。そこから、まずは画像ファイルの情報を列挙、その後に次のクエリーを投げるためのパラメータ検知、生成しています。最も古いツイートまで到達したりして情報が取得できなかったら抜けます。
拍子抜けしてしまうほど簡単でした。14行ておま。Perl や Ruby の Twitter API なモジュール、Gem を使ってやっていたのが虚しいくらいです。もちろん、これ以外にもいろいろな機能を実装していた上に、Unicode なツイート内容などを扱い始めるとシェルスクリプトでは都合が悪い(勝手が悪い)部分も多々存在します。
絶対的優位と言えそうな点は、media_timeline に対してクエリーを投げているので、画像ファイルのダウンロードが目的であれば不必要なその他のツイートは取得せずに、ピンポイントでダウンロードできる点じゃないでしょうか。(そっちの方が Twitter のサーバに対しても優しいかも。1万ツイートしていて画像ファイルが100個しかないアカウントに対して全ツイートを取得するのは非効率的すぎますし、そもそも API 制限で全ては取得できませんし…。Twitter API もメディアファイルがついているものだけを取得できないのかなぁ)
ということで、いくつかオプションを追加して叩けば落ちてくるシェルスクリプト「berryjack」を GitHub に置いておきました。何百番煎じかもしれませんが、興味がある方は見てみてください。
ちなみに、一度だけダウンロードしたい方は、次のようなソフトもあります。
なんと素晴らしいアプリですか><
これはハッシュタグの一覧ダウンロードとかは出来ないでしょうか?
そこに集まった画像を集めたかったのですが・・・
あとはダウンロードの際はオリジナルサイズでのダウンロードになるのでしょうか?
[…] blog: Twitterの画像を一括ダウンロードするシェルスクリプト「berryjack」を書いた… […]