RubyとXPathでスクレイピングをマスター!14の詳細な手法とサンプルコード

RubyとXPathを使用したスクレイピングの詳細な手法とサンプルコードを解説する記事のサムネイル Ruby
この記事は約21分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればサンプルコードを活用して機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

ウェブスクレイピングとは、ウェブページから情報を抽出することです。

手作業では時間がかかるこの作業を自動化するための技術が求められます。そしてそのためのツールがRubyとXPathです。

Rubyはプログラミング言語の一つで、XPathはXML文書の一部を選択するための言語です。

この二つを組み合わせることで、効率的にウェブページから情報を抽出することが可能になります。

今回の記事では、RubyとXPathを用いたウェブスクレイピングの具体的な手法を14種類、サンプルコードと共にご紹介します。

初心者から経験者まで、幅広い読者に理解してもらえるよう詳細に解説します。

スクレイピングの基本から、RubyとXPathの使い方、さらにはカスタマイズの方法まで、あなたのスキルアップに役立つ情報が詰まっています。

それでは、一緒に学んでいきましょう。

●RubyとXPathとは

まず初めに、RubyとXPathについて基本的な情報をお伝えします。

それぞれ何であるのか、何のために使うのか、基本的な特性などを理解することで、その後のスクレイピングの手法について理解しやすくなります。

○Rubyとは

Rubyは、まつもとゆきひろ氏によって開発されたプログラミング言語です。

オブジェクト指向を基本とした言語であり、シンプルで読みやすい文法が特徴です。

Rubyはウェブアプリケーションの開発によく使われ、特にRuby on Railsというフレームワークを用いた開発が広く行われています。

しかし、Rubyの使い道はそれだけにとどまりません。

Rubyのライブラリには、さまざまな機能を提供するものが揃っています。

その中には、ウェブページの情報を抽出するためのライブラリも含まれており、その一つがNokogiriです。

Nokogiriは、HTMLやXMLの解析を手助けし、XPathやCSSセレクタを用いて情報を抽出することができます。

これがRubyをウェブスクレイピングに用いる理由の一つです。

○XPathとは

XPathとは、XML文書から特定の部分を選択するための言語です。

XPathはXMLのツリー構造をトラバース(走査)するための強力なツールで、XML文書の任意の部分を指定することができます。

XPathの一番の特徴はその柔軟性です。

XML文書のノード(要素)を特定するための複数の方法が用意されており、その中から最適なものを選ぶことができます。

また、XPathはその名の通りXMLに対して用いるものですが、HTMLに対しても使用することができます。

これは、HTMLをXMLの一種であるXHTMLとして解釈し、XPathを適用するためです。

これらRubyとXPathの特性を理解した上で、次に進んでウェブスクレイピングの手法を見ていきましょう。

●RubyでのXPathの基本的な使い方

RubyでXPathを用いてウェブページから情報を抽出するためには、Nokogiriライブラリを使います。

Nokogiriは、RubyでHTMLやXMLの解析を行うためのライブラリで、XPathやCSSセレクタによる情報抽出をサポートしています。

Nokogiriを使用するためには、まずRubyの環境にインストールする必要があります。

Rubyの環境が既にある場合は、下記のコマンドでNokogiriをインストールできます。

gem install nokogiri

Nokogiriのインストールが完了したら、次にNokogiriを使ってHTML文書を解析し、XPathを使って情報を抽出する方法を見ていきます。

そのための基本的なコードは次のようになります。

require 'nokogiri'
require 'open-uri'

url = 'https://www.example.com'
doc = Nokogiri::HTML(open(url))

nodes = doc.xpath('//h1')
nodes.each do |node|
  puts node.text
end

このコードでは、まずopen-uriライブラリとNokogiriを読み込んでいます。

次に指定したURLのHTMLを取得し、Nokogiri::HTMLメソッドで解析します。

その結果をdocという変数に格納しています。

次に、doc変数のxpathメソッドを用いて、HTML文書からh1タグを全て抽出しています。

その結果をnodesという変数に格納し、nodesの各要素(node)に対して、そのテキストを出力しています。

これがRubyとNokogiriを使った基本的なXPathの使い方です。

