常駐監視型 Twitter メディアダウンローダー「berryjack/win32」

bjw32

Twitter の常駐監視型メディアダウンローダー berryjack の Windows 移植版を作成しました。品質無保証の人柱版として公開します。

概要

監視対象となるアカウントを定期的に巡回して、メディアファイル(画像、動画ファイル)が投稿されていたら自動的にダウンロードしてくれます。投稿されたメディアファイルを一括ダウンロードする点では、他の Twitter ダウンローダーと変わりがありませんが、起動しておくだけで複数のアカウントを定期的にチェックしてくれるところが大きな特徴です。

また、HTTP 経由でメディアタイムラインのみを取得するため、ツイート全文を取得する Twitter API 経由でのアクセスよりも少ないトラフィックで済み、直近 3200 ツイートしか取得できないという制限がないという特徴もあります。

各国の報道機関や犯罪組織の声明など発信される情報が注視されるようなアカウントや、イベントなどで期間限定のアカウントなどを監視するのに最適です。

ダウンロード

使い方

  1. 「list.txt」に監視対象のアカウントを1行に1つずつ書いて保存します。たとえば、アカウント「@AbeShinzo」「@tenkijp」「@jaxa_jp」「@pamyurin」の4つのアカウントを監視したい場合は、下記のように書きます。「@」マークはあってもなくても良いです。

bjw32_list

  1. バッチファイル「start-bjw.bat」をダブルクリックして実行します。コマンドプロンプトが起動して、ダウンロードが開始されます。ダウンロードした画像と動画ファイルは、download フォルダ内にアカウント毎に保存されます。

  2. 終了するには、コマンドプロンプトを閉じます。閉じるまで、ずっと監視&ダウンロードが実行されます。

注意事項・免責など

このバージョンは人柱版です。自己責任でお使いください。 このソフトを利用して発生したいかなる不具合、不都合も作者は責任を負うことができません。 また、Twitter やその他のサーバーに負荷をかけるような設定、運用は絶対に行なわないでください

ライセンス情報等は、配布しているアーカイブファイル内に同梱しています。

OpenCASCADE 6.9.0 を Debian でビルド

先月の12日にリリースされた Open CASCADE の 6.9.0 をビルドしました。公式のロードマップでは 6.x 系列は 6.8 が最後で、次は 7.0 になるとの話だったはずですが、何だかんだで 6.9 がリリースされた模様

v6.9 のリリースノートを読んではいましたが、ここのところ忙しくて対応ができなかったので出遅れてしまいました。

ここ数バージョンは、ビルドの仕方マニュアルがいろいろと整備されてきて、時代に合わせてなのか、ビルド環境ごとの Markdown なドキュメントも付属しています。このブログで改めて紹介する必要性もあまりなくなってきました。詳しい内容は公式ドキュメントに任せるとして、要点だけかい摘まんで紹介したいと思います。

公式ドキュメンテーション

v6.9.0 の内容は次のドキュメントで網羅されています。

v6.9.0 のリファレンスマニュアルは、ソースコード tar ボールや Windows インストーラー内に同梱されています。最も最新バージョン(開発版)のリファレンスマニュアルであればこちらで参照できます。

v6.9.0 リリースの要点

モデリング・アルゴリズム

ファジー ブール演算

これまでのバージョンでは、ソリッドモデル等で行うブール演算時に対象と対象がちょうど同一の位置にある面や線を共有して存在していた場合、意図した演算結果にならない事が多くありました。意図した結果にならない場合はまだ良かったんですが、いつまで経っても計算が帰ってこない、または例外を吐いてお亡くなりになるケースもありました。この点が改善されているようです。

複数の引数を取るブール演算

これまでのブール演算では TopoDS_Shape を二つ用いて、Fuse, Common, Cut 等の演算を実行していました。あんまり詳しく見てませんが、同時に複数の TopoDS_Shape を演算させることができるようになるようです。これまで数回の処理で書いていたものが一度にできるわけですが、複数のソリッド群の一つに reverse させたソリッドを混ぜて Common に投げて、結果的にその部分だけは Cut させる動作にするなど、より「ブーリアン」っぽい演算としてコーディングできるようになりそうです。

