![]() |
Ruby 逆引きレシピ すぐに美味しいサンプル&テクニック 232 (PROGRAMMER’S RECIPE) 島田 浩二 設樂 洋爾 村田 賢太 前田 智樹 谷口 文威 翔泳社 2009-07-25 by G-Tools |
これは Ruby逆引きレシピAdvent Calendar の参加エントリです。12月17日を担当します。前日の担当は @y_ogagaga さんで iCalendar形式のデータを読み書きしたいでした。
職場とか学校で、Rubyに詳しい頼りになる先輩がいるっていうのは、こんな感じなんじゃなかろーかと想像する。「こういうことしたいんですけど?」と聞いてみると「ああ、これでできるよ」と一瞬で返ってくるような。
レシピ先輩(仮称)はいろいろなライブラリを知ってる。だから第1章の1.1に書いてあるのはRubyのコードの書き方じゃあなくて、有無をいわさずrubygemsをインストールして使う、ということだ。レシピ先輩はIRCをばりばり使う。だから第6章 ネットワーク処理のはじめは、ウェブじゃなくってIRC BOTのつくりかただ。レシピ先輩はいろいろなコミュニティに参加している。だから最後の第24章で伝えるのはコミュニティに参加する方法だ。
レシピ先輩の魂のライムに酔いしれろー!!
Web ページを取得して解析したい / Web サイトから情報を抽出したい
今回は、惚れさすレシピ124「Web ページを取得して解析したい」と、惚れさすレシピ152「Web サイトから情報を抽出したい」を参考にして、お手軽な画像ダウンローダを作ってみます。正義の味方たこ焼き仮面が作ってくれた Nokogiri を使えば、とっても簡単に Web から情報を抜き出せちゃいます。
Web Scraping
Web Scraping、つまり「Web ページからの情報抽出」の手順は、ざっと以下の通りです。これは、Web API などの正面玄関がない場合を想定しています。玄関がある場合は、お行儀よく玄関から入りましょう。その方が楽ですし、Web ページの中の人にも迷惑を掛けません。
- ターゲットを決める
- 所望の情報が記載されている Web ページを探す
- 対象の Web サイトのソースを見て、HTML 構造とにらめっこする
- 対象の Web サイトにアクセスして、所望の情報を抜き出すプログラムを書く
- ページングやエラー処理等の処理を追加し、プログラムを仕上げる
- プログラムを動かす
惚れさせ画像ダウンローダ
地獄のミサワの「女に惚れさす名言集」のすべての惚れさせ画像をダウンロードするプログラムを書きました。
# -*- coding: utf-8 -*- | |
require "open-uri" | |
require "rubygems" | |
require "nokogiri" | |
module Jigokuno | |
URL = "http://jigokuno.com/" | |
NEXT_XPATH = "//div[@id='page_area']/div[@class='page_navi']/a[contains(text(), '>>')]" | |
class Misawa | |
include Enumerable | |
attr_reader :current | |
def initialize | |
@current = URL | |
@document = Nokogiri::HTML(open(@current)) | |
end | |
def next | |
next_link = @document.at(NEXT_XPATH) | |
return nil if next_link.nil? | |
@current = next_link["href"] | |
@document = Nokogiri::HTML(open(@current)) | |
self | |
end | |
def each | |
Scraper.new(@document).meigens { |meigen| yield meigen } | |
next_page = self.next | |
return if next_page.nil? | |
next_page.each { |meigen| yield meigen } | |
end | |
end | |
class Scraper | |
def initialize(html) | |
@html = html | |
end | |
def meigens | |
@html.xpath("//div[@class='entry_area']").each { |entry| | |
h2 = entry.xpath("h2").text.tr("0-9", "0-9").chomp | |
id, title = h2.scan(/惚れさせ(\d+).*「(.+)」/).first | |
id = id.to_i | |
title = title.to_s | |
image = entry.at(".//img[@class='pict']").attributes["src"].to_s | |
character = entry.at("center/ul/li[2]/a").text | |
yield Meigen.new(id, title, character, image) | |
} | |
end | |
end | |
class Meigen | |
attr_reader :id, :title, :character, :image | |
def initialize(id, title, character, image) | |
@id = id | |
@title = title | |
@character = character | |
@image = image | |
end | |
def to_s | |
"%03d_%s_%s" % [@id, @title, @character] | |
end | |
end | |
end |
images = "images" | |
Dir.mkdir images unless File.exist? images | |
horesasu = Jigokuno::Misawa.new | |
horesasu.each { |meigen| | |
open("%s/%s.gif" % [images, meigen], "w") { |gif| | |
gif.puts open(meigen.image).read | |
} | |
sleep 5 | |
} |
horesasu の each で meigen を新しいものから順番に渡してくれるので、それに対する処理をブロックで与えてやるとよいです。今回はダウンローダなので、ファイルとして保存する処理を書きました。
えっ、なんか今日のエントリはいつもと違うって?ふふふ… 今までタイピングしていた手は、利き腕ではない。
惚れさせを、いつも側に
すべての惚れさせ名言が、あなたの手元に届きました。
ファイル名にタイトルとキャラクター名を含めてあるので、検索できて便利です。
おおっと… コードとブログを書いているとすぐに時間が過ぎちゃうな。僕が今シャブやってるからっていうのもあるけどね。
わかってんのかよ
さて!「500枚近くの画像をダウンロードしたいんだけど、とても手作業じゃあ無理だなあ。どうすれば…」そんな日常のちょっと困った場面で、惚れさすレシピ集はとっても心強い1冊です。まるで、身近にいる頼りになる先輩みたいに、あなたを助けてくれることでしょう。試しにRuby逆引きレシピ レシピ一覧をご覧なさいな。お品書きの充実っぷりに驚くこと間違いなしです。
Ruby逆引きレシピに載っているレシピを利用して、何かちょっとしたプログラムを作ってみてAmazonのRuby逆引きレシピのページにレビューを投稿するというイベントです。
そうそう、プログラムを書いて、ブログを書いて、レビューを書くまでがこの企画でしたね。今からレビューを書いてきます!Ruby逆引きレシピAdvent Calendar の明日の担当は mikeneck さんです!
おまけ
惚れさせレシピ225に、実はあたしも出演しています。お手元のレシピ本をどうぞご確認ください。
まずいな〜!睡眠時間を削ってこんなエントリを書いてるのバレたら、心配されちゃってまずいな〜!