サイトのスクレイピングを自動化する
以前のエントリで、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さんに負荷をかけてしまうので良い子のみなさんはやらないで下さいね!)
以上で、スクレイピングの自動化ができました。