ビジュアライゼーション

選択処理を再設計して、より良いパフォーマンスに

OCCT のビジュアライゼーションは長いことほったらかしになっていた様子で、ちょっと貧弱でした。これは、あくまでも OCCT は三次元幾何演算とトポロジックな形状の演算がメインであり、代替ライブラリーを用いて解決できるビジュアライゼーションは二の次でも大丈夫!という背景もあります。 実際、OCCT を採用している有名なオープンソース三次元 CAD ソフトの FreeCAD は、OCCT 提供のビジュアライゼーションを使用せずに別のライブラリで三次元ビューを提供しています。 ただ、ここ数バージョンでは、前述の幾何を扱うことろがだいぶ安定してきたのか、二の次だったビジュライゼーションが次々と強化されており、パフォーマンスも改善しています。まだ実験的な印象ではあるものの、レイトレーシングレンダリングの採用、GLSLシェーダが読み込めるようになっていることなど、単なる計算ライブラリから本当に「CAD」として必要な機能の強化が見てとれます。 後述する VTK の採用も注目すべき点です。

OpenGL ES 2.0 互換

ビジュアライゼーションの改良の特記すべきもう一つの点は、iOS, Android などのモバイル端末への対応です。OpenGL ES はモバイル端末向けの OpenGL のサブセットです。OCCT の幾何ライブラリの部分は、早い段階から Android にも移植されて動作していましたが、ビジュアライゼーションはそのままではビルドできませんでした。ES 互換となることにより、これらの環境へもシームレスな移植が可能となりそうです。

シェイプを表示する際の三角形メッシュ化の制御

コンテキストにシェイプを追加する際、これまでは必要に応じて自動的にシェイプの描画データである三角形メッシュを内部で生成していました。これを外側から無効にするオプションが導入されたようです。 形状の変形はなく、大量のシェイプを回転させるだけでも再三角形メッシュ化が走って表示速度が落ちていましたが、それらを動的に制御することができそうです。(※回転も行列演算している意味では変形(トランスフォーメーション)ですが、自由曲面の式まで遡って、形状の三角形メッシュを再構築する必要すらない場合も往々にあります)

その他

Intel TBB ライブラリを使わない並列処理のサポート

こちらも詳しく追っていませんが、自前で並列処理を行う環境が整いつつあるようです。

サンプルに AndroidQt, JniViewer for Android が追加

Android 環境のサンプルも充実してきました。

JniViewer

JniViewer for Android

AndroidQt

GUI は QML を使って書いてあるみたいです。本当に WPF/.NET Framework なんて使ってる場合じゃないです。

AndroidQt

その他のサンプルに、Qtデスクトップ版、MFC、C# があります。C# では WPF ベースのものと System.Windows.Forms 版があり、今のご時世でいうと半ばどうでもいいですが、Direct3D デモも追加されています。

v6.9.0 の全体的な感想

幾何演算部分の改良は喜ばしい限りで、ビジュアライゼーションの強化も頑張ってほしいところです。ようやくモバイル端末のサポートも視野に入れてきているようですが、個人的にはいっそのこと三次元ビューアは WebGL 環境へシフトしていくのもアリなんじゃないかなぁと考えています。OCCT をサーバ上で並列処理させて、クライアントの WWW ブラウザ上で表現する…素晴しいじゃないですか。最近は NW.js (Node.js + Webkit)のようなツールキットも存在しますので、ライトウェイトなビューアーからワークステーションで動かす CAD まで環境に依存しないビジュアライゼーション機能になっていけばいいな、と思っています。え?お前が Context や Viewer, View を JavaScript で再実装しろって?それが仕事になればいいんだけどなぁ…;)

v.6.9.0 のビルド

ビルド方法は次のドキュメントに詳しく書いてあります。

なお、このドキュメントはソースコード tar ボールを解凍して生成されるdoxディレクトリ以下に markdown ファイルとして収録されています。(逆に言うと、上記の HTML はそれらのファイルを doxygen にかけたものと思います。)

