Ruby Mechanize スクレイピングでよく使う設定やメソッドをクラス定義して使い回す


Overview - 概要

対象の gem でいつも決まって使用する設定たちや、
よく使うプロセスをオリジナルに定義したクラスでまとめて、リユースできるようにする。
今回は実際に仕事で必要になった Mechanize を例として使っています。

スクレイピングは、対象サイトごとに構造が違うので、コードを書き分けないといけませんが、
基本的なフローや動作はほとんど同じなので、可能な部分は再利用します。

ちょっと詰まりましたので、忘れないようにアウトプット!

Contents - 目次

  1. Intention - 目的
  2. Examples - 例
  3. References - 参考文献
  4. Postscript - あとがき
  5. Revision - 改訂
    2016/01/08 修正

1. Intention - 目的

Mechanize使用時に、いつも共通で行っている設定やよく使うメソッドを
専用クラスで定義して、使いまわせるようにする。

mechanize_config.rb

  require 'mechanize'

  agent = Mechanize.new
  agent.user_agent_alias = 'Windows Chrome'
  agent.ca_file = "../etc/cacert.pem"
  agent.keep_alive = false
  agent.max_history = 1
  agent.open_timeout = 60
  agent.read_timeout = 180

基本的に使用する上記の設定を専用に定義したクラスの initialize で実行する。
※注意:6行目 (agent. 3行目) の ca_file は、外部ファイルを指定しているので上記コードコピペでは使用不可。後日別投稿にて解説予定。

2. Examples - 例

失敗例から紹介しますね。
はじめは何も考えずに、さくっと以下のコードにしてしまったんですね。

mechanize_helper_mistake.rb

  require 'mechanize'

  class MechanizeHelper
    def initialize
      agent = Mechanize.new
      agent.user_agent_alias = 'Windows Chrome'
      agent.ca_file = "../etc/cacert.pem"
      agent.keep_alive = false
      agent.max_history = 1
      agent.open_timeout = 60
      agent.read_timeout = 180
      return agent
    end
  end

  # Call part
  agent = MechanizeHelper.new
  page = agent.get('http://www.foo.com/bar.htm')

HEY! 楽勝ですね! Let"s run!

gems/mechanize-2.7.4/lib/mechanize.rb:464:in `get': undefined method `fetch' for nil:NilClass (NoMethodError)
from mechanize_helper_mistake.rb:19:in `<main>'

OMG!

考えてみると、今までこういった使い方をするシーンに出会ったことがありませんでした。
きちんと調べて作りましょう! と調べまして、できましたのが以下のコードです。

mechanize_helper.rb

  require 'mechanize'

  class MechanizeHelper < Mechanize

    def initialize
      super
      self.user_agent_alias = 'Windows Chrome'
      self.ca_file = "cacert.pem"
      self.keep_alive = false
      self.max_history = 1
      self.open_timeout = 60
      self.read_timeout = 180
      return self
    end

  end

  agent = MechanizeHelper.new
  page = agent.get('http://www.foo.com/bar.htm')
  # => Success!

Tada! やりましたね!

私のケースでは設定値はほとんど変えることがないので、直接書き込んでいます。
しかし、外部ファイルに分けて読み込ませたり、呼び出しごとに引数を設定してもいいでしょう。
あとは他にも良く使うプロセスを考えて、メソッドとして追加していこうと思います。

3. References - 参考文献

Rubyのクラスメソッドとインスタンスメソッドの例
Atuhor : tbpgr様 2015/06/30
tbpgr様の投稿には、いつも助けられております。

今回は、上記を参考にさせていただきました。
ありがとうございました。THX!Pretty awesome!

4. Postscript - あとがき

最後までお読み頂き有難うございました。
間違いや改善点などございましたら、遠慮無くご指摘頂けましたら幸いです。
ご質問やそれ以外のコメントも歓迎です。

Posted by Alex Origin Post

5. Revision - 改訂

2016/01/08 修正

偉大なる little様よりご指摘を頂きまして修正いたしました。すみませんでした。

誤でも、動くは動きますが、ユーザーエージェントなど反映されません。
ユーザーエージェント表示ページを取得して、確認済みです。

mechanize_helper.rb

  require 'mechanize'

  class MechanizeHelper < Mechanize

    def initialize
      super
      self.user_agent_alias = 'Windows Chrome'
      self.ca_file = "cacert.pem"
      self.keep_alive = false
      self.max_history = 1
      self.open_timeout = 60
      self.read_timeout = 180
      return self
    end

  end

mechanize_helper.rb

  require 'mechanize'

  class MechanizeHelper < Mechanize

    def self.initialize
      user_agent_alias = 'Windows Chrome'
      ca_file = "cacert.pem"
      keep_alive = false
      max_history = 1
      open_timeout = 60
      read_timeout = 180
    end

  end