bundle install
した時にRubyのバージョンがあってなくて「nokogiriのインストールが終わらん〜」って悶絶するかたをよく見る気がします。
今回は、お仕事で例のnokogiriを調査→使うシーンがありましたので、調査時のメモを書き残しておこうかなと思います。
この記事なに? 🤔
Rubyのgem「nokogiri」を使ってHTML要素を抜き出す、というやり方を記載する記事になります。
nokogiriとは?
HTML / XMLといったDOM構造を持つドキュメントから、要素を抜き出せるGemのようです。
※ちなみに、nokogiriは日本語の鋸が発祥っぽいですね。
公式サイト、リポジトリはこちらから。
- GitHub - sparklemotion/nokogiri: Nokogiri (鋸) is a Rubygem providing HTML, XML, SAX, and Reader parsers with XPath and CSS selector support.
- Nokogiri
実際に動かしてみる
では、以下のリポジトリに格納されているhtmlから、実際にHTML要素を抜き出してみます。
サンプルコード
要素を抜き出す対象のhtml
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> </head> <body> Nokogiriテスト <input type="hidden" name="hidden_name" value="hidden_name" /> <input type="hidden" id="hidden_id" value="hidden_id" /> <div class="nokogiri"> test </div> </body> </html>
nokogiriを使ったrubyのソース
require 'nokogiri' # index.htmlを読み込み html = open('./index.html', &:read) doc = Nokogiri::HTML.parse(html, nil) doc.search('input').each do |element| puts "element.attributes: #{element.attributes}" puts "type: #{element.attributes['type'].value}" puts "name: #{element.attributes['name'].value}" if element.attributes['name'] puts "id: #{element.attributes['id'].value}" if element.attributes['id'] puts "value: #{element.attributes['value'].value}" end doc.css('.nokogiri').each do |element| puts "element.attributes: #{element.attributes}" puts "element.content: #{element.content}" end
結果
# 1つめのループ element.attributes: {"type"=>#<Nokogiri::XML::Attr:0x3feb26ca60ec name="type" value="hidden">, "name"=>#<Nokogiri::XML::Attr:0x3feb26ca60d8 name="name" value="hidden_name">, "value"=>#<Nokogiri::XML::Attr:0x3feb26ca60b0 name="value" value="hidden_name">} type: hidden name: hidden_name value: hidden_name element.attributes: {"type"=>#<Nokogiri::XML::Attr:0x3feb26caa728 name="type" value="hidden">, "id"=>#<Nokogiri::XML::Attr:0x3feb26caa714 name="id" value="hidden_id">, "value"=>#<Nokogiri::XML::Attr:0x3feb26caa6d8 name="value" value="hidden_id">} type: hidden id: hidden_id value: hidden_id # 2つめのループ element.attributes: {"class"=>#<Nokogiri::XML::Attr:0x3feb26cb23c4 name="class" value="nokogiri">} element.content: test
使い方まとめ
実際に使ってみて、自分なりにnokogiriの使い方をまとめてみると、以下のようになりました。
- 要素の特定方法
- HTMLタグで特定したい場合は
search
を使う - クラスで特定したい場合は
css
を使う
- HTMLタグで特定したい場合は
Nokogiri::XML::Attr
から特定の値を抜き出す場合- 属性値(
name
/id
/type
など)を抽出したい場合はattributes['要素名'].value
- タグ内の値(
<div>value</div>
のvalue
)を抽出したい場合はcontent
- 属性値(
※上記は、必要に応じて追記していくかもです。
おわり
nokogiri、使い勝手いいなーという感想です。
今回、大きいDOMを扱うわけでもないので、パフォーマンス面は調査しませんでしたが、速度的にはどうなんだろう。と思っていたら、nokogiriのパフォーマンス測定を行っていた記事がありました。感謝感謝。
結果だけさらっと見た感じ、悪くなさそうですが、XMLを解析する場合はxpath
メソッドを使って要素検索した方が速いっぽいですね。