Rubyでスクリーンショットサーバ(1)

最近リンク先のページを小さく表示しているサイトをよく見かけるのですが、興味があったので実装する方法を調べていました。私はてっきりクライアントのブラウザでレンダリングをさせているのだと思っていたのですが(すいません無知で)、スクリーンショットをサムネイル化したイメージファイルを表示しているとわかりました。

すでにいくつかサービス化もされているようです。


ページのサムネイルorキャプチャをWEB上で作るサービスまとめ:phpspot開発日誌


他には以下のようなサイトがありました。


http://thumbs.bookmacro.com/sample/
WebToJpeg
Blinky


無料のサービスがほとんどですので利用させてもらえばいいのですが、サーバ側で保持していないサムネイルを新たに生成するのにどうしても時間がかかるようでしたので、何とか自前でつくろうと思い方法を調べてみました。
システム構成は、サーバはLinux、できればOpenVZ上で、APIは勉強中のRuby、できればRuby On Railsでつくり、イメージはファイルにするのではなくMySQLに格納して、というのを考えていました。

すでに他に構築している人がいないかなと探してみた結果、見つけたのが以下のサイトです。Linuxを使って、言語はPerl/Python/PHP/Rubyと一同勢ぞろいです。ただ、はてなさんはスクリーンショットWindowsで行っているようです。


SimpleAPI の仕組みについて考察してみる - drk7jp
http://yamashita.dyndns.org/blog/generate-web-page-thumbnails-on-linux-server-without-x
http://www.res-system.com/item/603


Drk7jpさんをでは、Xvfbという仮想フレームバッファ(仮想Xサーバ)を立ち上げそこにブラウザを起動させ、スクリーンショットをとるという方法をとっています。参考にしてVZ上で試してみました。VEはとりあえずFedora Core3(パッチ提供止まってますが)で構築しました。
Xvfbってどこかで聞いたことがあるような…と思ったら、オープンギャラリーさんのOpenVZのVEでXサーバを立ち上げる手順でも使っていました。
仮想環境では使うことができない(サーバにもあまり必要がない)/dev/ttyを必要としないXサーバ、といったところでしょうか。

手順通りに構築するとすんなりスクリーンショットをとることができました。
ただ、VE環境だとX系のパッケージをインストールする際に、/dev配下のデバイスファイルがほとんどなくなってしまいます。こうなるとVEにsshできなくなりますし、ハードウェアノードからvzctl enter もできなくなります。おそらくどちらもVEの/dev/urandomが必要なのでしょう。どこかから/dev配下のファイルをコピーしてくれば復旧します。よく見るとオープンギャラリーさんでも説明していました。
また、Firefox1.5系を使っていると何回かサイトを表示させていると不具合があったので、2.0系に変更しました。

この方法で一応できたのですが、以下の点に不満がありました。

  • 連続してキャプチャすると、レンダリングがキャプチャに追いつかず、前のページ(もしくはレンダリング途中のページ)がキャプチャされるので、sleepをいれなければならない
  • 外部コマンドを呼び出していてかっこ悪い
  • ブラウザ(Firefox)を常駐させているので、大量にメモリ食っている


Weboo!Returnsさんではgtkmozembedというライブラリを使っていて、外部コマンドを呼び出しておらず、これが理想です。ただ、言語がPythonなのがネックです。
Rubyで同じことができないかと調べてみると、Rubyにもgtkmozembedライブラリが提供されていることがわかりました。

マニュアルがほとんど英語ですし、Rubyの基礎も怪しいのに背伸びしすぎかなと躊躇していると、すでにBlinkyさんがgtkmozembedを利用してRubyで構築していることがわかりました。しかもソースを全て公開しています。感謝です。

さっそくDBにバイナリデータを格納するように改造してみようと思います。まずは、このソースを読んで勉強します。