●XPathの基本的な文法

XPathの文法を理解することは、XPathを使ってウェブページから情報を抽出するための重要な第一歩です。

XPathの基本的な文法は次のとおりです。

①ノードの選択

ノードとはXML文書の要素や属性などを指します。

XPathでは、「/」を用いてノードを選択します。

例えば、「/html/body」はhtmlノードの下のbodyノードを指します。

②属性の選択

属性はノードに付随する情報で、XPathでは「@」を用いて属性を選択します。

例えば、「//a[@href]」はhref属性を持つ全てのaノードを指します。

③文字列の選択

ノードのテキスト内容は「text()」関数を用いて選択します。

例えば、「//p/text()」は全てのpノードのテキスト内容を指します。

④ワイルドカード

「」は任意のノードを指します。

例えば、「//p」は全てのノードの下のpノードを指します。

⑤複数のパス

「|」は複数のパスを同時に選択します。

例えば、「//h1 | //h2」はh1ノードとh2ノードを同時に指します。

⑥条件付き選択

「[]」は条件を指定してノードを選択します。

例えば、「//a[@href=”https://www.example.com”]」はhref属性が「https://www.example.com」である全てのaノードを指します。

これらの基本的な文法を用いることで、様々なXPath式を組み立てることが可能になります。

それでは次に、これらの文法を用いたRubyとXPathによるウェブスクレイピングの具体的な手法を見ていきましょう。

●RubyとXPathを用いたスクレイピングの手法

ウェブスクレイピングでは、XPathの文法を応用して、目的とする情報を効率的に抽出します。

ここでは、RubyとXPathを用いたスクレイピングの具体的な手法をいくつか紹介します。

○サンプルコード1:XPathを使用してHTML要素を取得

下記のコードでは、XPathを使用してHTML文書からh1要素を取得する手法を紹介します。

この例では、「//h1」を用いてHTML文書中の全てのh1要素を選択しています。

require 'nokogiri'
require 'open-uri'

url = 'https://www.example.com'
doc = Nokogiri::HTML(open(url))

h1_elements = doc.xpath('//h1')
h1_elements.each

 do |element|
  puts element.text
end

このコードを実行すると、指定したURLのHTML文書から全てのh1要素のテキストが出力されます。

このように、XPathを使用して特定のHTML要素を取得することができます。

○サンプルコード2:XPathを使用して特定の属性値を取得

下記のコードでは、XPathを使用してHTML文書から特定の属性値を取得する手法を紹介します。

この例では、「//a[@href]」を用いてhref属性を持つ全てのa要素を選択し、その属性値を取得しています。

require 'nokogiri'
require 'open-uri'

url = 'https://www.example.com'
doc = Nokogiri::HTML(open(url))

a_elements = doc.xpath('//a[@href]')
a_elements.each do |element|
  puts element.attribute('href').value
end

このコードを実行すると、指定したURLのHTML文書から全てのa要素のhref属性の値が出力されます。

このように、XPathを使用して特定の属性値を取得することができます。

○サンプルコード3:XPathを使用して複数の要素を一度に取得

下記のRubyとXPathを用いたサンプルコードでは、複数のHTML要素を一度に取得します。

この例では、HTML文書中のh1要素とh2要素を同時に選択します。

この選択はXPathの「|」演算子を用いて行います。

require 'nokogiri'
require 'open-uri'

url = 'https://www.example.com'
doc = Nokogiri::HTML(open(url))

elements = doc.xpath('//h1 | //h2')
elements.each do |element|
  puts "#{element.name}: #{element.text}"
end

このコードでは、「//h1 | //h2」というXPath式を使って、h1要素とh2要素を同時に指定しています。

そして、それぞれの要素の名前とテキストを出力します。

つまり、出力結果はそれぞれの要素のタイプ(h1またはh2)とそのテキスト内容になります。

このように、XPathの「|」演算子を用いると、一度に複数の種類の要素を取得することができます。

○サンプルコード4:XPathを使用してテキスト内容を取得

下記のRubyとXPathを用いたサンプルコードでは、特定のHTML要素のテキスト内容を取得します。

