yhara.jp

Recent Posts

RubyでWebスクレイピング

Tech

MechanizeとNokogiriの使い方について書きます。mechanize 2.7.6, 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です。

準備

  • Ruby
  • gem install mechanize

Mechanizeを使う

require 'mechanize'

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

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

# Nokogiriを使った操作
page.search("img") #=> imgタグの一覧
page.at("img") #=> 最初のimgタグを取得 (.search("img")[0] と同じ)

Mechanize::Formの使い方

Mechanize::Formオブジェクトは例えばform = page.forms.first のようにして取得できます。

form.keysで、nameの一覧を調べることができます。例えば以下のようなフォームがあったとすると:

  <form action="POST">
    ユーザ名:<input type="text" name="user"><br>
    パスワード:<input type="password" name="pass"><br>
  </form>

form.keys["user", "pass"]のようになります。この場合以下のようにしてフォームを送信できます。

form["user"] = "taro"
form["pass"] = "passw0rd"
form.submit
# new_page = form.submit  # 送信後のページもほしい場合はこうする

ログイン後は同じagentオブジェクトでagent.get等するとログインした状態でページを取得できます。

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タグに変える

上級編:Cookieを保存する

agent.cookie_jar.save('./cookies.yaml')  #=> cookies.yamlというファイルにCookieを保存する
agent.cookie_jar.load('./cookies.yaml')  #=> saveしたCookieを読み込む

デフォルトではセッションCookie(expire指定がなく、ブラウザを閉じたら消える想定のCookie)は保存されませんが、session: trueを付けると保存されるようになります。

agent.cookie_jar.save('./cookies.yaml', session: true)
agent.cookie_jar.load('./cookies.yaml', session: true)

More posts

Posts

(more...)

Articles

(more...)

Category

Ads

About

About the author