ビルド環境

OCCT のビルド環境もかなり充実してきており、以前のようにチューニングしながらあれやこれやする必要もほとんどなくなりました。公式サポートしているのは次の環境です。

  • Automake
  • CMake
  • CMake + ADT (Android SDK)
  • Code::Blocks (Mac OSX)
  • Xcode (Mac OSX)
  • Microsoft Visual C++ (Windows)

また、パフォーマンスチューニングレポートでは Linux 版の Clang/LLVM でも検証されているようです。

今回は一番馴染みがある Automake でいきたいと思います。

ビルド手順

作業ディレクトリに入り、tar ボールを落としてきます。ソースコードは前バージョンまではユーザー登録&ログインしないとアクセスできなかった気がしますが、今回から下記の URL で落とせるようです。なお、git での clone は登録が必須です。

cd /tmp
wget http://files.opencascade.com/OCCT/OCC_6.9.0_release/opencascade-6.9.0.tgz

解凍してディレクトリにはいります。

tar zxvf opencascade-6.9.0.tgz
cd opencascade-6.9.0/

configue をビルドして configure します。オプションについては後述します。

./build_configure
./configure -prefix=/opt/occ690 \
-with-vtk-include=/usr/include/vtk-6.1 \
-with-vtk-library=/usr/lib/i386-linux-gnu/

make して install します。

sudo make -j2 install

とりあえずこれだけです。便利。

貧弱な自宅サーバ(Debian GNU/Linux、32bit環境、Intel Atom)では、make で

real    183m57.121s
user    336m24.168s
sys     16m36.896s

となりました。

configue オプション

-prefix=

最終的にビルドしたファイルをインストールする場所です。自分は /opt/occ690 に指定しています。

-with--include=, -with--library=

ヘッダのインクルードパスとライブラリパスを追記しています。VTK が見えてなかったようなので、明示的に指定しました。

その他のオプションはこちらを参考にしてください。

ビルド時のテクニック

configure では、ビルドする環境にインストールされているライブラリの有無によって OCCT のモジュールとよばれるライブラリ群の Makefile を生成します。

モジュール > ツールキット > パッケージ > クラスや列挙型など

OCCT は上記のように階層構造を持ったライブラリです。ツールキットの部分が共有ライブラリファイル(.so)に当たります。Windows ではダイナミックリンクライブラリ(.dll)になります。モジュールはそれらをまとめて用途別にグループにしたものだと思ってください。

モジュールには次のものがあります。

  • FoundationClasses … 共通関数などを提供
  • ModelingData … 幾何形状をデータとして表現する機能
  • ModelingAlgorithms … 幾何形状を構築する機能
  • Visualization … 幾何形状を画面に描画する機能
  • ApplicationFramework … OCCT を使ったアプリのための有用な機能
  • DataExchange … 幾何データファイルのサポート(IGES,STEP,STLなど)
  • Draw … テスト環境

ざっくりと説明すると上に行くほど依存関係が少なくてすみます。詳細な依存関係はリファレンスマニュアルの図のとおりです。

occt modules

さらに、個々のモジュール内のツールキットの中で依存関係があります。なお、IGES などのデータファイルをサポートするには、GUI が必要がない場合でもビジュアライゼーションやアプリケーションフレームワークの各ツールキットを全て背負い込まなければならないかというと、実はそうではありません。具体的にはモジュール同士の依存関係の奥にはツールキット同士の依存関係があり、それを満たしていればこの図の限りではありません。今のところ、モジュールを越えた関係図はないので、リファレンスマニュアルを見て何が必要なのかを調べる必要があります。

さて、ビジュアライゼーション以下のモジュールは、さらに多くの別の人(サードパーティ)が開発しているグラフィック系のライブラリに依存しています。

そのため、グラフィック系のライブラリがない環境で configue すると、ビジュアライゼーション以下のモジュールが無効になった Makefile が生成されます。

