Ubuntu 12.04 ruby1.9.3p0 mechanize 2.5.1 Yahoo文字化け

特に最新の組み合わせを指向した分けではないが、新規のubuntuサーバーを建てるために12.04を採用したために全て:

  • ubuntu11.04 ->12.04
  • ruby1.9.2p180 ->1.9.3p0
  • mechanize2.1 ->2.5.1

になった。

その途端にmechanizeで今まで正常に動いていたYahooJapanへのスクレーピング・ソフトが文字化けを起こすようになった。理由は分からないが、『きたももんが』さんの
http://d.hatena.ne.jp/kitamomonga/20090328/ruby_mechanize_incoming_0_9_3
に有るように、YahooJapanはメタタグでエンコードの指定がなく、HTTPヘッダで'euc-jp'が設定されているケースなので、mechanizeとnokogiriの間でエンコードの繋ぎがうまく行っていないのかもしれない。

理由良く分からなかったが、今まで(ubuntu11.04-ruby1.9.2p180-mechanize2.1)では以下の16個目のリンクを探すために

\新規スペース\
p agent.get(YahooJapan_URL).search('a')[15].inner_text #=>新規スペース
でうまく行っていたが、新規の組み合わせでは『新規スペース』が文字化けを起こす。(全角の『新』『ー』特に要注意だと思う。)
山勘だけどエンコード:Windows-31J,cp932がらみと決めつけて、

eucBody=a.get(YahooJapan_URL){|page| page.encoding="EUC-JP"}.body
utfBody=eucBody.encode('UTF-8','EUC-JP')
page = Nokogiri::HTML(utfBody)  #=>ここでエラー
p page.search('a')[15].inner_text
`encode': "\xFD\xFE" from EUC-JP to UTF-8 (Encoding::UndefinedConversionError)

そこで、無理やり古いパッケージNKFで

eucBody=agent.get(YahooJapan_URL){|page| page.encoding="EUC-JP"}.body
utfBody=NKF.nkf('--utf8 --euc-input', eucBody)
page = Nokogiri::HTML(utfBody)   #=>エラーなし
p page.search('a')[15].inner_text #=>新規スペース OK

と言う訳で、実際のところOS,ruby,mechanize(nokogiri)の何処に問題が有るのか分からないが取り敢えずうまく行った。

ただ、この方法の著しく馬鹿馬鹿しいのは、mechanizeとnokogiriを切り離して使うのなら、態々mechanizeを使わずに初めからopen-uriをつかったほうが簡単だし早い。後にフォームの入力/サブミット等がないのなら、こんなことはしない方が良いのかもしれない。


参考
http://jp.rubyist.net/magazine/?0009-BundledLibraries