Nookogiriで使えるcssセレクタまとめ


Nokogiriとは?

RubyでWebスクレイピングをするライブラリ。
Webスクレイピングは、ホームページから欲しいデータや文章を自動抽出する技術のことです。仕組みとしては、ホームページのhtml構造をみて、欲しいデータを特定できるhtmlタグや属性を指定することで、対象のデータを抽出します。

基本的な使い方

スクレイピングをするコードの基本的な書き方は次のようになります。

scraping.rb
require 'open-uri' #スクレイピングしたいページのurlを読み込むためのライブラリ
require 'nokogiri' #Nokogiriライブラリ

#urlを読み込む
url = URI.open('https://対象のページurl')

#url先のページのhtmlを読み込み、Nokogiri::HTML::Documentクラスへ変換
doc = Nokogiri::HTML(url)

このdocに対して様々な操作をすることで、html内の特定の箇所のデータだけ抽出することができます。

cssとat_cssメソッド

次のようなページをスクレイピングしたいとします。

<html>
  <head><title>お気に入り映画</title></head>
  <body>
    <h3>映画</h3>
    <div class="movies">
      <div>
        <h3 class="title">ショーシャンクの空に</h3>
        <p>ヒューマンドラマ</p>
        <p id="year">1994</p>
      </div>
    </div>
    <div class="movies">
      <div>
        <h3 class="title">スターウォーズ</h3>
        <p>SF</p>
        <p id="year">1977</p>
      </div>
    </div>
  </body>
</html>

cssメソッドは、Nokogiri::HTML::Documentクラスの持つメソッドで、引数にcssセレクタを与えることで、それを満たす要素を全て抽出します。複数ある場合、該当する要素が全て入った配列が得られます。(厳密には配列ではなくNokogiri::XML::NodeSetクラス)。
該当する要素が見つからなかった場合は、空の配列が返ってきます。

doc.css("h3") #タグで指定 
# >> [ <h3>映画</h3>, <h3 class="title">ショーシャンクの空に</h3>,  <h3 class="title">スターウォーズ</h3>]

doc.css(".title") #クラスで指定
# >> [<h3 class="title">ショーシャンクの空に</h3>, <h3 class="title">スターウォーズ</h3>]

doc.css("#year") #idで指定
# >> [<p id="year">1994</p>, <p id="year">1977</p>]

doc.css("h1") #ない要素を指定
# >> []

似たようなcssセレクタを用いる抽出用メソッドで、at_cssというものもあります。
こちらは、cssメソッドとは違って、複数該当するものがあっても一番最初に引っかかった要素のみを返します。
また、cssメソッドとは異なり、対象の要素が見つからなかった場合nilが返ってきます。

doc.at_css("h3") #タグで指定 
# >>  <h3>映画</h3>

doc.at_css(".title") #クラスで指定
# >> <h3 class="title">ショーシャンクの空に</h3>

doc.at_css("#year") #idで指定
# >> <p id="year">1994</p>

doc.at_css("h1") #ない要素を指定
# >> nil

複雑なcssセレクタの指定方法

ページのhtml構造によっては、一つの指定では欲しいデータを特定できないこともあると思います。
その時は、次のようなセレクタ指定をとることもできます。

doc.css(".movies h3") #半角スペースで区切ると、.moviesクラスの配下にある全てのh3タグを抽出
# >> [<h3 class="title">ショーシャンクの空に</h3>, <h3 class="title">スターウォーズ</h3>]

doc.css(".movies > h3") # >で区切ると、.moviesクラスの直下にあるh3タグを抽出
# >> [<h3 class="title">ショーシャンクの空に</h3>, <h3 class="title">スターウォーズ</h3>]

doc.css("h3 + p") # +で区切ると、h3タグと並列な直後の要素pを抽出
# >> [<p>ヒューマンドラマ</p>, <p>SF</p>]

doc.css("h3 ~ p") # ~で区切ると、h3タグと並列なそれより後の要素pを抽出
# >> [<p>ヒューマンドラマ</p>,<p id="year">1994</p>, <p>SF</p>, <p id="year">1977</p>]

また、テキストで指定することもできます。

doc.css("h3:contains('スターウォーズ')") # :contains('文字列')を与えると、テキスト検索できる。
# >> <h3 class="title">スターウォーズ</h3>

最後に

今回は説明していませんが、得られた1つの要素は、Nokogiri::XML::Elementクラスのオブジェクトで、ここからテキストを抽出したり、aタグで指定されているurlを取得したりできます。
対象のhtml構造や、どう言ったデータが欲しいかによってcssセレクタの指定方法が違うので、全てをパターン化して記事にするのは難しいです。
今回紹介した指定方法を組み合わせて、欲しいデータを抽出しましょう。