configure の出力に各モジュール名と Yes/No といった表示が出力されるので、それでモジュールが有効になっているか無効になっているか、無効の場合はどのライブラリが足りていないのかを表示してくれます。以下に私の環境の configure 出力を示します。

3rdparty mandatory products       
---------------------------------
freetype      : yes 
tcltk         : yes 

3rdparty optional products       
---------------------------------
gl2ps         : no (--with-gl2ps=DIR option was not defined)
freeimage     : no (--with-freeimage=DIR option was not defined)
tbb includes  : no (--with-tbb-include=DIR option was not defined)
tbb libraries : no (--with-tbb-library=DIR option was not defined)
opencl        : no 
qt            : no (--with-qt=DIR option was not defined)
vtk           : yes 

Component                   Build
--------------------------  -----
FoundationClasses           yes 
ModelingData                yes 
ModelingAlgorithms          yes 
Visualization               yes 
ApplicationFramework        yes 
DataExchange                yes 
Draw                        yes 

「3rdparty mandatory products」は必須ライブラリ、「optional」は指定があったら使うライブラリです。必要なライブラリとそのバージョンは、以下にまとめてあります。

Open CASCADE Technology: Overview

Debian GNU/Linux jessie 32bit 版では、すべてのサードパーティ・ライブラリを標準リポジトリからインストールすることができました。(ソースコードの取得とビルドは不要)

また、テスト環境である Draw や Qt のサンプルプロジェクトをビルドする必要がなければ、 Tcl/Tk や Qt のインストールは必要ありません。 上記の「mondatory products」に Tcl/Tk が入っているのは、すべてのモジュールをビルドする際に必須、という意味だと思います。

siren をビルド

OCCT を使った siren というソフトを作ってます。OCCT が提供する三次元幾何演算機能を Ruby で簡単に記述することができ、ちょっとした演算なら手軽にすることができます。

上記でビルドした OCCT 6.9.0 を使って siren の最新リビジョン(OCCT6.8.0ベースで記述)をビルドし直してみると、あっけなくビルドが通りました。クラス名が変更されたり、siren で使っている機能が変更されることがなかったようです。

ひとまず安心しました。


ツイキャス録画スクリプト

リアルタイム動画配信サービス「ツイキャス」の録画をしてくれるシェルスクリプトを書いてみました。…と言っても、ffmpeg の入力ソースに食わせるだけですので、スクリプトというよりは例によって自分の覚え書きのようなものになっています。


使い方は、実行権限を付与して

./twitcast.sh ツイキャスアカウント名

という具合です。配信中であれば ffmpeg による録画が開始されます。

なお、パスワード付き配信は試していませんが未対応だと思います。

ufwを使ったファイアウォール設定

ufw コマンドは、複雑な設定を要する iptables を直接操作することなく、簡単な操作だけでファイアウォールの設定を行うことができる便利なコマンドです。 以下、簡単な操作のはずなのに、設定するたびに忘れる私のダメな脳味噌のための備忘録です。

  • ポートを許可する、制限する

    ufw allow 1234
    ufw allow 1234/TCP
    ufw denny 1234
    
  • ファイアウォールを有効、無効にする

    ufw enable
    ufw disable
    
  • 現在の設定状況を調べる

    ufw status
    

※ ちなみに、設定方法から設定例まで man ページに丁寧に書いてあります。

MD5ハッシュ値をURLセーフな文字列に変換

大量に保存した画像ファイルなどの重複潰しも兼ねて、ファイル名を MD5 ハッシュ値にリネームして保存しています。

dyama/hashmv · GitHub

まったく同一のファイルであれば、ハッシュ値が同一になりますので、ファイル名が同一になります。上のスクリプト「hashmv」ではリネーム時に同一ファイルを上書きしますので、結果、重複ファイルを除去することができます。

実行イメージ

    $ hashmv foobar.jpg
    foobar.jpg -> ./d41d8cd98f00b204e9800998ecf8427e.jpg    

