Nokogiriのインストールについては、Rails Nokogiri を導入するを参照ください。
リファレンス
- Nokogiriの公式サイト:Nokogiri 鋸
- Nokogiriのリファレンス1:Nokogiri (RubyDoc)
- Nokogiriのリファレンス2:Nokogiri (RubyForge)
リファレンスの見方
Nokogiri::HTMLメソッドなどを見ると、戻り値が=> Objectとなっており、戻り値の型が分かりません。そんなときは、戻り値に対して、.classメソッドを使い、型を確認します。例えば次のようにします。
doc = Nokogiri::HTML(open('http://www.yahoo.co.jp')) p doc.class #=> Nokogiri::HTML::Document
上の例では、戻り値がNokogiri::HTML::Documentであることが分かるので、リファレンスのNokogiri::HTML::Documentのページを参照して、どんなメソッドが使えるのか確認できます。
さらに上記のページを見ると、XML::Documentを継承(Inherits)しており、さらにXML::Nodeを継承していることが分かるので、そちらのメソッドも使えます。
基本的な使いかた
Nokogiriは次のステップで使います。
- Nokogiriライブラリを読み込む
- HTMLなどを解析(パース)して、Nokogiriドキュメントを生成する。
- CSS指定かXPath指定で目的の要素を取得する。
Step1. Nokogiriライブラリを読み込む
Nokogiriを使うには、nokogiri を読み込みます。
require 'nokogiri'
Step2. Nokogiriドキュメントを生成する
HTMLを解析してNokogoriドキュメントを生成するにはHTMLメソッドを使います。open-uriはhttp/ftpに簡単にアクセスするためのクラスです。openメソッドがopen-uriのものです。
require 'open-uri' doc = Nokogiri::HTML(open('取得元のURL'))
ここで得られたdocは、Nokogiri::HTML::Document(継承:XML::Node、XML::Document、XML::Searchable) です。使えるメソッドはリンク先のリファレンス参照。
カラム:ブラウザでの見た目通りにHTMLを取得できない
例えば、www.yahoo.co.jpをopenメソッドで取得すると、ブラウザでアクセスした場合と結果が異なります。次のようにすると確認できます。
doc = Nokogiri::HTML(open('http://www.yahoo.co.jp')) render :text => doc.to_html
この場合はユーザーエージェントを指定してアクセスします。例としてgoogle chromeのユーザーエージェントを使用してみます。
doc = Nokogiri::HTML(open('http://www.yahoo.co.jp', "User-Agent" => "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36")
ブラウザと同じように取得できたことを確認します。
Step3. ドキュメントから目的の要素を取得する
XML::Searchableのメソッドを使って絞り込みを行います。
方法1.
CSSで検索する場合は、cssメソッドを使います。cssメソッドの戻り値はXML::Elementの集合のXML::NodeSetです。
doc.css('CSSセレクタルール')
例) IDが#topicsfbのリスト要素liを取得するには次のようにします。
nodes = doc.css('#topicsfb li') # 取得したXML::NodeSetからXML::Elementを取り出して表示します。 nodes.each do |node| p node.text end
方法2.
XPathで検索する場合は、xpathメソッドを使います。
doc.xpath('XPath')
例) IDが#topicsfbのリスト要素liを取得するには次のようにします。cssメソッドの戻り値はXML::Elementの集合のXML::NodeSetです。
nodes = doc.xpath('//*[(@id = "topicsfb")]//li') # 取得したXML::NodeSetからXML::Elementを取り出して表示します。 nodes.each do |node| p node.text end