近&況

Recent Posts
Edit

RubyでWebスクレイピング

MechanizeとNokogiriの使い方について書きます。mechanize 2.7.5, nokogiri 1.6.8.1をベースにしています。

概要

Mechanizeでできること

MechanizeはRubyからWebページにアクセスするためのライブラリです。あるWebサイトのHTMLを取ってきたり、そこからリンクされている画像ファイルをダウンロードなどができます。

Nokogiriでできること

NokogiriはHTMLファイル・XMLファイルをRubyで解析するためのライブラリです。Mechanizeの一部の機能はNokogiriを利用して実装されているため、MechanizeをインストールするとNokogiriも自動的にインストールされますが、gem install nokogiriのようにすればNokogiriだけをインストールすることもできます。HTMLファイルがすでにダウンロードしてある場合はNokogiriだけあればOKです。

準備

Mechanizeを使う

require 'mechanize'

agent = Mechanize.new
page = agent.get("https://google.com")

page.links  #=> Mechanize::Page::Linkの一覧
page.forms #=> Mechanize::Formの一覧
page.body #=> HTML文字列

page.root #=> Nokogiriのオブジェクト
page.root.search("img") #=> imgタグの一覧

Nokogiriを使う

require 'nokogiri'
doc = Nokogiri::HTML.parse(File.read("a.html"))

p doc.search("img")  #=> imgタグの配列
p doc.at("img")  #=> 最初のimgタグ
p doc.at("img.photo")  #=> CSSセレクタも書けます

タグに対する操作

span = doc.at("span")
span.text  #=> 中身を文字列で返す
span.to_html  #=> spanタグ全体をHTML文字列として返す

a = doc.at("a")
a["href"]  #=> aタグのhref属性の値を文字列で返す

CSSセレクタ

doc.search("img.news")  # 「class="news"」が付いたimgタグの一覧
doc.search("img#news")  # 「id="news"」が付いたimgタグの一覧

doc.search("table a")  # tableタグ内にあるaタグの一覧

doc.search("table tr:first-child td") # tableの最初のtrにあるtdタグ
doc.search("table tr:nth-child(3) td") # tableの3番目のtrにあるtdタグ
doc.search("table tr:nth-last-child(3) td") # tableの「後ろから3番目」のtrにあるtdタグ
doc.search("table tr:last-child td") # tableの最後のtrにあるtdタグ

doc.search("a[href^='/gallery/']")  # hrefが「/gallery/」から始まるaタグの一覧
doc.search("a[href$='.xml']")  # hrefが「.xml」で終わるaタグの一覧
doc.search("a[href*='new']")  # hrefに「new」が含まれるaタグの一覧

周囲のタグを取得

td = doc.at("td")
td.parent  #=> 親要素
td.children #=> 子要素の一覧
td.next #=>次の兄弟要素
td.previous #=> 前の兄弟要素

上級編:エイリアス

searchメソッドは「/」にエイリアスされています。atメソッドは「%」にエイリアスされています。これらを使うとより短く書けます(読みにくくなるかもしれませんが)。

p doc / :td   # doc.search("td")と同じ
p doc % :img  # doc.at("img")と同じ

例えば「テーブルの各行の最後のtd」は以下のように書けます。

table = doc % :table
(table/:tr).each do |tr|
  p (tr/:td).last
end

上級編:内容の書き換え

NokogiriはHTMLを解析するだけでなく、書き換えることもできます。書き換えたあとは、to_htmlメソッドで新しいHTML文字列を取得できます。

div = doc.at("div")
div["class"] = "button new"   # 属性値を書き換える
puts doc.to_html  #=> 書き換え後のHTML 

div.content = "..."  # 中身のテキストを置き換える

div.remove # タグを削除する

div.name = "span"  # divタグからspanタグに変える