hashmv では、32 文字のハッシュ値のそのままファイル名に変換しているので、ちょっと長いなと思いました。md5sum のオプションを見ても、もうちょっとコンパクトな出力を得るオプションが見当たらなかったので、車輪の再発明上等でシェルスクリプトを書いてみました。

    #!bash
    function compress_hash()
    {
      echo $2 | sed \
        -e 's/aaa*/A/g' \
        -e 's/abb*/B/g' \
        -e 's/acc*/C/g' \
        -e 's/add*/D/g' \
        -e 's/aee*/E/g' \
        -e 's/aff*/F/g' \
        -e 's/baa*/G/g' -e 's/ecc*/g/g' \
        -e 's/bbb*/H/g' -e 's/edd*/h/g' \
        -e 's/bcc*/I/g' -e 's/eee*/i/g' \
        -e 's/bdd*/J/g' -e 's/eff*/j/g' \
        -e 's/bee*/K/g' -e 's/faa*/k/g' \
        -e 's/bff*/L/g' -e 's/fbb*/l/g' \
        -e 's/caa*/N/g' -e 's/fcc*/n/g' \
        -e 's/cbb*/M/g' -e 's/fdd*/m/g' \
        -e 's/ccc*/O/g' -e 's/fee*/o/g' \
        -e 's/cdd*/P/g' -e 's/fff*/p/g' \
        -e 's/cee*/Q/g' -e 's/0[0-9][0-9]*/q/g' \
        -e 's/cff*/R/g' -e 's/1[0-9][0-9]*/r/g' \
        -e 's/daa*/S/g' -e 's/2[0-9][0-9]*/s/g' \
        -e 's/dbb*/T/g' -e 's/3[0-9][0-9]*/t/g' \
        -e 's/dcc*/U/g' -e 's/4[0-9][0-9]*/u/g' \
        -e 's/ddd*/V/g' -e 's/5[0-9][0-9]*/v/g' \
        -e 's/dee*/W/g' -e 's/6[0-9][0-9]*/w/g' \
        -e 's/dff*/X/g' -e 's/7[0-9][0-9]*/x/g' \
        -e 's/eaa*/Y/g' -e 's/8[0-9][0-9]*/y/g' \
        -e 's/ebb*/Z/g' -e 's/9[0-9][0-9]*/z/g' \
        | cut -c -$1
    }

    for hashstr in $@
    do
      compress_hash 6 $hashstr
    done

元のハッシュ値は [a-f0-9] の文字集合ですが、パターンマッチングによって [a-fA-Z0-9] の文字集合に置き替え、桁数を落としています。見たとおり、ある一定のパターンの繰り返しを単一文字に置き換えているので、上のスクリプトでは元ハッシュ値に対する可逆性はありません。さらに、破壊的に圧縮したハッシュ値をcut で任意の桁数に切り落としています。

次に、評価用のコードを示します。

    while :
    do
      hash=$(date +%s | md5sum | cut -f 1 -d ' ')
      compress_hash 6 $hash
      sleep 1
    done

1秒おきに、UNIX タイム文字列を変換して印字する評価コードです。実行すると

    dFc7wa
    vqA5cx
    rc1a1d
    ucufyV
    1d2b8c
    qm9Le4
    6sqc5c
    atavIr
    7bqc5r
    3auf7b
    ....

のように、6 桁の圧縮されたハッシュ値が出てきます。

短縮 URL などの用途に代表されるように、URL セーフな文字列で桁数を抑えつつもある程度のパターン数は稼ぎたい場合に有効かもしれません。なお、元のハッシュ値は基数が a-z0-f の 16 ですが、これは a-zA-Z0-9 の 62 となる為、6 桁でも約 568 億パターンも稼ぐことが可能です。

    # 62^10 = 839299365868340224 (約84京パターン)
    # 62^9  =  13537086546263552 (約1.3京パターン)
    # 62^8  =    218340105584896 (約218兆パターン)
    # 62^7  =      3521614606208 (約3.5兆パターン)
    # 62^6  =        56800235584 (約568億パターン)
    # 62^5  =          916132832 (約9億パターン)
    # 62^4  =           14776336 (約1477万パターン)

6 桁なら長くなく、覚えられない長さではないし、1/568億の確率で衝突するくらいの強さは持ってますので、ファイル管理には十分だと思いました。

