ちょっくら趣味でWebスクレイピングしてみる。
普段ほとんど使わないRubyで、Nokogiriというライブラリを使ってみたところ、サイトによってうまくパースできないことがあった。
うーん、おかしい…とパケットキャプチャ結果をしばし眺める。すると、content-encodingに’gzip’がある場合にうまくいっていない。gzipされたHTTPレスポンスをそのままNokogiriでパースしては駄目なようだ。
てっきりnet/httpかnokogiriが、gzipレスポンスを展開して、自動的に処理してくれるものと思いこんでいました(それとも、何かうまいやり方があるのかな?)。下のようなコードを書くことで、gzipにも対応できましたとさ。
require "nokogiri" require "net/http" require 'zlib' require 'pp' class DocUtil def self.getDoc(url) content = self.getContent(url) doc = Nokogiri::HTML.parse(content) return doc end def self.getContent(url) uri =URI.parse(url) http = Net::HTTP.new(uri.host, uri.port) response = http.get(uri.request_uri) #encodingを確認する encoding=response['content-encoding'] content=nil if encoding then #圧縮あり case encoding when 'gzip' #gzip i=Zlib::GzipReader.new(StringIO.new(response.body)) content=i.read when 'deflate' #deflate i=Zlib::Inflate.new content=i.inflate(response.body) else raise "Unknown: " + encoding end else content=response.body #圧縮無しの場合 end return content end end doc = DocUtil.getDoc("http://twitter.com") pp doc #パース結果を表示