この例では、p要素のテキストを取得しています。

require 'nokogiri'
require 'open-uri'

url = 'https://www.example.com'
doc = Nokogiri::HTML(open(url))

p_elements = doc.xpath('//p/text()')
p_elements.each do |element|
  puts element
end

このコードでは、「//p/text()」というXPath式を使って、全てのp要素のテキストを指定しています。

そして、それぞれの要素のテキストを出力します。

つまり、出力結果はそれぞれのp要素のテキスト内容になります。

このように、XPathの「text()」関数を用いると、特定のHTML要素のテキストを取得することができます。

○サンプルコード5:XPathを使用して特定の要素の存在を確認

下記のRubyとXPathを用いたサンプルコードでは、特定のHTML要素が存在するかどうかを確認します。

この例では、特定のクラスを持つdiv要素が存在するかどうかを検証します。

require 'nokogiri'
require 'open-uri'

url = 'https://www.example.com'
doc = Nokogiri::HTML(open(url))

element = doc.xpath('//div[@class="important"]')
if element.empty?
  puts '該当の要素は存在しません。'
else
  puts '該当の要素が存在します。'
end

このコードでは、「//div[@class=”important”]」というXPath式を使って、特定のクラス(この例では”important”)を持つdiv要素を指定します。

そして、その要素が存在するかどうかを出力します。

つまり、出力結果は、特定のクラスを持つdiv要素が存在するかどうかの確認結果になります。

このように、XPathを用いると、特定の要素が存在するかどうかを容易に確認することができます。

○サンプルコード6:XPathを使用して特定の要素の位置を取得

下記のRubyとXPathを用いたサンプルコードでは、特定のHTML要素の位置を取得します。

この例では、全体のul要素の中から3つ目のli要素を取得します。

require 'nokogiri'
require 'open-uri'

url = 'https://www.example.com'
doc = Nokogiri::HTML(open(url))

element = doc.xpath('//ul/li[3]')
puts element.text

このコードでは、「//ul/li[3]」というXPath式を使って、全体のul要素の中から3つ目のli要素を指定しています。

そして、そのli要素のテキストを出力します。

つまり、出力結果は、全体のul要素の中から3つ目のli要素のテキストになります。

このように、XPathを用いると、特定の位置の要素を容易に取得することができます。

○サンプルコード7:XPathを使用して階層構造の要素を取得

次に紹介するRubyとXPathを用いたスクレイピングのサンプルコードでは、HTMLの階層構造の中から特定の要素を取得する方法を解説します。

下記のコードは、親要素の下にある子要素を取得する例です。

require 'nokogiri'
require 'open-uri'

url = 'https://www.example.com'
doc = Nokogiri::HTML(open(url))

element = doc.xpath('//div[@class="parent"]/p')
puts element.text

このコードでは、「//div[@class=”parent”]/p」というXPath式を用いて、class属性が”parent”という値を持つdiv要素の下にあるp要素を取得しています。

そのp要素のテキストが出力されます。

これにより、HTMLの階層構造を活用して、特定の位置にある要素を精密に取得することが可能になります。

○サンプルコード8:XPathを使用して特定のテキストを持つ要素を取得

下記のRubyとXPathのコードは、HTML文書から特定のテキストを持つ要素を探し出すためのものです。

この例では、あるp要素の中で”Ruby”というテキストを含む要素を取得します。

require 'nokogiri'
require 'open-uri'

url = 'https://www.example.com'
doc = Nokogiri::HTML(open(url))

element = doc.xpath('//p[contains(text(), "Ruby")]')
puts element.text

このコードでは、「//p[contains(text(), “Ruby”)]」というXPath式で、テキスト部分に”Ruby”という文字列を含むp要素を探します。

そして、その要素のテキストを出力します。

これにより、特定のテキストを持つ要素を効率的に探すことができます。

○サンプルコード9:XPathを使用して特定の属性を持つ要素を取得

次に、特定の属性を持つ要素を取得するためのサンプルコードを紹介します。

このコードでは、XPathの機能を用いてHTML要素の中からid属性を持つ要素を取り出します。

require 'nokogiri'
require 'open-uri'

