読者です 読者をやめる 読者になる 読者になる

Think Big Act Local

iPhone開発を軸にブレブレの記事を書いていきます。

サイトのスクレイピングを自動化する

以前のエントリで、RubyのNokogiriライブラリを使ったスクレイピングのやり方を紹介しました。
RubyのNokogiriを使ってサイトをスクレイピングする

しかし、前回の方法では$ ruby scrape.rb http://eiga.com/movie/55975/ という様に一つひとつURLを指定しなければならず不便です。

そこで今回は前回のコードを拡張し、スクレイピングの自動化に挑戦します。

考え方

「自動化」というと難しい気がしますが、スクレイピングするURL(http://eiga.com/movie/55975/)の内、映画のidにあたる55975の部分を順に変化させていくことを今回のゴールとします。

ステップとしては2つで、

  • 前回のコードを拡張し、存在しないURLへのアクセス時のエラー対応を実装
  • 1のコードを別スクリプトから呼び出す

という流れになるかと思います。

1. 前回のコードを拡張する

前回のコードについては、前回記事のscrape.rbを参考にしてください。
これを、以下のように拡張しました。

scrape_status.rb

# -- coding: utf-8

require "open-uri"
require "rubygems"
require "nokogiri"

# url = "http://eiga.com/movie/55975/"

url = ARGV[0]
charset = nil
http_status_code = 0
html = open(url) do |f|
  charset = f.charset
  f.read
end

doc = Nokogiri::HTML.parse(html, nil, charset)
p doc.title
if doc.title == "作品情報 - 映画.com"
  p "No Match Movie"
  exit()
end

doc.xpath('//div[@class="moveInfoBox"]').each do |node|
  #title
  p node.xpath('h2').text

  #released_at
  p node.xpath('span[@class="opn_date"]/strong').text

  #releaset_at (YYYY-MM-DD)
  p node.xpath('span[@class="opn_date"]/strong').attribute("content").value

  #image_url
  p node.xpath('//div[@class="pictBox"]/a/img[@class="main"]').attribute("src").value

  #thumbs
  thumbs = node.xpath('//p[@class="thumBox"]/a')
  p thumbs.size
  thumbs.each do |thumb|
      p thumb.xpath('img').attribute('src').value
  end

  #description
  p node.xpath('div[@class="outline"]').text

  #staff
  staffs = node.xpath('div[@class="staffcast"]/div[@class="staffBox"]/dl/dd/a')
  staffs.each do |staff|
    p staff.text
  end

  #casts
  casts = node.xpath('div[@class="staffcast"]/div[@class="castBox"]/ul/li/span/a')
  casts.each do |cast|
    p cast.text
  end

変更した点

変更した点は1ヵ所のみです。

// タイトルで判断する
if doc.title == "作品情報 - 映画.com"
  p "No Match Movie"
  exit()
end

存在しない映画IDをリクエストした時にはhttp://eiga.com/movie/にリダイレクトされるため、そのリダイレクト先ページのタイトルと同じかどうかで判断しています。
(もっとうまく書ける方法があると思います)

では、ここまでのコードを実行してみましょう。

実行結果(成功時)

$ ruby scrape_status.rb http://eiga.com/movie/57265/
"シュガー・ラッシュ : 作品情報 - 映画.com"
"シュガー・ラッシュ"
"2013年3月23日"
(中略)
"多田野曜平"

実行結果(映画ID見当たらなかった場合)

$ ruby scrape_status.rb http://eiga.com/movie/11111/
"作品情報 - 映画.com"
"No Match Movie"

動作確認はOKのようです。これでエラー対応版のスクレイピングが出来ました。

2. 1のコードを別スクリプトから呼び出す

ここはそんなに難しくないと思うので、ソースを貼るに留めます。

multi_scrape.rb

(77268..77273).each do |i|
  code = "ruby scrape.rb http://eiga.com/movie/#{i}/"
  system(code)
  p "----"
end

77268から77273までの映画IDのページを順番にスクレイピング
system(code) を使って別のファイルに書かれたスクリプトを実行しています。

実行結果

$ ruby multi_scrape.rb 
"よみがえりのレシピ : 作品情報 - 映画.com"
"よみがえりのレシピ"
(中略)
"----"
"リアル 完全なる首長竜の日 : 作品情報 - 映画.com"
"リアル 完全なる首長竜の日"
(中略)
"----"
"ひとりかくれんぼ 劇場版 真・都市伝説 : 作品情報 - 映画.com"
"ひとりかくれんぼ 劇場版 真・都市伝説"
(中略)
"----"
"武蔵野線の姉妹 : 作品情報 - 映画.com"
"武蔵野線の姉妹"
(中略)
"----"
"フタバから遠く離れて : 作品情報 - 映画.com"
"フタバから遠く離れて"
(中略)
"----"
"ふとめの国のありす : 作品情報 - 映画.com"
"ふとめの国のありす"
(中略)
"----"

順番にスクレイピング処理をかけることができました。
今回は(77268..77273) と範囲指定しましたが、 (10000..99999) 等とすれば全ての映画についてスクレイピングすることも可能です。
(※映画.comさんに負荷をかけてしまうので良い子のみなさんはやらないで下さいね!)

以上で、スクレイピングの自動化ができました。

ソースコード

その他

  • スクレイピングは著作権等の問題もあるので気をつけましょう
  • 負荷の話もあるので、過度なアクセスは控えましょう
  • スクレイピング先のソースの構成が変わったら苦しみましょう

おすすめ本

たのしいRuby 第3版

たのしいRuby 第3版

広告を非表示にする