なお、a-zA-Z0-9 の文字集合に加えて記号 /+= を許可する場合は、上のようなスクリプトではなくハッシュ値をそのまま base64 エンコードした方が手っ取り早いです。

USB フロッピーディスクドライブで FD をフォーマットする

フロッピーディスクを整理しようと Amazon で 1680 円だった USB フロッピーディスクドライブを買いました。一応 Windows 9x・古い MacOS 向けのインストール CD が付属していましたが、Linux Mint は挿すだけで認識しました。便利。

nemo にアイコンが表示され、そこからクリックや右クリックメニューを使ってマウントをすることができるけど、右クリックメニューの「フォーマット」は USB フラッシュメモリー向けのダイアログが表示されるので使えません。

ということでマニュアルでフォーマットします。

  1. dmesg でフロッピーディスクドライブのデバイスファイルを確認する。本例では、/def/sdf とする。
  2. root で fdformat /dev/sdf すると Invalid argument と怒られるので、mtools の mformat を使う。/etc/mtools.conf を次のように編集。

    - drive a: file="/dev/fd0" exclusive
    + drive a: file="/dev/sdf" exclusive        
    
  3. mformat a: && mkfs -t msdos -I /dev/sdf する。

  4. マウントしてみて読み書きできたら成功。

もちろん、マウント済みの場合は一旦アンマウントしてから実行します。

手元の FD は論理的に壊れているものはフォーマット。物理的に壊れているものは処分しました。 ちゃんと読み書きできたものの中に 1996年の Mac 版 NetScape インストーラの FD などがありました。

FD ドライブを使うの自体、10年ぶりくらいです。読み書きの音が懐しいですね。

Linux で 64GB SDXC カードを使う

今使っているラップトップは、SONY VAIO Z の BTO で SSD ストレージなのですが、予算をケチって 128 GB にしています。というのも、ストレージはどんどん安くなっていくので「必要になったら後から足せばいいか」と考えていたからです。

SD カードも SDHC カード、SDXC カードと進化しつつもどんどん安くなっていて、64 GB の SDXC カードが3200円〜3800円程度で買えるようになってきました。

そろそろ容量を確保しておきたくなったので、Amazon で 64 GB SDXC カードを購入。 Linux で SDXC カードを使う際の注意事項が、調べてみてもあまり情報がなかったので購入時は少し不安でした。

参考までにいくつかの側面からポイントを書いておきます。(もちろん保証はできませんのであしからず…)

物理的な問題

SDHC カードを想定していたハードウェアで使えるか?ということです。/dev/mmc* (本体に搭載されたSDカードリーダー)や /dev/sd* (USB SDカードリーダー)として認識し、今のところちゃんと使えているようです。

パーティションテーブル的な問題

問題なく、普通のストレージと同じようにパーティションが切れます。GParted でも確認済み。

ファイルシステム的な問題

インターネット上の SDXC カードに関する記事は exFAT とペアで掲載されていますが、ファイルシステムを exFAT しか許していないわけではなく、何でもいいようです。普通に mkfs コマンドでファイルシステムを作れます。うちでは ext4 を使っています。もちろん、SDXC カード対応と謳ったデジカメなどの類は exFAT しか読み書きできないはずです。なお、うちの Linux Mint では、購入直後にフォーマットされていたであろう exFAT な SDXC カードをマウントできませんでした。

暗号化的な問題

cryptsetup や LUKS で魔法をかけることもできました。

# cryptsetup luksFormat /dev/mmcblk0p1 

WARNING!
========
This will overwrite data on /dev/mmcblk0p1 irrevocably.

Are you sure? (Type uppercase yes): YES
Enter passphrase: 
Verify passphrase: 
# cryptsetup luksOpen /dev/mmcblk0p1 sdxc
Enter passphrase for /dev/mmcblk0p1: 
# ls /dev/mapper/
control  sdxc
# mkfs.ext4 /dev/mapper/sdxc
# 略
# cryptsetup luksClose sdxc

