Nokogiriでエラー「undefined method `[]’ for nil:NilClass」にハマる

ruby_icon_314

ruby でHTMLパーサーを作っていたのですが、euc-jpのページをパースしている最中必ず特定の場所で undefined method とかいうエラーが出て汗かきました。

3時間くらいハマってたのですが、結構意外なところで躓いている事に気がつき、非常に勉強になったのでエントリーします。

まず、今回やりたかったことは適当なwebページをNokogiriで解析し、中に存在するURLリンクを全部引っこ抜く という、まぁよくありがちな処理でした。

だいぶ端折ってかくと こう

require 'rubygems'
require 'nokogiri'
require 'open-uri'

# htmlを取得しに行く
url = 'http://hogehoge....'
doc = Nokogiri( open(url).read)

doc.css("div.hogehoge dl").each do |dd|
blog_url = dd.css("a").first["href"]
end

で、ページ内のある一定の箇所以降のaタグから拾えなくなり、標準エラーで以下の表示。

undefined method `[]’ for nil:NilClass

なんやねん。 と思いながら、dd.css(“a”)のクラスがNilクラスなのか?! とか調べてみたりするけど全然普通のNokogiriオブジェクトだったりする。

くそう、と思ってppでまるごとdocの中身吐き出してみて画面をにらみつける。

すると、ある箇所以降のHTMLテキストがまるっとNokogiriのオブジェクトに格納されていないことに気がつく。

どこやねん。 と調べてみる。 そこには”髙”という文字がいた。

どうやらHTMLの中にはEUC-JPと指定されていてもEUCとして理解できない文字コードが含まれている事があるそうです、昨日今日エンジニアになった私みたいな人間としてはナニソレ的な文字である事が、判明した的な感じ。

EUC-JPではこのコードは使えないので、(ちゃんと勉強してないので詳しいことはわかりませんが)unicodeを突っ込んで、わかるブラウザさんにはちゃんと表示される。 という仕組みだとの事。
へぇ~~ (´∀` )

さっそく解消する術を調査する。

まず、Nokogiriは文字コードを内部で変換しいてくれているらしいのですが、これが怪しい。

信用のならないNokogiriに渡す前に、kconvで一度まるっと対象のEUCなページをUTF8に変換する事を試みる。
ただ、変換後の文字列をNokogiriに渡すときは文字コード指定で渡さないと怒られたのでシャーナシで第3引数でUTF8を指定します。
わかりやすく書くと、こんな感じ。

require 'rubygems'
require 'nokogiri'
require 'open-uri'
require 'kconv'

html_txt = open("http://hogehoge...").read
html_txt_utf8 = html_txt.kconv(Kconv::UTF8, Kconv::EUC)
doc = Nokogiri(html_txt_utf8,'nil','UTF-8')
# 以下、上と同じ

これだと、中に混在していたunicodeさんとかいうダークサイドな見た目の漢字達がパリっとしたUTF8になってエラーがでなくなりました。
(*´▽`*)=3

ちなみに、もっとイケてる方法がありますよ 的な方いらっしゃったら是非教えていただけると助かります。

おわり

2012-08-08 | Posted in RubyNo Comments » 


関連記事

Comment





Comment



*