url = 'https://www.example.com'
doc = Nokogiri::HTML(open(url))

element = doc.xpath('//*[@id]')
puts element.text

このコードでは、XPathの式’//*[@id]’を使って、id属性を持つすべての要素を選択しています。

そして、その要素のテキストを出力します。

このように、特定の属性を持つ要素を簡単に取得することが可能です。

○サンプルコード10:XPathを使用して特定の属性値を持つ要素を取得

特定の属性値を持つ要素を取得する場合はどうすれば良いでしょうか。

下記のコードでは、class属性の値が”important”という要素を取得します。

require 'nokogiri'
require 'open-uri'

url = 'https://www.example.com'
doc = Nokogiri::HTML(open(url))

element = doc.xpath('//*[@class="important"]')
puts element.text

このコードでは、「//*[@class=”important”]」というXPath式を使用して、class属性の値が”important”であるすべての要素を選択します。

そしてその要素のテキストを出力します。

特定の属性値を持つ要素を選択することで、更に精度高く情報を抽出することが可能です。

○サンプルコード11:XPathを使用して特定のタグを持つ要素を取得

さて、特定のタグを持つ要素を取得するためのコードは次の通りです。

この例では、すべてのh1タグを持つ要素を取得します。

require 'nokogiri'
require 'open-uri'

url = 'https://www.example.com'
doc = Nokogiri::HTML(open(url))

element = doc.xpath('//h1')
puts element.text

このコードでは、「//h1」というXPath式で、h1タグを持つすべての要素を取得します。

そして、その要素のテキストを出力します。

特定のタグを持つ要素を取得することで、ページの構造や意味を理解しやすい情報を効率的に抽出することができます。

○サンプルコード12:XPathを使用して要素の集合を取得

まず、要素の集合を取得する方法を見ていきましょう。

XPathは、ある条件に合致する複数の要素を一度に取得することが可能です。

この例では、すべてのリンク要素(aタグ)を取得します。

require 'nokogiri'
require 'open-uri'

url = 'https://www.example.com'
doc = Nokogiri::HTML(open(url))

elements = doc.xpath('//a')
elements.each do |element|
  puts element.text
end

このコードでは、「//a」というXPath式を用いて、aタグを持つすべての要素を選択します。

そして、それぞれの要素のテキストを出力します。

これにより、Webページ上のリンクテキストをすべて取得できます。

○サンプルコード13:XPathを使用して要素の範囲を取得

XPathを用いると、特定の範囲の要素を取得することも可能です。

下記のコードでは、リスト要素(liタグ)のうち、2番目から4番目までの要素を取得します。

require 'nokogiri'
require 'open-uri'

url = 'https://www.example.com'
doc = Nokogiri::HTML(open(url))

elements = doc.xpath('//li[position() >= 2 and position() <= 4]')
elements.each do |element|
  puts element.text
end

このコードでは、「//li[position() >= 2 and position() <= 4]」というXPath式を使用して、2番目から4番目までのliタグを持つ要素を選択します。

そして、それぞれの要素のテキストを出力します。

このように、XPathは特定の範囲の要素を取得することも容易に可能です。

○サンプルコード14:XPathを使用して特定の位置の要素を取得

次に、特定の位置にある要素を取得する方法を紹介します。

下記のコードでは、すべてのリスト要素(liタグ)の中から最後の1つを取得します。

require 'nokogiri'
require 'open-uri'

url = 'https://www.example.com'
doc = Nokogiri::HTML(open(url))

element = doc.xpath('//li[last()]')
puts element.text

このコードでは、「//li[last()]」というXPath式を使って、最後のliタグを持つ要素を選択します。

そしてその要素のテキストを出力します。

XPathを使えば、一覧の最初や最後の要素を直感的に取得することが可能です。

●XPathの発展的な利用方法

XPathを利用すると、HTML文書の特定の部分を効率的に取得できますが、さらに発展的な利用方法もあります。

例えば、特定の属性を持つ要素や特定のテキストを含む要素を取得することも可能です。次にその例を見てみましょう。

まず、特定の属性を持つ要素を取得するコードを紹介します。

