読者です 読者をやめる 読者になる 読者になる

なんかかきたい

プログラミングなどの個人的なメモやサークル「ゆきいろパラソル」の情報を載せてます

PhantomJSで日本語が文字化けして辛い

javascript phantomjs ruby

PhantomJSは素敵なツールで、Webサイトのキャプチャを簡単に取ったりできる。 PhantomJSを使ってWebサイトのスナップショットを取る便利なライブラリも既にいくつかあって、例えばnode-webshotとかあったりする。便利。

そんな便利なPhantomJSだけど、Linux上で動かすと日本語フォントが文字化けするケースがしばしばあって、とたんに苦しい感じになる。 先日、Debian Wheezyで動かそうとして大変な思いをしたので、いくつか試してわかったことを残しておきたいと思う。 ただ、完全にうまくいく方法は結局わからなかったのでご容赦願いたい。もっとこうしたほうがいいのではみたいなのがあったら教えてほしいところ。

なお、Macだとだいたいうまくいくけど、1.9.7を使うとWebフォントの描画がおかしな感じになるので、1.9.2とか使うのがよい。

PhantomJSをインストールするのは、npmが便利。

npm i phantomjs@1.9.2-6

先に説明した通り、1.9.7だとWebフォントの描画がうまくいかないので、1.9.2を使う。今後のバージョンで直ると嬉しい。

後は、examplesに入っているrasterize.jsを使って簡単にキャプチャを試すことができる。

./node_modules/.bin/phantomjs --ssl-protocol=any \
./node_modules/phantomjs/lib/phantom/examples/rasterize.js \
https://encrypted.google.com/ capture.png

SSLのサイトをキャプチャするには--ssl-protocolTLSとかを指定する。anyも使えるので、とりあえずanyにしておけばいいんじゃないかと思ってる。

OSXだとこれで十分で、うまく日本語でもキャプチャーできるけど、同じことをDebianでやるとだいたいお豆腐になる。

日本語フォントを入れる

当たり前だけど、日本語フォントが入っていないと日本語をレンダリングできないのでお豆腐になる。

デフォルトのフォントはdejavuなっているはずなので、IPAフォントとかそのあたりを入れればいい。MigMixがいい感じだった。

aptitude install fonts-migmix

これで日本語フォントがインストールされる。 fc-matchとかを使って確認する。

fc-match 'sans-serif'
migmix-2p-regular.ttf: "MigMix 2P" "Regular"

これでうまく日本語が表示された幸せな方はラッキーです。

font-configの設定をする

日本語フォントをインストールするだけで解決するといいけど、今回うまくいかなかったので、font-confをいじることになった。

PhantomJSはfont-configを使っているので、代替フォントの設定をするとよい。と思ったけど、うまくいかなかった。

フォントの設定は/etc/fontsにあって、/etc/fonts/fonts.confとかをいじるとかネットで検索すると引っかかるけど、 Debian的には/etc/fonts/fonts.confを直接触るのはダメらしいので、/etc/fonts/conf.availにファイルを置いて/etc/fonts/conf.dシンボリックリンクを置くスタイルにするらしい。 もしくは、/etc/fonts/local.confを作ってもいいし、$XDG_CONFIG_HOME/fontconfig/fonts.confでもいい。

fontfoncigの設定ファイルはXMLで、たとえばこんな感じに書く。

<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
  <match target="pattern">
    <test qual="any" name="family">
      <string>serif</string>
    </test>
    <edit name="family" mode="assign" binding="strong">
      <string>MigMix 2P</string>
    </edit>
  </match>
</fontconfig>

これでserifのフォントをMigMixにできるはずだけど、自分の環境ではうまくできなかったので、次の方法で対応した。 (PhantomJSがQTWebkitを使っていることが原因じゃないかと疑っているけど、調べきれていない。)

なお、69-language-selector-ja-jp.confなんて設定があるので、試してみるのもいいかもしれない。

CSSを入れ替える

PhantomJSにはpage.evaluateがあって、任意のJSを実行することができる。 これを利用して、ページのCSSを入れ替え、フォントをシステムにインストールされているものにしてしまう。

* {
  font-family: "MigMix 2P"
}

これはただのWorkaroundだけど、これだけでうまくいくページも多い。どうしてもダメなときには便利だ。 ただ、この方法だとWebフォントの置き換えがされてしまうと苦しいので、CSS3のnotセレクタを使うと便利。

 最後に

workaroundではない最高の解決方法があれば誰か教えてください。

その他

  • LANG="ja_JP.UTF8" だとダメだという情報もあるけど、LANG=Cでもうまくいかなかったのでよくわからない。
  • 適応したいフォント以外をmvするなどしてどければいいという情報もあったけど、fontconfigが適したフォントを見つけられず結果的にそれが選ばれるだけで、いい方法ではないと思う。
  • あと、自分の環境ではその方法でもうまくいかなかったので、他の原因がありそう。
  • というか悪いのはfontconfigではないのかもしれない。
  • /etc/fonts/fonts.confを書き換える系はやめておいたほうがいい。このファイルは自動生成されるファイルなので、いつ書き換わるかわからない。