SDXC カードを用いて Windows コンピュータやデジタル家電とデータをやりとりするには、Linux 側での exFAT サポートが必要になってくると思います。(「linux exfat」で検索するとたくさん情報が出てくるので可能なはずです。)しかし、単に Linux だけで完結する小さな拡張ストレージという用途では、普通に使えるようです。

Twitterの画像を一括ダウンロードするシェルスクリプト「berryjack」を書いた。

以下、スクリプトの解説が中心です。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_idmax_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 に置いておきました。何百番煎じかもしれませんが、興味がある方は見てみてください。

ちなみに、一度だけダウンロードしたい方は、次のようなソフトもあります。

自炊ZIPをスマホや電子ブックリーダー向けに最適化する

去る2月、楽天の Kobo を中古購入しました。投げ売り価格の2500円でした。私は風呂でよく本を読むので、浴槽に落としてもそんなに凹まない安価な端末を探していました。期待をまるでしていない、という意味では Kobo は最高の端末です。

2500円という価格にしては、Linuxが中で動いているし、電子ブックリーダーでしか触ることのできない電子ペーパーを扱えたり、WiFiに対応していたり、本体を開ければ簡単にカスタマイズできたり、と Raspberry Pi よりも「香ばしい」端末なんですけどね。あんなに薄いのにバッテリーまで搭載しているし。

ソフトウェア面は最悪です。電子ブックリーダーなのに本が読みにくい。本棚の表示が遅かったり、改ページが遅かったり。電子ペーパーの画素書き換えの遅さではなく、それ以上にソフトウェアが下手に組んである遅さが気になりました。20世紀末の Windows 98 全盛期くらいの最新 PC くらいのスペックは持ってるんだし、ブックリーダーに用途は特化されているんだから、「もうちょっとどうにかしてよ」という感じ。サービス面に至っては、今更論評するまでもなしですね。

Kobo は至るところで散々叩かれまくっているので、用途を割り切るつもりで購入しました。割り切って使うと決めて購入したら、現物を触ってみてもそんなに落差がないです。
「ああ、やっぱ遅いな」とかそのくらいの印象でした。同時に、「割り切って使う」という目的はなんとかクリアできそうという実感も。

hangousuihan

hangousuihan は、画像ファイルを含むZIP圧縮ファイルに対し、解凍、画像処理、再圧縮の一連の処理を行うツールです。以前、Windows 向けに書きました。このツールの目的は、スマートフォンやタブレットPC、電子ブックリーダーなどの端末の画面にジャストフィットするサイズに画像を縮小して、圧縮ファイル自体をコンパクトにすることです。超高解像度のマンガファイル、1冊300MBなんていうのは家に保存しておいて、実際に見るのは30MBくらいのファイルで充分ですよね、というアプローチです。私が持っている Kobo も、micro SD カードを差すことができますが、水没を前提と考えているので、あまりお金をかけて拡張する気がありません。内蔵メモリだけで済ませたいところです。

Windows の場合、カチッとしたアプリケーションを拵えない限り使いものにはなりませんが、UNIX 系 OS の場合はスクリプトを書けば事足ります。私は普段、Linux しか使ってませんので、次のシェルスクリプトを用いています。

[bash]

!/bin/bash

wd="/tmp/$$"

for target in "$@"
do
[ ! -d "$wd" ] && mkdir "$wd"
unzip -j "$target" -d "$wd"
[ ! -d "$wd/result" ] && mkdir "$wd/result"
tname=basename "$target"
for item in find "$wd" -type f
do
name=basename "$item"
convert -type grayscale -quality 40 -resize 600×800 "$item" "$wd/result/$name"
zip -9 "/tmp/$tname".cbz "$wd/result/$name"
done
mv "/tmp/$tname".cbz /media/$USER/KOBOeReader/
rm -rf "$wd"
done
[/bash]

Kobo の画面解像度にフィットする 600×800 に画像を圧縮し、グレイスケール化しています。Ubuntu では、Kobo のファイルシステムのマウント場所は /media/$USER/KOBOeReader となるので、そこにダイレクトに CBZ で出力するようにしています。