下記のコードは、class属性が”important”であるdivタグを持つ要素をすべて取得します。

require 'nokogiri'
require 'open-uri'

url = 'https://www.example.com'
doc = Nokogiri::HTML(open(url))

elements = doc.xpath('//div[@class="important"]')
elements.each do |element|
  puts element.text
end

このコードでは、「//div[@class=”important”]」というXPath式を用いて、class属性が”important”であるdivタグを持つすべての要素を選択します。

そしてそれぞれの要素のテキストを出力します。

このように、特定の属性を持つ要素を選択することができます。

また、特定のテキストを含む要素を取得することも可能です。

下記のコードは、”特別なお知らせ”というテキストを含むh2タグを持つ要素を取得します。

require 'nokogiri'
require 'open-uri'

url = 'https://www.example.com'
doc = Nokogiri::HTML(open(url))

element = doc.xpath('//h2[contains(text(), "特別なお知らせ")]')
puts element.text

このコードでは、「//h2[contains(text(), “特別なお知らせ”)]」というXPath式を用いて、”特別なお知らせ”というテキストを含むh2タグを持つ要素を選択します。

そしてその要素のテキストを出力します。

このように、特定のテキストを含む要素を選択することもできます。

これらのコードを適切に利用することで、HTML文書から必要な情報をより効率的に取得することが可能になります。

しかし、一方で、スクレイピングには注意点もあります。

●RubyとXPathによるスクレイピングの注意点と対策

Webスクレイピングを行う際には、次のような注意点があります。

①Webサイトの利用規約

スクレイピングを行う前には、対象となるWebサイトの利用規約を必ず確認し、規約に反しない範囲で行うようにしましょう。

②負荷の問題

頻繁にスクレイピングを行うと、Webサイトのサーバーに大きな負荷をかける可能性があります。

負荷を軽減するためには、一定時間をおいてから次のスクレイピングを行うなど、適切な間隔を持つことが重要です。

③Webサイトの構造の変更

Webサイトの構造は、更新により変わることがあります。

そのため、スクレイピングのコードは定期的に見直し、必要に応じて更新する必要があります。

以上の注意点を踏まえ、次にスクレイピングのコードをカスタマイズする方法を見ていきましょう。

●RubyとXPathのカスタマイズ方法

RubyとXPathを使用したスクレイピングのコードは、自分の目的に合わせてカスタマイズすることができます。

まず、特定の要素の属性を取得する方法を見てみましょう。

下記のコードは、すべてのリンク要素(aタグ)のhref属性(リンク先のURL)を取得します。

require 'nokogiri'
require 'open-uri'

url = 'https://www.example.com'
doc = Nokogiri::HTML(open(url))

elements = doc.xpath('//a')
elements.each do |element|
  puts element['href']
end

このコードでは、「//a」というXPath式を用いて、aタグを持つすべての要素を選択します。

そしてそれぞれの要素のhref属性を出力します。

これにより、Webページ上のすべてのリンク先のURLを取得できます。

また、要素の内容を整形することも可能です。

下記のコードは、h1タグを持つ要素のテキストを取得し、それを大文字に変換します。

require 'nokogiri'
require 'open-uri'

url = 'https://www.example.com'
doc = Nokogiri::HTML(open(url))

element = doc.xpath('//h1')
puts element.text.upcase

このコードでは、「//h1」というXPath式を使って、h1タグを持つ要素を選択します。

そしてその要素のテキストを取得し、upcaseメソッドで大文字に変換した後出力します。

これにより、要素のテキストを任意の形式で出力することができます。

まとめ

今回の記事では、RubyとXPathを用いたWebスクレイピングについて詳しく解説しました。

基本的な使い方から発展的な手法まで、具体的なコードを用いて解説しました。

スクレイピングは情報収集の強力な手段ですが、注意点もあります。

また、自分の目的に合わせてコードをカスタマイズすることで、より効率的な情報収集が可能になります。

これからRubyとXPathを使ってスクレイピングを行う方は、ぜひこの記事を参考にしてください。

さまざまなテクニックを組み合わせて、自分だけのスクレイピングコードを作り上げてみてはいかがでしょうか。