最終更新:
kitamomonga 2010年10月06日(水) 18:03:39履歴
サーバにアクセスするための「Web ブラウザ」を表現するクラスです。このクラスのオブジェクトを操作してウェブにアクセスします。
require 'rubygems' require 'mechanize' require 'kconv' # アクセスのためのオブジェクトを作成 agent = Mechanize.new # Rubyの日本語サイトのトップページ uri = URI.parse('http://www.ruby-lang.org/ja/') # uri にアクセスしてページを取得 agent.get(uri) # 「現在のページ」のHTML上で "ダウンロード" なリンクを「クリック」してアクセスし内容取得 agent.page.link_with(:text => "ダウンロード".toutf8).click # リンクをクリックした結果のページのURIを表示 puts agent.page.uri
結果: http://www.ruby-lang.org/ja/downloads/
Mechanize オブジェクト(インスタンス)の生成は Mechanize.new で行います。引数は特にありません。変数名は agent が一般的です。
agent = Mechanize.new
#get メソッドで URL が表すページを取得することができます。
agent.get(uri)取得したページのオブジェクトは HTML なら Mechanize::Page に、HTML 以外なら Mechanize::File になります。ページ内のリンクやフォームを操作し、リンククリックやフォーム送信をすることもできます。Mechanize::Page#link_with や Mechanize::Page#form_with を参照してください。
#page メソッドは「Mechanize が最後に取得した最新のページ」を返します。#get や Mechanize::Page::Link#click などで更新されます。
agent.get(url1) agent.page # url1のページが返る agent.page.link_with(:text => "ダウンロード".toutf8).click agent.page # "ダウンロード" なリンクをクリックした結果取得したページが返る
ユーザーエージェント文字列を既存のブラウザ名で偽装したい場合は #user_agent_alias= メソッドを、アクセス時のログを設定したい場合は #log= メソッドを使用します。
agent.user_agent_alias = 'Windows IE 7' require 'logger' agent.log = Logger.new('mechlog.txt')
最新ページではなく過去にアクセスしたページを URL で指定して呼び出したい場合は #visited_page が利用できます。
agent.get(url1) agent.get(url2) agent.get(url3) agent.visited_page(url2)... # url2 のページが返る
- VERSION - Mechanize のバージョンを表す文字列
- AGENT_ALIASES - ユーザーエージェント指定用のキーワードと値の Hash
- html_parser= - Mechanize クラスで使用する HTML パーサのクラスを変更する
- html_parser - Mechanize クラスで使用する HTML パーサのクラスを返す
- log= - Mechanize クラスで使用するログ出力クラスのオブジェクトを指定する
- log - Mechanize クラスで使用するログ出力クラスのオブジェクトを返す
- new - Mechanize オブジェクトを生成する
- open_timeout= - Net::HTTP の接続タイムアウトの秒数の設定
- open_timeout - ユーザーが設定した接続タイムアウトの秒数を返す
- read_timeout= - Net::HTTP の読み込みタイムアウトの秒数の設定
- read_timeout - ユーザーが設定した読み込みタイムアウトの秒数を返す
- user_agent= - サーバへ送る User-Agent リクエストヘッダの値を自力で設定する
- user_agent - サーバへ送る User-Agent リクエストヘッダの値を返す
- watch_for_set - REXML 用の何か
- watch_for_set= - REXML 用の何かを設定
- ca_file= - SSL 認証用の CA certification ファイルパスを指定
- ca_file - SSL 認証用の CA certification ファイルパスを返す
- key= - SSL 認証用の RSA 公開鍵ファイルのパスを指定
- key - SSL 認証用の RSA 公開鍵ファイルのパスを返す
- cert= - SSL 認証用の OpenSSL::X509::Certificate に使用するファイルのパスを指定
- cert - SSL 認証用の OpenSSL::X509::Certificate に使用するファイルのパスを返す
- pass= - SSL 認証用の RSA 公開鍵のパスフレーズを指定
- pass - SSL 認証用の RSA 公開鍵のパスフレーズを返す
- redirect_ok= - Location レスポンスヘッダのリダイレクトに追随するかどうかを真偽で指定
- redirect_ok - Location レスポンスヘッダのリダイレクトに追随するかどうかを真偽で返す
- gzip_enabled= - リクエストヘッダの Accept-Encoding に gzip を追加するかどうかを真偽で指定
- gzip_enabled - リクエストヘッダの Accept-Encoding に gzip を追加するかどうかを真偽で返す
- keep_alive_time= - リクエストヘッダの Keep-Alive に指定する秒数を指定
- keep_alive_time - リクエストヘッダの Keep-Alive に指定する秒数を返す
- keep_alive= - リクエストヘッダに keep-alive 関連を含ませるかどうかを真偽で指定
- keep_alive - リクエストヘッダに keep-alive 関連を含ませるかどうかを真偽で返す
- conditional_requests= - 304 Not Modified への対応を真偽で指定
- conditional_requests - 304 Not Modified への対応を真偽で返す
- follow_meta_refresh= - meta タグの refresh に追随するかどうかを真偽で指定
- follow_meta_refresh - meta タグの refresh に追随するかどうかを真偽で返す
- verify_callback= - Net::HTTPS#verify_callback に渡す Proc オブジェクトを指定
- verify_callback - Net::HTTPS#verify_callback に渡す Proc オブジェクトを返す
- history_added= - ページオブジェクトが返る直前に実行させたい Proc オブジェクトを指定
- history_added - history_added= で指定した Proc オブジェクトを返す
- scheme_handlers= - scheme_handler の Hash を上書きする
- scheme_handlers - URL スキームごとの URL 処理を追加する
- redirection_limit= - Location リダイレクトの連続追随回数を指定
- redirection_limit - Location リダイレクトの連続追随回数設定を返す
- request_headers= - 全てのリクエストヘッダに追加するヘッダを Hash で指定
- request_headers - 全てのリクエストヘッダに追加するヘッダを Hash で返す
- proxy_addr - プロキシのアドレスを返す
- proxy_pass - プロキシのパスワードを返す
- proxy_port - プロキシのポートを返す
- proxy_user - プロキシのユーザー名を返す
- html_parser= - Mechanize オブジェクトで使用する HTML パーサのクラスを指定
- html_parser - Mechanize オブジェクトで使用する HTML パーサのクラスを返す
- pluggable_parser - Content-Type ごとに Mechanize が行う処理を指定
- follow_redirect? - alias #redirect_ok
- max_history= - アクセス履歴兼キャッシュの最大保持数を整数で指定
- max_history - アクセス履歴兼キャッシュの最大保持数を整数で返す
- log= - Mechanize クラスで使用するログ出力クラスのオブジェクトを指定する
- log - Mechanize クラスが使用するログ出力クラスのオブジェクトを返す
- pre_connect_hooks - サーバ接続直前に行いたい Proc オブジェクトを登録
- post_connect_hooks - サーバからファイルを取得した直後に行いたい Proc オブジェクトを登録
- set_proxy - アクセス用のプロキシを設定
- user_agent_alias= - ユーザーエージェントを略記で指定して詐称
- cookies - クッキー一覧を返す
- auth - Basic 認証や Digest 認証に使用するデータを設定
- basic_auth - alias #auth
- cookie_jar - クッキー管理クラスのオブジェクトを返す
- cookie_jar= - クッキー管理クラスのオブジェクトを再代入する
- get_file - url を GET で取得して履歴に登録し、body 部だけを返す
- click - 引数のリンクをクリックしたとみなしてアクセスして履歴に登録し、返す
- back - 最新のページを実際に削除して履歴を詰める
- current_page - 履歴で最新のページ(最後に取得した「現在のページ」)を返す
- visited? - URL が履歴に存在するかどうかを真偽で返す
- visited_page - 履歴から該当 URL のページを取り出して返す
- transact - ブロック終了時にブロック前の履歴を書き戻す
- page - alias #current_page
- history - アクセス履歴オブジェクトを返す
- get - 引数の URL に GET でアクセスして結果を履歴に登録してから返す
- put - 引数の URL に PUT でアクセスして結果を履歴に登録してから返す
- delete - 引数の URL に DELETE でアクセスして結果を履歴に登録してから返す
- head - 引数の URL に HEAD でアクセスして結果を履歴に登録せずに返す
- post - 引数の URL へ POST でデータを送信し結果を履歴に登録して返す
- submit - フォームを送信してサーバからの返答を返す
- request_with_entity - エンティティ文字列を指定したHTTP送信メソッドで送り、結果を履歴に保存してから返す
- fetch_page - 実際に Net::HTTP でアクセスして値を返す
Mechanize のバージョンを表す文字列を返します。
irb> p Mechanize::Version "1.0.0"
クラスから生成されるオブジェクトで使用する HTML パーサのクラスを返す Mechanize.html_parser メソッドの返り値を変更します。
require 'hpricot' Mechanize.html_parser = Hpricot agent = Mechanize.new p agent.html_parser #=> Hpricot今後生成されるすべての Mechanize オブジェクトのパーサが変更されます(既に存在する Mechanize オブジェクトのパーサはそのままです)。
require 'hpricot' old_agent = Mechanize.new Mechanize.html_parser = Hpricot new_agent = Mechanize.new p old_agent.html_parser #=> Nokogiri::HTML p new_agent.html_parser #=> Hpricot
引数 html_parser は Nokogiri::HTML または Hpricot と互換の HTML パース動作をする HTML パーサのクラスオブジェクトであればなんでも構いません。
インスタンスメソッドの #html_parser= で指定することで、Mechanize オブジェクトごとにパーサを切り替えることもできます。
Mechanize クラスで生成されるオブジェクトで使用する HTML パーサのクラスを返します。
p Mechanize.html_parser #=> Nokogiri::HTMLデフォルトは Nokogiri::HTML です。
Mechanize オブジェクトは、生成されるたびにこのメソッドの返り値を #html_parser の値に複製します。生成された Mechanize オブジェクトの #html_parser= で別のクラスが指定された場合でも、このメソッドの返り値は不変です。
変更は Mechanize.html_parser= で行います。
デフォルトのログ出力クラスのオブジェクトを返す Mechanize.log メソッドの返り値を設定します。
require 'loger' Mechanize.log = Logger.new('mechlog.txt')設定を行わなかった場合はログ出力は行われません。設定後にログ出力を止めたい場合は nil を指定します。
標準添付の Logger ライブラリと互換の動作をするログ出力クラスを指定してください。設定されたログ出力クラスオブジェクトは Mechanize.log で参照できます。
#log= はこのメソッドを呼んでいます。Mechanize オブジェクト単位でログ出力を切り替えることはできません。
Mechanize クラスで生成されるオブジェクトで使用するログ出力クラスのオブジェクトを返します。
require 'loger' Mechanize.log = Logger.new('mechlog.txt') Mechanize.log.level = Logger::INFO ... Mechanize.log.info('login failed') if Mechanize.logデフォルトは nil で、ログ出力は行われません。指定は Mechanize.log= で行います。
生成された Mechanize オブジェクトのインスタンスメソッド #log= で別のクラスが指定された場合、クラスメソッドであるこのメソッドの返り値も変更されてしまいます。Mechanize オブジェクト単位でログ出力を切り替えることは、Mechanize 1.0.0 の時点ではできません。
Mechanize オブジェクトを生成し、それを返します。
ブロックがある場合は self が渡され、ブロック内で評価された self がそのまま返ります。
# 以下の 2つは同じ動作 agent = Mechanize.new{|a| a.user_agent_alias = 'Windows IE 7' } agent = Mechanize.new agent.user_agent_alias = 'Windows IE 7'
IO オブジェクトの open(path){...} のような、ブロック終了時に「必ず実行されるべき処理」が設定されているというようなことはないので、ブロックを使わなくても特に問題はありません。
内部で使用される Net::HTTP#open_timeout の秒数を Integer で設定します。
agent.open_timeout = 5 # 5sec
設定を行わなかった場合の内部値は nil で、TCPSocket.open が利用している C ライブラリの接続タイムアウトを待ちます。なお、TCPSocket.open を timeout(sec){ ... } で包んでいるだけなので、DNS 解決(gethostbyname)などのタイムアウトを制御することはできません。
DNS 解決のタイムアウトを制御したい場合は Ruby 実装を使用させるために require 'resolv-replace' した上で open_timeout= を設定してください。
resolv-replace 下でタイムアウトを迎えた場合は Ruby 標準の例外 Timeout::Error が発生します。open timeout と read timeout を発生する例外で区別することはできません。$!.backtrace を正規表現でマッチさせるなどの小細工が必要になります。
... require 'resolv-replace' ... agent.open_timeout = 3 agent.read_timeout = 10 begin agent.get(uri) rescue TimeoutError => ex case ex.backtrace when /protocol.rb/ warn "read timenout: 処理サーバが落ちてます" else warn "open timenout: 回線が抜けてるかDNSエラーです" end end end
DNS は引けるしリクエストも送れるがサーバからの返事が来ない、という時のタイムアウトの設定は #read_timeout= で行います。
内部で使用される Net::HTTP#read_timeout の秒数を Integer で設定します。
agent.read_timeout = 5 # 5sec設定を行わなかった場合の内部値は 60 で、リクエスト送信後 60 秒以内にサーバからレスポンスがない場合は Ruby 標準の例外 Timeout::Error を発生させます。
そもそもサーバが見つからないときのタイムアウトを設定したい、という場合は #open_timeout= を参照してください。
サーバアクセス時に User-Agent リクエストヘッダで送信される値を文字列で設定します。
# 悪用されまくったWebスクレイピングライブラリの末路、またはMechanizeの将来 require 'rubygems' require 'mechanize' agent = Mechanize.new agent.user_agent = 'libwww-perl' agent.get('http://www.google.com/search?q=ruby')結果:
Mechanize::ResponseCodeError: 403 => Net::HTTPForbidden
設定を行わなかった場合、#user_agent_alias= で設定されていた場合はそのユーザーエージェント文字列が、エイリアスがない場合は "WWW-Mechanize/バージョン (http://rubyforge.org/projects/mechanize/)" となります。
ユーザーエージェントとして不正不当な値でもチェックは行われず、そのまま送信されます。
ユーザーエージェントの書式(詳しくは RFC2616 の 3.8 Product Tokens と 2.2 Basic Rules を参照)
製品名1/バージョン 製品名2/バージョン 製品名3 (コメント) という形式で、製品名は何個でもよい バージョンは / で区切り、バージョンはなくてもよく、記述は空白で区切る agent.user_agent = 'WonderfulGreatExcellentTractor/1.12 Ruby/1.8.7 (http://example.com/wget)' 製品名部分は"固定"であるべき、変更されうるのはバージョンの部分の番号(相当)だけであるべき コメントは最後に ( ) で括って書く 製品名とバージョンには次の18文字は使えない ( ) < > @ , ; : \ " / [ ] ? = { } 空白 ひとつの製品名に対してバージョンを / で複数記述することはできない(MyMech/0.0.2/Ruby1.8.7 は不可) コメントに ( ) " の3文字を使用する場合はバックスラッシュでクオートする
サーバアクセス時に User-Agent リクエストヘッダで送信される文字列を返します。
#user_agent= や #user_agent_alias= で設定していない場合のデフォルト値は "WWW-Mechanize/バージョン (http://rubyforge.org/projects/mechanize/)" です。
現在使用されていません。
現在使用されていません。
SSL 認証に使用する CA certification ファイルのパスを文字列で設定します。
設定を行わなかった場合の内部値は nil となります。
このときの通信には OpenSSL::SSL::VERIFY_PEER が用いられ、#verify_callback が指定されていればそれも用いられます。
引数は Net::HTTPS#ca_file= にそのまま渡されるので、そちらを参照してください。
なお、ca_file と #cert= と #key= のどれも指定されていない場合、https の SSL 通信は OpenSSL::SSL::VERIFY_NONE で行われます。
SSL 認証に使用する OpenSSL::X509::Certificate クラスに読み込ませるファイルのパスを文字列で指定します。
設定を行わなかった場合の内部値は nil となります。
Net::HTTPS#cert=OpenSSL::X509::Certificate.new(::File.read(cert)) のような処理になっています。
Net::HTTPS#cert= を参照してください。
そちらを参照してください。
なお、#ca_file= と cert と #key= のどれも指定されていない場合、https の SSL 通信は OpenSSL::SSL::VERIFY_NONE で行われます。
#cert= で設定された、SSL 認証に使用する OpenSSL::X509::Certificate クラスに読み込ませるファイルのパスを文字列で返します。設定されていない場合は nil を返します。
SSL 認証に使用する RSA 公開鍵に必要なパスフレーズを文字列で指定します。
設定を行わなかった場合の内部値は nil で、パスワードは空とみなされます。
証明書のファイルパスは #cert= で、公開鍵のファイルパスは #key= で指定します。
Net::HTTPS#key=OpenSSL::PKey::RSA.new(::File.read(key), pass) のような処理になっています。OpenSSL::PKey::DSA オブジェクトを利用することはできません。
Basic 認証のパスワード設定は #password= を使用します。
サーバから 301 Moved Permanently や 302 Found が送られてきたとき、Location レスポンスヘッダのリダイレクトに追随するかどうかを設定します。
設定を行わなかった場合の内部値は true で、Location レスポンスヘッダに記載された URL に自動で移動します。
サーバからのレスポンスヘッダ内で秒数が指定されていた場合はその秒数だけ sleep してから移動します。
リダイレクトの連続回数の最大値は #redirection_limit= で指定します。
元ページを HEAD で取得していた場合は HEAD で移動し、それ以外の HTTP メソッドだった場合は GET で移動します。
対象となる HTTP レスポンスは 300、301、302、303、305、307 です。304 Not Modified はこのメソッドではなく #conditional_requests= の担当です。
Location 遷移の履歴は最後の URL とページで置き換えられ、消去されます。
irb> agent.get('http://host/1') I, [2010-06-03 #4187] INFO -- : Net::HTTP::Get: /1 I, [2010-06-03 #4187] INFO -- : status: 301 I, [2010-06-03 #4187] INFO -- : follow redirect to: http://host/2 I, [2010-06-03 #4187] INFO -- : Net::HTTP::Get: /2 I, [2010-06-03 #4187] INFO -- : status: 301 I, [2010-06-03 #4187] INFO -- : follow redirect to: http://host/3 I, [2010-06-03 #4187] INFO -- : Net::HTTP::Get: /3 I, [2010-06-03 #4187] INFO -- : status: 200 irb> p agent.history.size 3 irb> puts agent.history.map{|page| page.uri} http://host/3 http://host/3 http://host/3
サーバから 301 Moved Permanently や 302 Found が送られてきたとき、Location レスポンスヘッダのリダイレクトに追随するかどうかを返します。デフォルトは true です。
設定は #redirect_ok= で行います。
#follow_redirect? はこのメソッドのエイリアスです。
Mechanize のリクエストヘッダの Accept-Encoding に gzip を追加するかどうかを設定します。
設定を行わなかった場合の内部値は true で、Accept-Encoding : gzip,identity というヘッダが常に送信されます。false に設定した場合は identity のみ送られます。
identity のみにするのは差分取得でよく見られる手法ですが、Mechanize 自体は差分取得をうまく差分として扱えません。取得したデータを自力で解釈する必要があります。
なお、サーバから gzip として送られてきたデータは Mechanize が自動で展開し Mechanize::Page#body や Mechanize::File#body に格納します。
Mechanize のリクエストヘッダの Accept-Encoding に gzip を追加するかどうかを真偽で返します。デフォルトは true です。
設定は #gzip_enabled= で行います。
Mechanize のリクエストヘッダの Keep-Live に指定する秒数を整数で指定します。
設定を行わなかった場合の内部値は 300 で、#keep_alive が(デフォルトの)真のままである限り、Keep-Alive : 300 というヘッダがサーバに送信されます。
Mechanize で keep-alive を利用するかどうかを設定します。
設定を行わなかった場合の内部値は true で、
Connection : keep-alive Keep-Alive : 300というリクエストヘッダがサーバに送信されます。Keep-Alive の秒数は #keep_alive_time= で設定できます。
false に設定した場合は
Connection : closeというリクエストヘッダがサーバに常に送信されます。余談ですが Mechanize の HTTP のバージョンは 1.1 です。
Mechanize で keep-alive を利用するかどうかを返します。デフォルトは true です。
If-Modified-Since ヘッダによる更新確認を行うかどうかを設定します。
設定を行わなかった場合の内部値は true で、履歴に存在するページへの再アクセスには更新チェックが試されます。
nil や false などの偽を指定すると、更新確認は行われず、サーバからの取得は必ず行われます。
true で更新チェックを行う設定である場合は
- アクセスする URL が履歴内に存在する
- agent.visited?(url) が真
- 以前のアクセス時のレスポンスヘッダに Last-Modified ヘッダが存在する
- agent.visited_page(url).response['last-modified'] が時刻
ただし、サーバ送信後 304 Not Modified が返ってきた場合、Mechanize はそのレスポンスヘッダを保存せず、履歴の agent.visited_page(url) の返り値のオブジェクトを #get や #head などの返り値として再利用してしまいます。
irb> agent.get('http://www.ruby-lang.org/images/logo.gif') I, [2010-09-28] INFO -- : Net::HTTP::Get: /images/logo.gif ... D, [2010-09-28] DEBUG -- : response-header: etag => "100d2874-2180-89b0f40" D, [2010-09-28] DEBUG -- : response-header: last-modified => Sat, 19 Aug 2006 16:04:37 GMT D, [2010-09-28] DEBUG -- : response-header: date => Tue, 28 Sep 2010 01:39:57 GMT I, [2010-09-28] INFO -- : status: 200 irb> agent.head('http://www.ruby-lang.org/images/logo.gif') I, [2010-09-28] INFO -- : Net::HTTP::Head: /images/logo.gif D, [2010-09-28] DEBUG -- : request-header: if-modified-since => Sat, 19 Aug 2006 16:04:37 GMT ... D, [2010-09-28] DEBUG -- : response-header: etag => "100d2874-2180-89b0f40" D, [2010-09-28] DEBUG -- : response-header: date => Tue, 28 Sep 2010 01:40:01 GMT I, [2010-09-28] INFO -- : status: 304 D, [2010-09-28] DEBUG -- : Got cached page irb> p agent.page.code "200" irb> p agent.page.body[0..5] "GIF89a"Mechanize 1.0.0 の時点では If-Modified-Since のアクセスの結果のヘッダはユーザーは取得できません。
結果として、Mechanize ではサーバが 304 Not Modified を返したかどうかどうかをスクリプト内から直接知ることができません(ログ出力を Mechanize.log で有効にしていた場合は 'Got cached page' という DEBUG レベルのログが出力されます)。更新されていないかどうかの情報が必要な場合は、返り値のオブジェクトと履歴にあるオブジェクトを equal? や == で比較してください。更新されていない場合は同一 ID のオブジェクトが返されるので、これが真になります。
agent.get(url) # 1st agent.head(uri) # 2nd with If-Modified-Since: if agent.page.equal?(agent.visited_page(uri)) then warn 'not modified' else some_process(agent.page) end
meta タグの refresh と レスポンスヘッダの Refresh ヘッダに追随して自動移動するかどうかを設定します。
設定を行わなかった場合の内部値は false で、refresh を解釈して自動で移動することはありません。
agent.follow_meta_refresh = true として真に設定すると、アクセスした HTML に以下のような meta タグがあった場合、
<meta http-equiv="refresh" content="2; URL=http://example.com/">
2 秒間 sleep したあと、http://example.com/ へ(GET で)アクセスします。リファラは通常の Web ブラウザでの動作同様、一切送られません。
HTTP ヘッダの Refresh ヘッダも自動で読み、
Refresh: 10, http://www.example.jp/という HTTP ヘッダをサーバから受け取ると、Mechanize は sleep で実際に 10秒待ってから http://www.example.jp/ にアクセスします。
秒数を無視することはできません。
リフレッシュ先 URL に相対 URL が書かれていることは無いはずなのですが、相対 URL だった場合はページの URL をベースに絶対 URL と解釈してアクセスします。
指定された秒数を待ちたくない場合は、たとえば meta タグでは agent.page.meta[0].uri が移動先の URL なはずなので、直接 get などを行ってください。
agent.get(url) if agent.page.meta[0] && agent.page.meta[0].uri then agent.get(agent.page.meta[0].uri) endmeta ではなく HTTP の Location ヘッダによるリダイレクトについては #redirect_ok を参照してください。
meta タグの refresh と レスポンスヘッダの Refresh ヘッダに追随して自動移動するかどうかを真偽で返します。デフォルトは false です。
設定は #follow_meta_refresh= で行います。
SSL 通信用の Net::HTTPS#verify_callback に渡す Proc オブジェクトを設定します。
設定を行わなかった場合の内部値は nil で、verify_callback は行われません。
SSL 通信用の Net::HTTPS#verify_callback に渡す Proc オブジェクトを返します。デフォルトは nil です。
設定は #verify_callback= で行います。
Proc オブジェクトを設定すると、「サーバにアクセスしてページを返すメソッド」の処理の最後にその Proc オブジェクトを実行させることができます。
設定を行わなかった場合の内部値は nil で、何も実行されません。
#get、#post、#put、および Mechanize::Page::Link#click や Mechanize::Form#submit 等のページを返り値として返すメソッド全てが対象になります。
返るページオブジェクトが Proc#call の引数として渡されます。内部では history_added.call(page) if history_added という動作になっています。
メソッド名には「history」の文字がありますが、履歴登録のタイミングを全て監視しているわけではなく、リダイレクト時などには「最後」にしか実行されません。これが意図的なものなのか不具合なのかはよくわかりません。
require 'rubygems' require 'mechanize' require 'logger' agent = Mechanize.new agent.log = Logger.new($stdout) agent.history_added = lambda{|page| page.mech.log.info("Page Title: #{page.title}") if page.mech.log} agent.get('http://www.yahoo.co.jp/')整形済み結果:
I, [2008-10-15T12:30:24] INFO -- : Net::HTTP::Get: /fc D, [2008-10-15T12:30:24] DEBUG -- : response-header: location => http://dailynews.yahoo.co.jp/fc/ I, [2008-10-15T12:30:24] INFO -- : status: 302 I, [2008-10-15T12:30:24] INFO -- : follow redirect to: http://dailynews.yahoo.co.jp/fc/ I, [2008-10-15T12:30:24] INFO -- : Net::HTTP::Get: /fc/ I, [2008-10-15T12:30:25] INFO -- : status: 200 I, [2008-10-15T12:30:25] INFO -- : Page Title: Yahoo!ニュース - トピックス 速報と関連リンクで世の中が分かる
実行されるタイミングに注意してください。Location: ヘッダのリダイレクトをした時点では実行されていません(あくまで、メソッド内部で値を返す直前になります)。
サーバ接続直前にリクエストヘッダや送信本文に対して実行したい Proc オブジェクトがある場合は #pre_connect_hooks を、サーバからデータ取得直後にレスポンスヘッダや取得本文に対して実行したい Proc オブジェクトがある場合は #post_connect_hooks を使用してください。
scheme_handler の Hash 自体を上書きします。
スキームごとの登録を行いたい場合はこのメソッドを使用せず、 #scheme_handlers の返り値に Hash#[]= したり Hash#store したりしてください。
scheme_handler の Hash を返します。
デフォルトでは http、https、relative、ftp の 4つをキーとする Hash が返ります。
scheme_handler は URL をアクセス直前に変更することができます。
agent.scheme_handlers['http'] = lambda{|uri, referer_page| … result_uri }というように Proc オブジェクトを指定してください。
Mechanize::Chain::URIResolver で整形した結果の「アクセス先 URL」の uri.scheme が指定キーであった場合に、アクセス先 uri と現在のページ referer_page をブロック引数として Proc オブジェクトが実行されます。ブロック返り値はアクセス先 URL を表す URI オブジェクトでなければなりません。
http で始まる URL にアクセスしようとしている場合にそのホスト名部分を大文字にする、という scheme_handlers は
agent.scheme_handlers['http'] = lambda{|uri, referer_page| uri.host = uri.host.upcase unless uri.relative? uri }などと書くことができます。が、正直使いどころがよくわかりません。
Location ヘッダによるリダイレクトの連続回数の最大値を整数で設定します。
設定を行わなかった場合の内部値は 20で、#redirect_ok が(デフォルトの)真で HTTP リダイレクトが有効な場合、連続 21回目に例外 Mechanize::RedirectLimitReachedError? を発生させます。
Mechanize の毎回のサーバアクセス時にリクエストヘッダとして追加するヘッダを Hash で設定します。
agent.request_headers = { 'accept-language' => 'ja, ja-JP, en', 'accept-encoding' => 'utf-8, us-ascii' }設定を行わなかった場合の内部値は空の {} で、ヘッダ追加は行われません。Hash のキーは文字列でさえあれば大文字でも小文字でも構いません(送信直前に Net::HTTP が適切にキャピタライズします)。
ヘッダ追加の処理の流れ的には 2番目でかなり早く、Mechanize::Chain::HeaderResolver? が毎回発行する基本的なリクエストヘッダを上書きすることだけができます。#post などが生成する内部ヘッダや #get などの引数で追加されるユーザー指定ヘッダを書き換えることはできません。
Mechanize がヘッダを作成する順番は以下の通りです。
- Mechanize が共通で発行するヘッダを定義
- Mechanize#request_headers= で指定したヘッダを追加
- Mechanize#post など取得メソッド固有のヘッダを追加
- Mechanize#get などでユーザーが引数で指定した追加ヘッダを追加
- Mechanize#pre_connect_hook で直接 HTTP オブジェクトをいじる処理
- If-Modified-Since ヘッダの追加
たとえば、POST 送信用の Content-Type をこの request_headers= で指定しても、Mechanize#post や Form#submit の固有ヘッダで必ず消されてしまいます。この request_headers= で指定した Accept-Language は、Mechanize#get の引数で指定した Accept-Language で上書きされます。
この request_headers= で指定されたヘッダは Mechanize の全アクセスで使用されてしまうので、特定のアクセス単位でヘッダを追加したいというだけの場合は #get などの送信メソッドの引数でヘッダを追加することをお勧めします。
この Mechanize オブジェクトで使用する HTML パーサのクラスを設定します。
設定を行わなかった場合の内部値は Nokogiri::HTML です。
Nokogiri::HTML または Hpricot と互換の HTML パース動作をする HTML パーサであれば何でも構いません。
Mechanize.html_parser= で指定したパーサがある場合は、デフォルトがクラスメソッドのものになります。
その上でこのインスタンスメソッドで別途指定したパーサがある場合は、インスタンスメソッドのパーサが優先されます。
pluggable parser を設定します。
サーバからの Content-Type によって、パースなどを行う内部クラスを切り替えます。独自処理の自作クラスを指定することもできます。Mechanize::PluggableParser を参照してください。
アクセス履歴として Mechanize が保持してもよい、ページやファイルのオブジェクトの数を整数か nil で設定します。
設定を行わなかった場合は #max_history の値が使用されます。
履歴に関しては Mechanize::History クラスを参照してください。
アクセス履歴として Mechanize が保持してもよい、ページやファイルのオブジェクトの数を整数で返します。
デフォルトは nil で、取得したページやファイルのオブジェクトを全て無限にメモリ内に保持します。
履歴に関しては Mechanize::History クラスを参照してください。
設定は #max_history= で行います。
デフォルトのログ出力クラスのオブジェクトを返す Mechanize.log メソッドの返り値を設定します。
Mechanize.log= を参照してください。
必ずクラスメソッドを呼びます。Mechanize オブジェクト単位でログ出力を切り替えることは、Mechanize 1.0.0 の時点ではできません。
Mechanize クラスで生成されるオブジェクトで使用するログ出力クラスのオブジェクトを返します。
Mechanize.log を参照してください。
必ずクラスメソッドを呼びます。誰かが #log= か Mechanize.log= でログ出力を変更したら、現存する全 Mechanize オブジェクトおよびこれから生成される Mechanize オブジェクト全てが即座に影響を受けます。Mechanize オブジェクト単位でログ出力を切り替えることはできません。
サーバへのアクセスの直前に行いたい Proc オブジェクトを登録します。
agent.pre_connect_hooks << Proc.new{|params| ...} agent.get(uri) agent.page.link_with(...).click agent.pre_connect_hooks.clear # 以降の get や click に影響させたくない場合
メソッドの返り値として配列が返るので、Array#push や Array#<< で手続きオブジェクトを登録してください。サーバへのアクセス直前に、配列の最初から順番に Proc#call されます。
何も設定しなかった場合の内部値は空の配列 [ ] で、何も行われません。
Proc オブジェクトに渡される引数は、特定の Symbol をキーに持つ Hash です。たとえば、
agent.pre_connect_hooks << Proc.new{|params| params[:request]['Header-Name'] = new}と登録すると、サーバに送られる予定の HTTP ヘッダ Header-Name の値を new へ変更することができます(ただし、実際に「全アクセスのヘッダ追加変更」をするなら Mechanize#request_headers= を推奨します)。
- params[:uri]
- アクセスする URI オブジェクト(パラメータが URI#query に既に入った完全なもの)
- params[:request]
- Net::HTTP::Get(やPost)のオブジェクト
- params[:connection]
- Net::HTTP オブジェクト
params が受け付ける全てのキーについては、プライベートメソッド #fetch_page の params を参照してください。
なお、pre_connect_hooks の処理後から実際のサーバ接続の間に行われるものがいくつかあり、
- If-Modified-Since ヘッダ
- open_timeout とread_timeout の設定
手続きオブジェクトは Mechanize オブジェクトのインスタンス変数に保存されるので、以後の get や click 、submit や post などのサーバアクセスでずっと使われます。
一度使いたいだけの場合は、get メソッドなどの終了後に agent.pre_connect_hooks.clear などとして内部の配列を空にしておいてください。
サーバからファイルを取得した直後に行いたい Proc オブジェクトを登録します。
agent.post_connect_hooks << Proc.new{|params| ...} agent.get(uri) agent.post_connect_hooks.clear # 次の get や click に影響させたくない場合
メソッドの返り値として配列が返るので、Array#push や Array#<< で手続きオブジェクトを登録してください。サーバからデータを取得して gzip 展開して「ファイル」とした直後に、配列の最初から順番に Proc#call されます。
何も設定しなかった場合の内部値は空の配列 [ ] で、何も行われません。
Proc オブジェクトに渡される引数は、特定の Symbol をキーに持つ Hash です。
- params[:response_body]
- サーバから取得したファイルのボディ部。gzip 展開済み
- params[:res_klass]
- サーバからのレスポンスコードを表す Net::HTTPOK などのクラス
- params[:response]
- サーバからの Net::HTTPResponse のオブジェクト
- params[:uri]
- アクセスした URI オブジェクトの複製(パラメータが URI#query に入った完全なもの)
- params[:request]
- 接続に使用した Net::HTTP::Get(やPostなど)のオブジェクト
- params[:connection]
- 接続に使用した Net::HTTP オブジェクト
たとえば、Proc.new{|params| p params[:response]['Header-Name']} と登録すると、サーバから送られてきた HTTP ヘッダ Header-Name の値を表示することができます。
手続きオブジェクトは Mechanize オブジェクトのインスタンス変数に保存されるので、以後の get や click 、submit や post などのサーバアクセスでずっと使われます。
一度使いたいだけの場合は、get メソッドなどの終了後に agent.post_connect_hooks.clear などとして内部の配列を空にしておいてください。
この post_connect_hooks が実行されたあと、pluggable_parser 処理や Cookie 登録、<meta> のリフレッシュ処理や各種 HTTP レスポンスの解釈(302や301や401)や履歴への登録が行われます。
インターネットアクセスに必要なプロキシのアドレス(host)、ポート(port)、ユーザー名(user)、パスワード(pass)を設定します。
pass の値が返ります。
agent.set_proxy('proxy.localhost', '8080', 'proxyuser', 'proxypassword')アドレスは http:// などを事前に取り除いたホスト名で設定します(user:pass@localhost:8080 のような一括記法は受け付けません)。ユーザー名やパスワードが不要な場合は省略するか nil を指定します。
プロキシの設定はサイト接続前に行ってください。一度サイトAへの接続を試したあとプロキシを設定してもう一度同じサイトへアクセス、といったことをしても、サイトAへのアクセスにはプロキシが使用されません。
ユーザー名とパスワードは Proxy-Authorization ヘッダの記述に用いられます。詳しくは Net::HTTP.new のマニュアルを参照してください。
サーバアクセス時に User-Agent ヘッダで送信される値を、既存の Web ブラウザのもので詐称するよう設定します。
agent.user_agent_alias = 'Windows IE 7'とすると、それ以降のアクセスでは
User-Agent: 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)'というリクエストヘッダが送られます。
デフォルトでは #user_agent= の値が使用されます。user_agent= でも指定されていなかったときには 'Mechanize' のエイリアスが User-Agent として使用されます。
'Windows IE 6' => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)', 'Windows IE 7' => 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)', 'Windows Mozilla' => 'Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4b) Gecko/20030516 Mozilla Firebird/0.6', 'Mac Safari' => 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; de-at) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10', 'Mac FireFox' => 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6', 'Mac Mozilla' => 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.4a) Gecko/20030401', 'Linux Mozilla' => 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030624', 'Linux Firefox' => 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.1) Gecko/20100122 firefox/3.6.1', 'Linux Konqueror' => 'Mozilla/5.0 (compatible; Konqueror/3; Linux)', 'iPhone' => 'Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1C28 Safari/419.3', 'Mechanize' => "WWW-Mechanize/#{VERSION} (http://rubyforge.org/projects/mechanize/)"
省略記述文字列は完全に一致するものを指定してください。正しくない文字列を指定した場合は RuntimeError: unknown agent alias が発生します。
irb> agent.user_agent_alias = 'Windows IE6' RuntimeError: unknown agent alias
相手サーバは ユーザーエージェントで判断するので、ユーザーエージェントを他のブラウザのものにしていると Mechanize でパースできないファイル(元々のブラウザでは当然読める)が返ってくることがあります。
Mechanize オブジェクトが現在持っている Mechanize::Cookie オブジェクトをすべて、期限切れのものも含めて配列にして返します。
配列に変換してから返すので、CookieJar としては操作できません。クッキーを操作したい場合は #cookie_jar メソッドの返り値を操作してください。
Basic 認証や Digest 認証に使用するユーザー名 user とパスワード password を設定します。
password が返ります。
# get より前に設定しておく agent.auth('username', 'pasuwa-do123') # あとは自動 agent.get('http://example.com/auth/')
- 認証の必要なエリアに(たまたま)普通にアクセスする
- サーバから 401 Unauthorized が返ってくる
- auth メソッドで事前設定がある場合は認証ヘッダを自動で送る、未設定なら例外 Mechanize::ResponseCodeError?
- 認証失敗で再度 401 Unauthorized が返ってきたら例外 Mechanize::ResponseCodeError?
- 認証成功の場合は認証の遣り取りを履歴に残さずに取得データをページとして URL に対するメソッドの返り値とする
という流れになります。
認証成功のデータはホストごとに(uri.host 名義で)記録され、一度成功したホストへの全てのアクセスには以後自動的に認証ヘッダが送られ続けます。せめてディレクトリ単位で記憶してくれると嬉しいのですが。
複数の認証セットを「予約設定」しておくことはできません。それぞれの認証が起こるアクセスの直前にそれぞれの認証セットを auth してください。
Digest 認証のレスポンス生成に使われる cnonce は Mechanize::Chain::AuthHeaders::CNONCE? です。
RubyのMechanizeでBASIC認証・Digest認証も参照してください。
実際に作成される HTTP ヘッダについては、Mechanize::Chain::AuthHeaders? を参照してください。
#basic_auth はこのメソッドのエイリアスですが、特に BASIC 認証に特化した何かがあるというわけではありません。BASIC 認証を basic_auth で予約したあとでも Digest 認証を auth で1個だけ予約できるとかそういう使い分けもありません。
Mechanize が持つ全てのクッキーを管理するクラス Mechanize::CookieJar のオブジェクトを返します。
クッキーを操作したい場合は、これの返り値から CookieJar クラスのメソッドを利用してください。
# ファイルからクッキーを読んですべて置き換える agent.cookie_jar.load('./cookie.yaml') # 以後のアクセスにはファイルのクッキーが使用される puts agent.get(uri).title ... # 現在の全クッキーをファイルに保存する agent.cookie_jar.save('./cookie.yaml')
引数の Mechanize::Page::Link オブジェクトの表す URL を #get で取得して返します。
Link オブジェクトをagent.page.links[3].click のように直接 click した場合に、内部でこのメソッドが呼ばれています。
agent.page.link_with(:text => 'home').click agent.click(agent.page.link_with(:text => 'home'))動作上は全く同一ですが、ユーザーが後者の Mechanize#click のほうをスクリプト内で使う機会はあまりないことでしょう。
リファラは Link オブジェクトの所属するページ(Mechanize::Page::Link#page)か、それが空なら現在のページの URI のどちらかに必ずなります。それ以上の動作は #get そのものなので、動作の詳細は #get をどうぞ。ヘッダを追加することができないので、リファラを送りたくない場合は click 自体を使用せず、リンクの絶対 URL を get に渡すなどしてごまかしてください。
なお、#parser や #root から検索した Nokogiri のオブジェクトを直接引数にすることもできます。href 属性か src 属性のあるものを指定してください。
a_node = agent.parser.at(very_comlex_search_condition) agent.click(a_node) # たぶん動作一緒(hrefが相対URLならリファラ指定不要) agent.get(:url => a_node['href'], :referer => agent.page)
#history の最後のページオブジェクトを実際にひとつ削除します(つまり、Array#popします)。
結果として、#page メソッドなどの返り値が「ひとつ前」のものになるようになります。削除されたページオブジェクトを返します。
履歴が
irb> p agent.history.map{|page| page.uri} [uri_1, uri_2, uri_3, uri_4]という状態だった場合、#page は「uri_4 のページ」を返しますが、ここで back メソッドを実行すると「uri_4 に該当するページ」が削除され、
irb> p agent.history.map{|page| page.uri} [uri_1, uri_2, uri_3]という状態になります。この back 後では #page は「uri_3 のページ」を返します。
Web ブラウザの「戻る」ボタンにメソッド名が似ていますが、実際に削除してしまうことに注意してください(削除したら再取得しか手がありません)。
実際の Web ブラウザの(自在な)「戻る」ボタンに相当するのは #visited_page による agent.visited_page(uri_3) のような URL 指定の履歴抽出か、#history を配列として利用した agent.history[-2] のような順番指定だと思われます。
「現在」のページ(履歴で一番新しいページ、最後に取得したページ)の Mechanize::Page オブジェクトまたは Mechanize::File オブジェクトを返します。
履歴はページ取得ごとに Array#push される配列なので、履歴配列 #history の一番後ろを返すことになります。
got_page = agent.get(url) # 全部同じオブジェクトを指す got_page agent.current_page agent.page agent.history[-1] agent.visited_page(url)履歴が存在しない場合は nil を返します。
#page はこのメソッドのエイリアスです。
履歴の Mechanize::History オブジェクト が url に関するページを含んでいれば true を、そうでなければ false を返します。
#visited_page メソッドの返り値が nil かどうかをチェックしています(nil だったら false)。引数の url の詳細などはそちらを参照してください。
履歴の Mechanize::History オブジェクトが url に関するページを含んでいれば抽出して返します。存在しなければ nil を返します。
キャッシュコントロールなどの HTTP ヘッダは考慮されず、キャッシュ不可だろうがキャッシュ期間切れだろうがごく機械的に過去のオブジェクトが抽出されます。
有効な url の書式は以下のとおりです。
- Mechanize::Page::Link オブジェクト
- Ruby 標準の URI オブジェクト
- http:// か https:// か file:// で始まる URL 文字列
- 「現在」のページの URL で有効な、 / で始まる URL の絶対パス文字列(/test/index.html のようなもの)
- 「現在」のページの URL から見た、ドットで始まる相対パス文字列(../test/index.html のようなもの)
- 「現在」のページの URL から見た、ドットで始まらない相対パス文字列(test/index.html のようなもの)
agent = Mechanize.new agent.get('http://example.com/test/index.html') agent.get('http://example.com/test/other.html') # 完全なURL p agent.visited_page('http://example.com/test/index.html').uri.to_s # 絶対パス p agent.visited_page('/test/index.html').uri.to_s # ドットつき相対パス p agent.visited_page('../test/index.html').uri.to_s # ドット無し相対パス p agent.visited_page('index.html').uri.to_s結果
http://example.com/test/index.html http://example.com/test/index.html http://example.com/test/index.html http://example.com/test/index.html
Mechanize では path 部が無い URI は / が追加されて扱われるので、
agent.get('http://www.example.com') p agent.visited_page('http://www.example.com').uri p agent.visited_page('http://www.example.com/').uriこれはどちらも http://www.example.com/ の URI を返します(つまり通常のWebブラウザと同じ挙動であり、悩まなくても構いません)。
Location ヘッダによるリダイレクトや meta タグによるリフレッシュにより飛んでいた場合は、「飛ぶ前」の URL でも「飛んだ後」の URL でも最終的な「飛んだ先」のページが返ります。
必ずブロックをとり、そのブロック終了時に、履歴オブジェクトをブロック開始直前の履歴オブジェクトで上書きします。
ブロックの結果を返します。
結果として、ブロック内でアクセスしたページはブロック後の履歴に残りません。
Mechanize::History オブジェクトを一旦退避させて終了時に上書きしているため、ブロック内で max_history の値を変えたりしてもブロック終了と同時に「元」に戻ります。
p agent.history.size #=> 9 agent.transact do |a| p a.history.size #=> 9、transactだが0ではない a.history.clear p a.history.size #=> 0 end p agent.history.size #=> 9何らかの理由で履歴を「別物」にさせたい場合には、ブロック開始時に履歴を一旦空にします。アクセス履歴以外のクッキーや Keep-Alive、認証履歴などは普通に共通なので、本当に全く新しいアクセスをしたい場合は Mechanize オブジェクトを新規に生成して利用することをお勧めします。
Mechanize オブジェクトが過去にアクセスしたページの一覧である Mechanize::History オブジェクトを返します。
履歴操作に関しては #max_history や #visited?、#visited_page も参照してください。直接この history の返り値から History クラスのメソッドを利用しても構いません(内部的には同じことになっています)。
引数の url にアクセスし、結果のヘッダやファイルを Mechanize ライブラリのオブジェクトにして、履歴に登録してから返します。
サーバから取得したデータが HTML だった場合は Mechanize::Page オブジェクトで、それ以外だった場合は Mechanize::File オブジェクトで返されます。
第 1引数には、アクセス先の URL を指定します。これのみ、必須です。URL を表す文字列か、Ruby 標準の URI オブジェクトが利用できます。
agent.get('http://example.com/') agent.get(URI.parse('http://example.com/')) agent.get(URI.escape('http://example.com/猫'))文字列の場合は適切にパーセントエンコード済みのものを渡してください。"http://example.com/猫" などのマルチバイト文字入り URL 文字列は解釈できません(URL として正しい状態の文字列のみ指定してください)。"http://例え.テスト/" のような国際化ドメイン名も利用できません。
第 2引数は GET のパラメータ(クエリパラメータ)を送るときに使用します。Hash かネストした配列を指定します。これは URL に直接含めても構いません。
agent.get(url, {'q' => 'ruby', 'page' => '0'}) agent.get(url, {[['q', 'ここだけShift_JISで送る'.tosjis], ['page', '0']]) agent.get('http://www.example.com/search.cgi?q=ruby&page=0') # also works文字列はそのまま適当に URI エンコードされます(URL 文字列に直書きするのでなければマルチバイト文字そのままでもOKです)。url に既に query 文字列がついていた場合はその後ろに追加されます。
第 3引数はリクエストヘッダの Referer に記述したい URL がある場合に使用します。URL 文字列か URI オブジェクトか Mechanize::Page オブジェクトか Mechanize::File オブジェクトで指定します。第2引数のクエリパラメータが不要な場合は nil を書いておきます。
agent.get(url, nil, 'http://referer.example.com/')
リクエストヘッダに追加したいヘッダがある場合は大文字小文字関係ないキーの Hash で指定します。Mechanize 1.0.0 では、キーワード風引数による指定しかできません。Mechanize::Chain::CustomHeaders? で処理されるのでそちらを参照してください。
agent.get( :url => url, # :uri ではなくユーアールエル :params => {'q' => 'Ruby'}, :referer => 'http://referer.example.com/', :headres => {'X-My-Header' => 'hello!'})なお、キーワード風引数は deprecated です。2010年10月に廃止されるのでヘッダ追加時以外では常用しないでください。
第 1引数に相対 URL を指定したときは、現在のページの URL などを参考にして絶対 URL が計算されます。ただし、引数 URL 文字列が "http" の 4文字で開始しているかどうかだけで判断しているので、agent.get('http_desc.html') などはエラーになります。'./http_desc.html' のように書くようにしてください。
リファラは通常送信されませんが、url が相対 URL だとみなされた場合は現在のページの url が自動で送られます。
内部的送信メソッドは #fetch_page です。
HTTP の PUT メソッドで entity 文字列を url へ送信します。
サーバからの結果(おそらくヘッダだけ)を履歴に登録し、ページとして返します。
第 1引数の url は URL を表す文字列か、Ruby 標準の URI オブジェクトです。
第 2引数の entity は送信可能文字列です。#post とは違い、送信可能状態の文字列しか受け付けません(本当にそのまま送信されます)。リクエストヘッダの Content-Type はデフォルトで application/octet-stream となります。
第 3引数 options は内部的な #fetch_page メソッドへのオプションで、リクエストヘッダ Hash とリファラページをそれぞれ :headers と :referer で指定できます。
additional_headers = {'content-type' => 'text/plain'} agent.put(url, entity_str, {:headers => additional_headers, :referer => agent.visited_page(refurl)}):headers のキーは大文字小文字無関係の文字列です。Mechanize::Chain::CustomHeaders? で処理されるのでそちらを参照してください。
HTTP の DELETE メソッドで url にアクセスします。
サーバからの結果(おそらくヘッダだけ)を履歴に登録し、ページとして返します。
第 1引数の url は URL を表す文字列か、Ruby 標準の URI オブジェクトです。
第 2引数 query_params はクエリ送信パラメータな Hash、
第 3引数 options は #fetch_page メソッドへのオプションです。
履歴登録前の動作的には HTTP 送信メソッドが DELETE なだけの #head メソッドです。詳細は #head を参照してください。
HTTP の HEAD メソッドで url にアクセスします。
サーバからの結果(おそらくヘッダだけ)を履歴に登録せずにページとして返します。
irb> agent = Mechanize.new irb> agent.head('http://www.google.com/') irb> p agent.history.size 0
第 1引数の url は URL を表す文字列か、Ruby 標準の URI オブジェクトです。
url に追加されるクエリ送信パラメータが存在する場合は第 2引数に Hash で指定します。url に既に含まれているような場合は第 2 引数を省略するか nil を指定しておいてください。
第 3引数 options は #fetch_page メソッドへのオプションです。リクエストヘッダ Hash とリファラページをそれぞれ :headers と :referer で指定できます。:headers のキーは大文字小文字無関係の文字列です。Mechanize::Chain::CustomHeaders? で処理されるのでそちらを参照してください。
HEAD に付きもののリクエストヘッダを追加する引数の場所は「第3引数の中」なので注意してください。なお、Ruby パーサを混乱させない限り、下記のような書き方も許されています。
# 一緒一緒 agent.head(url, nil, {:headers => {'If-Modified-Since' => 'Sun, 06 Jun 2010 04:33:19 GMT'}}) agent.head(url, nil, :headers => {'If-Modified-Since' => 'Sun, 06 Jun 2010 04:33:19 GMT'})
head でのアクセスで Location ヘッダが送られてきた場合、リダイレクト先にも head で移動します(妥当な動作です)。
head でのアクセスで 304 Not Modified が送られてきた場合、head メソッドはヘッダのみを返すことはせず、該当 URL の #visited_page の結果を返してしまいます(#get での 304と同じ動作)。レスポンスヘッダは消滅してしまい、304 を返してきたかどうかそのもを知ることはできません(妥当じゃない動作です)。
HTTP の POST メソッドで url に query データを送信し、結果を履歴に登録してそのオブジェクトを返します。
直接 POST したいデータが別途存在する等の理由があるのでない限り、ユーザーがこのメソッドを直接使用することはまずありません。通常は HTML のフォームを表す Mechanize::Form を利用します。
第 1引数の url は URL を表す文字列か、Ruby 標準の URI オブジェクトです。
第 2引数が文字列だった場合、#request_with_entity に request_with_entity(:post, url, query, {:headers => headers}) として渡されます。
第 2引数が Hash かネストした配列をだった場合は、そういう値の擬似的なフォームオブジェクトがあるとみなして処理されます。
<form action="#{url}"> <input type="text" name="#{query_name1}" value="#{query_value1}"> <input type="text" name="#{query_name2}" value="#{query_value2}"> <input type="text" name="#{query_name3}" value="#{query_value3}"> ... <input type="file" name="#{query_name9}" filename="#{File.basename(query_value9.path)}" value="#{query_value9.read}"> ...こんな感じのフォームを submit したとみなして処理します。引数データから Mechanize::Form を作成してしまうので、Form オブジェクトと Mechanize::Form::Field オブジェクトとしての制限を受けます。つまり
- name と value は Mechanize::Util.html_unescape されてから CGI.escape される
query に {'name' => file_io} という形で File オブジェクト file_io があった場合はファイルアップロードとみなし、名前を name、value を file_io.read 、filename トークンを File.basename(file_io.path) とみなします。この場合はサーバ送信時の Content-Type は multipart/form-data になります。
これらの一連の擬似フォーム処理がうまくないという場合はエンティティを自前で作り、文字列として post して(headersで適切なリクエストヘッダを指定して)ください。
リファラの URL はどの場合も現在のページ(#page の返り値)になります。
第 3引数の追加 HTTP リクエストヘッダ指定で、headers のキーは大文字小文字無関係の文字列です。Mechanize::Chain::CustomHeaders? で処理されるのでそちらを参照してください。
引数のフォーム form のデータを form.action で指定されている URL へ HTTP 送信メソッド form.action で送り、サーバから取得した結果のページを履歴に登録して返します。
Mechanize::Form#click_button が内部で呼んでいるメソッドです。Form クラスのメソッドのほうが、メソッドチェーン等で短く記述できるので人気です。こちらのメソッドを無理して使う必要はないでしょう。
# 最初のボタン押す限り一緒 agent.submit(agent.page.forms[0], agent.page.forms[0].buttons[0]) agent.page.forms[0].click_button第 1引数 form は送信したいデータを含んでいる Mechanize::Form オブジェクトです。
第 2引数 button は Mechanize::Form::Button かその継承オブジェクトで、送信ボタンとして押すボタンを指定します。Mechanize::Form::Button#name と Mechanize::Form::Button#value の値が form の現在のデータに追加されて一緒に送られます。通常の Web ブラウザは送信ボタンのデータも一緒に送るので、極力ボタンは指定してください(Mechanize::Form#click_buttonなら自動で先頭のボタンを指定します)。
第 3引数 headers は追加の HTTP リクエストヘッダです。headers のキーは大文字小文字無関係の文字列です。Mechanize::Chain::CustomHeaders? で処理されるのでそちらを参照してください。
リファラは常に現在のページになります。変更は headers 引数で。
submit するフォームが GET で送信するよう作られていて、なおかつ form 要素の action 属性の値にクエスチョンマーク ? が 1文字でも含まれていた場合、それを記述ミスとみなして ? とそれ以降を削除したものを送信先 URLとして扱います。つまり
<form action="http://host/search?"> <input type="hidden" name="q" value="v"> </form>というフォームだった場合、http://host/search%3F?q=v でも http://host/search??q=v でもなく http://host/search?q=v と送信します。本当は action 属性値はすべて投稿先 URL(のpath)として扱わなければなりません。たいてい HTML 側で余分に ? を書いてしまった記述ミスですが、本当に http://host/search%3F?q=v のような URL を送信したい場合は Mechanize::Form#action= でパーセントエンコーディング済みの "search%3F" に書き換えます。
内部的なメソッドです。HTTP 送信メソッド verb で、url に向けてエンティティ文字列 entity を application/octet-stream で送ります。
結果のページが履歴に追加され、返り値として返ります。リファラは現在のページとなります。
options は #fetch_page メソッドへのオプションです。ヘッダ変更等したい場合は option で。
サーバアクセス時のヘッダや接続設定をまとめ、Net::HTTP 以下のオブジェクトを生成してアクセスし、取得したデータのヘッダなどを解析して処理するメソッドです。ユーザーが使うことはできません。
#pre_connect_hooks や #post_connect_hooks はこのメソッドの中で実行されます。
- #put メソッドの引数で使われる option
- #pre_connect_hooks や #post_connect_hooks に渡される手続きオブジェクトの引数
- params[:uri]
- アクセス先 URL の文字列か URI オブジェクトです。Mechanize::Chain::URIResolver 内で絶対 URI に設定されます。
- params[:params]
- #get メソッドなどで使われる、送信クエリのハッシュまたは「配列の配列」です。Mechanize::Chain::ParameterResolver? 内で連結された送信用文字列に変換されます。
- params[:headers]
- #get メソッドなどで指定可能な、追加リクエストヘッダのハッシュです。Mechanize::Chain::CustomHeaders? 内で、Mechanize の作ったヘッダを上書きします。
- params[:referer]
- 送信時のリファラを表す URI オブジェクトか URL 文字列か Page オブジェクトです。Mechanize::Chain::HeaderResolver? 内で Referer: リクエストヘッダにセットされます。
- params[:verb]
- 送信メソッドを表す Symbol です。:get、:post、:head、:put、:delete の中から選ばれています。省略時は :get になります。
- params[:request]
- params[:verb] に応じた Net::HTTP::Get などのサーバアクセス用オブジェクトが格納されます。 Mechanize::Chain::RequestResolver? 内で生成されます。
- params[:response]
- サーバからの Net::HTTPResponse のオブジェクトが格納されます。Mechanize::Chain::ResponseBodyParser? あたりで生成されます。
- params[:connection]
- Net::HTTP オブジェクトが格納されます。Mechanize::Chain::ConnectionResolver の中で生成され、プロキシや Keep-Alive などが設定されます。
- params[:agent]
- Mechanize オブジェクトが指定されます。agent です。
- params[:redirects]
- リダイレクトの回数を一時保存する変数です。Mechanize 内で Location リダイレクトのカウントをします。
- params[:response_body]
- サーバから取得したファイルのボディ部です。gzip 展開済みです。
- params[:res_klass]
- サーバからのレスポンスコードを表す Net::HTTPOK などのクラスが格納されています。
流れとしてはこんな感じになります。
- 接続に必要なデータを Chain の Resolver らで実行&設定
- #pre_connect_hooks の中身を call
- 上記の全結果を持って net::http で接続
- サーバからの結果に対して #post_connect_hooks の中身を call
- 上記の結果を持って接続後処理の Chain の Resolver らを実行