使い方は、

[bash]$ ./hangousuihan.sh comic01.zip comic02.zip comic03.zip[/bash]

のように、変換したいファイルパスを引数に与えてやればOKです。

PDFを連番画像ファイルを含むZIP圧縮ファイルに変換

安価な Android 端末が出回っています。
Amazon キンドルが発売されて、投げ売り状態だった楽天の Kobo が、新品でも3000円程度で流通するようになりました。
ようやく、電子書籍を読むというライフスタイルが日本にも定着するんでしょうか。今後が楽しみです。

さて、私が持っている Huawei の IDEOS のような低スペックな端末では、PDF の文書を読むのにもひと苦労です。
低スペックな環境では、ファイルサイズが小さく高圧縮&レンダリングにマシンパワーが必要なものより、ファイルサイズが大きく冗長でも負荷をかけずに表示できるものの方が重宝される場合があります。

特にほとんどが文字の場合、ページをめくるたびに何秒も待たされるより、少々画質が荒くても(もちろん、文字が読める程度に、です)サクサクとページをめくれる方が良い事もあります。

という事で、既存の PDF ファイルの各ページを連番の JPEG ファイルにして、ZIP 形式で圧縮するスクリプトを書いてみましょう。

1. まず基本的な事

ImageMagick の convert コマンドで、次のようにタイプすると PDF のページを JPEG ファイルとして保存することができます。

[bash]
convert src.pdf[1] dst1.jpg
[/bash]

鉤括弧の中は、ページ番号を指定します。0 ページ目から開始します。存在しないページを指定すると

[bash]
convert src.pdf[999] dst999.jpg

Requested FirstPage is greater than the number of pages in the file: 645
No pages will be processed (FirstPage > LastPage).
[/bash]

とエラーになります。

2. シェルのブラケット展開で繰りかえす

エラーが出るまで繰替えせばいいので、

[bash]
for n in {0..999}; do convert src.pdf[$n] dst$n.jpg || break; done
[/bash]

と書く事ができます。0から999ページまで指定して変換を試みて、失敗したら break で抜ける、という動作をします。

3. 圧縮ファイルにつっこむ

変換し終わったファイルから ZIP ファイルに追加していくには

[bash]
for n in {0..999}; do convert src.pdf[$n] dst$n.jpg || break; zip target.zip dst$n.jpg; done
[/bash]

という風に、そのまま zip コマンドに投げてやれば良いです。

[bash]
for n in {0..999}; do convert src.pdf[$n] dst$n.jpg || break; zip target.zip dst$n.jpg && rm dst$n.jpg; done
[/bash]

ZIP ファイルへの追加に成功した後、JPEG ファイルは不要ですので、削除しておきましょう。

4. 変換オプションを指定する

必須ではありませんが、convert のオプションを利用する事によって、画像サイズの指定、グレースケール化、フォントの指定など様々なことができます。詳しくは

[bash]convert –help[/bash]

をご覧ください。

5. スクリプト化

以上の事を踏まえて、スクリプトにしてみます。

[bash]

/!usr/bin/env bash

src=$1
dst=$2

opt=’-density 600 -resize 640 -font kochigothic’

dir=/tmp/$$

(test ! -d $dir && mkdir $dir) || exit 1
test ! -f $src && exit 1

tmp=basename $dst

for n in {0..999}
do
pict=printf '%04d.jpg' $n
convert $opt $src[$n] $dir/$pict 2>/dev/null || break
pushd $dir >/dev/null
zip $tmp $pict && rm $pict
popd >/dev/null
done

mv $dir/$tmp $dst
rmdir $dir
[/bash]

このスクリプトは、/tmp 以下に一時ディレクトリを作成し、そこに画像ファイルとZIPファイルを貯め込むようにしています。
実行は、以下のように使います。

[bash]
pdf2cbz src.pdf dst.zip
[/bash]

dst.zip の名前を自動生成するようにすれば、複数ファイルの一括処理や Nautilus などのファイラから右クリックで変換、など、さらに便利に使えそうですね。