Nokogiriでうまく解析できなかった場合の対処
2015 年 1 月 27 日 by 山平Rubyでスクレイピングするなら、Nokogiriが定番です。
概ねDOMに忠実な実装でありながら、rubyらしく書きたいポイントは押さえている心憎いライブラリです。
ところが先日、Nokogiriを使ってWebページをスクレイピングしていた時に、上手くノードが取得できない場面に遭遇しましたので、備忘録としてここに残します。
まずは通常通りにタグを取得します。
この時のxpathはソースコードを確認して、絶対に存在するものが指定されています。
>> require 'nokogiri' => true >> require 'open-uri' => true >> url="http://hoge.fuga.com" => "http://hoge.fuga.com" >> doc=Nokogiri::HTML(open(url){|f|f.read}) => (割愛) >> zzz=doc.xpath("//p[@class='zzz']") => []
タグが取得できていません。
一体なぜなのでしょうか。
色々と試してみた結果、どうやら原因は「難読化されたJavaScriptコード」のようです。
本来なら機械的な意味で無駄が少なくなっているはずなのですが、Nokogiriと相性が悪いのでしょうか。
仕方がないので、<script>〜</script>を正規表現で取り除きます。
元々NokogiriはJavaScriptを実行できないので、あまり問題ないと判断しました。
>> require 'nokogiri' => true >> require 'open-uri' => true >> url="http://hoge.fuga.com" => "http://hoge.fuga.com" >> html=(open(url){|f|f.read}).gsub!(/<script[^>]*>.*?<\/script>/g, "") => (割愛) >> doc=Nokogiri::HTML(html) => (割愛) >> zzz=doc.xpath("//p[@class='zzz']") => [<Nokogiri::Node>]
なお、最近はヘッダ要素内ではなく、HTML中や末尾にscriptタグを記述することが増えてきました。
このため、正規表現は最短マッチさせるように記述しないと、本来必要な要素まで削除してしまうので、注意が必要です。
以上です。