inuinu blog(開発用)

BOT @wagagun の開発ノウハウや、IT向け?の雑記ブログです。

【Ruby】HTMLのTABLEの中身をスクレイピングする(Nokogiri編)

この記事では、RubyのNokogiri+CSSセレクタによるスクレイピングについて、TABLE(TD)タグを例に解説します。

Rubyでは、Nokogiri+CSSセレクタで簡単にスクレイピングすることが出来ます。
TABLE(TD)タグを例に解説します。

さて、今回はCSSセレクタを使用したスクレイピングです。

HTMLの中身を抜き出すことは可能でしょうか?
抜き出したいのはTABLEタグの中身です。

なるほど。
Rubyを使って、軽く作ってみましょう。

inuinu-tech.hatenablog.jp

簡単なのはRubyならNokogiri+cssセレクタ

下記はRubyの、Nokogiri+cssセレクタで、テキストを抽出する例です。

参考ソース

●test_nokogiri_table.rb

require 'nokogiri'
require 'open-uri'

src_url = "任意のURL"

html = open(src_url).read

doc = Nokogiri::HTML.parse(html)

table = doc.css('table') # 複数取得

table.each_with_index do |tb, ib|
  puts "●テーブル#{ib+1}個目"

  table_data = [] # この段階ではまだ1次元配列

  tb.css('tr:has(td)').each_with_index do |tr, ir|
    table_data[ir] = [] # 配列の要素単位に配列を作成する(二次元化)

    tr.css('td').each_with_index do |td, id|
      table_data[ir][id] = td.text.strip
    end
  end

  pp table_data

end

実行

ruby test_nokogiri_table.rb

解説

参考ソースではopen-uriを使いましたが、Mechanize等でもOKです。
私の実行環境ではhttpsでも行けました。

Nokogiriであれば、CSSセレクタを使用して、簡単にスクレイピングできます。
CSSセレクタとは、CSSの文法を流用することにより、HTMLの中の特定の情報を取得することができる仕組みです。
HTMLエンジニアやWebデザイナーなら、一度はChromeでF12からElementsタブをクリックして、「div.hoge」や「#foo」などで特定のclassやidなどの値の変化や、表示の挙動を調べたことがありますよね?
アレがこれです。

ループを3重(TABLE、TR、TD)にして、2次元配列(TR、TD)にセットしています。

Rubyは他の言語と異なり、空の2次元配列の枠だけを一気に定義できないので、ループしながら2次元目を定義する必要があります。
Ruby独特の記述方法はそれくらいでしょうか。

doc.css('table')だと複数のTABLEタグを持ってきます。
今回はループして全部のテーブルを取得するケースですが、殆どのニーズは特定のテーブルのみを持ってきたいでしょうから、TABLE配列の特定の要素(0から始まるので注意)からTR、TDのみのループに変更して使用してみてください。
(なので、2次元配列(TR、TD)にしています。)

tb.css('tr:has(td)')で、TDタグで構成されているTRタグをセレクトします。
よって、上記例ではTHタグの行は取得しません。
単にデータだけ欲しい場合はいらないでしょうし。CSV化したい場合でも、ヘッダー表は自分で作ったほうが良いと思います。

td.textはinnerTextなので、ボールドやイタリックやspanといった装飾タグは除去されます。
stripは他の言語で言うところのtrim()です。Nokogiriでは付けなくても良かったかもしれませんが、念のため。

出来上がった2次元配列は?

スクレーピングした情報は、多くの場合、DB等にストックし、何らかの再利用を行うと思います。

まず、数値の場合はカンマ区切りのまま取得していますので、除去しないと、INSERT/UPDATE時にエラーとなるでしょう。

また、DBのカラムがDECIMAL属性で、桁数チェックが必要になる場合があれば、チェックして、エラーがあれば、DBを改善するなりしたほうが良いかと思います。
VARCHARの場合は文字数あるいはバイト数チェックでしょうか。文字数チェックで済ませれば楽でしょうね。
(Rubyサロゲートペア対応していますので、可能な限り、サロゲートペアに対応しているDBを選択してください。)

最後に

他の言語をお使いの場合は、適宜移植してみてください。
(Nokogiriのようなものがあればいいですね。)

そんなパッケージは無いよ…といった場合は、下記の関連記事も参照ください。

inuinu-tech.hatenablog.jp

それでは、また。