PhantomJSで日本語が文字化けして辛い
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-protocol
でTLSとかを指定する。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ではない最高の解決方法があれば誰か教えてください。
昨日、今日、ずっと/etc/fontsのファイルをごちゃごちゃいじってる
— シリル@概念 (@t_cyrill) 2014, 10月 1
コンソールログはphantomjsの実行ログでいっぱいだ。200回くらいは打っているだろうか。phantomjsの開発者はもっといっぱい打っているんだろうな。自分はちがう。
— シリル@概念 (@t_cyrill) 2014, 10月 1
その他
- LANG="ja_JP.UTF8" だとダメだという情報もあるけど、LANG=Cでもうまくいかなかったのでよくわからない。
- 適応したいフォント以外を
mv
するなどしてどければいいという情報もあったけど、fontconfigが適したフォントを見つけられず結果的にそれが選ばれるだけで、いい方法ではないと思う。 - あと、自分の環境ではその方法でもうまくいかなかったので、他の原因がありそう。
- というか悪いのはfontconfigではないのかもしれない。
/etc/fonts/fonts.conf
を書き換える系はやめておいたほうがいい。このファイルは自動生成されるファイルなので、いつ書き換わるかわからない。