Ruby の Mechanize の wiki のよてい

Mechanize::Page



「サーバから取得した HTML」を表すクラスです。サーバから取得したファイルが HTML、XHTML、WAP だったときに返り値にこのクラスのオブジェクトが使用されます。
HTML 構造を解析した結果を内部で保持しています。

フォームを条件で探して操作したいときは #form_with メソッドを、
# <form name="f1"> なフォームを探してブロックに渡す
agent.page.form_with(;name => 'f1'){|form|
  form....
リンクを条件で探して操作したいときは #links_with メソッドを使用します。
# <a href="./top.html>戻る</a> なリンクを探してブロックに渡す
agent.page.link_with(;:text => '戻る'.toutf8){|link|
  link....

文字エンコーディングとパースの失敗について

(←クリックで展開) すべての Page オブジェクトには文字エンコーディングが設定されています。


Mechanize 1.0.0 の標準で Page クラスが使用される HTTP ヘッダの Content-Type の値は以下の通りです。HTML と XHTML と XHTML MP になります。
  • text/html
  • application/xhtml+xml
  • application/vnd.wap.xhtml+xml
HTML/XHTML/XHTMP WP 以外のファイル、たとえばプレーンテキストや普通の XML、画像ファイルなどは Mechanize::File クラスのオブジェクトになります。Page クラスで扱いたい Content-Type を増やしたい場合は Mechanize::PluggableParser を参照してください。
Mechanize::File を継承しています。


Mechanize::Page.new(uri=nil, response=nil, body=nil, code=nil, mech=nil){|page| optional_non_ensure_block}

ページを表す Mechanize::Page オブジェクトを生成します。ユーザーが使用することは通常ありません。
4つの引数に関しては継承もとの Mechanize::File.new を参照してください。
この Page.new の response 引数には、HTML であることを確定するために {'content-type' => 'text/html'} が必須です。ヘッダ名は小文字を推奨します。「空のページ」等の作成は、ヘッダがなくても動作する継承もとの Mechanize::File.new が簡便なのでお勧めです。
File に無かった 第 5引数の mech はこのページのリンクのクリックやフォーム送信に使用する Mechanize オブジェクトです。これを指定しないとこのクラスのメソッドからサーバアクセスができないので実質必須です。
よく使われる記述は以下のようなものです。
# example.com.html の内容を http://example.com/ のページとみなす
page = Mechanize::Page.new(
                           URI.parse('http://example.com/'),
                           {'content-type' => 'text/html'},
                           File.open('example.com.html', 'rb'){|f| f.read},
                           '200',
                           agent)
# 自作のページを履歴に登録する
agent.__send__(:add_to_history, page)
agent.page.uri #=> http://example.com/
第 2引数 response の content-type の値に text/html か application/xhtml+xml か application/vnd.wap.xhtml+xml が含まれていない場合、Mechanize::ContentTypeError? が発生します。

引数の条件に該当する HTML ノードを #parser から探し、合致する最初のものをひとつ返します。
parser.at(xpath_or_css) を行っています。Mechanize#html_parser がパースで返すオブジェクトの at メソッドの解説を参照してください。
デフォルトパーサの Nokogiri の場合、XPath か CSS3 記法で HTML のノード検索ができます。

サーバから取得した HTML(やXHTMLなど)を返します。
継承元の Mechanize::File#body を参照してください。
文字エンコーディング自体は変化していませんが、Ruby1.9 の場合、ASCII-8BIT に force_encoding されています。内部処理上はこれでも問題ないのですが、外部から Page#body として利用するような場合は気をつけてください。

このファイルをサーバから取得した際のリザルトコードを "200" などの 3桁の数字の文字列で返します。
継承元の Mechanize::File#code を参照してください。

alias #body

#response から "content-type" という小文字キーを探し、その値の文字列を返します。存在しない場合は nil を返します。
通常、レスポンスヘッダの Content-Type ヘッダの値が返ります。charset トークンなどもそのまま返されます。
Content-Type: text/html; charset=utf-8
というレスポンスヘッダだった場合、この content_type メソッドは "text/html" ではなく "text/html; charset=utf-8" という文字列を返します。

#parser のパース時に使用した(とparserが主張する)文字エンコーディング名を文字列で返します。
Mechanize#html_parser が Nokogiri ではない場合、nil が返ります。
HTML に meta charset
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
が存在した場合はおおむねそれと同じものが返りますが(例の場合"UTF-8")、トラブル時にはこの meta charset を読む行為ごとミスってることが多いので、パースのトラブル時の原因究明にはあまり向きません。実際の HTML の値が必要な場合は人力で直接 HTML に当たってください。再設定は #encoding= で行います。

HTML をパースするのに妥当な文字エンコーディングの値を明示的に文字列で再設定し、#parser を更新します。
agent.get(x_sjis_html)
p agent.page.encoding #=> "x-sjis"
agent.page.encoding = 'CP932'
p agent.page.encoding #=> "CP932"
引数 encoding_name は iconv にそのまま渡されるので、Mechanize の動作しているマシンにインストールされている iconv が解釈可能で動作可能なエンコーディング名をうまく指定してください。CP932 や EUC-JP、ISO-2202-JP、UTF-8、Windows-1252 などはおそらくどんな環境でも有効でしょう(iconvでのShift_JISは´↓澂舛覆匹粒板ナ源を含んでいないのでエラーになります。CP932を指定してください)。
文字エンコーディング指定後、その新しい文字エンコーディングを使用して #parser が更新されます。ただし、引数 encoding_name が #encoding の返り値の文字列を大文字小文字無視で含んでいる場合(/#{encoding}/i =~ encoding_name)、再パースは行われません。
どんな場合でも必ず encoding_name とみなして再パースを行って欲しいという場合は、事前に手動でインスタンス変数 @parser を消去します。
agent.page.instance_variable_set(:@parser, nil)
agent.page.encoding = "Iconv的に正しいHTMLの文字エンコーディング名"
また、再パースしても既存のフォームやリンクを保持したインスタンス変数はリセットされません。#forms#links などがページの返り値表示時に呼ばれてしまう irb で時々問題になります。なにか問題が起きた場合は該当するインスタンス変数を instance_variable_set で nil にするか、該当インスタンス変数の生成自体をなんとかして抑制してください。
irb> agent.get(bad_uri)
(formsやlinksの結果がinpsectで自動表示される)
irb> agent.page.encoding = 'correct encoding'
irb> agent.page.links... # @links が再パース前にセットされているので昔の変なまま
irb> agent.history.clear
irb> agent.get(bad_uri); nil
irb> agent.page.encoding = 'correct encoding'
irb> agent.page.links... 
form_with(pattern){|tgt| optional_non_ensure_block}

{メソッド名 => 返り値} という条件を満たす Mechanize::Form オブジェクトを #forms から探し、最初のものを返します。
動作は Mechanize::Form#xxxx_with を参照してください。

有効なメソッドと値のペアは Mechanize::Form のメソッドと返り値になります。
# name が f1 なフォームを探してブロックに渡す
agent.page.form_with(:name => 'f1'){|form|
  form.field_with...
}
# action 属性が /search なフォームを探す
form = agent.page.form_with(:action => '/search')

#parser から form 要素を検索し、出現順に Mechanize::Form オブジェクトにして配列で返します。
form 要素が無かった場合は空の配列 [] を返します。
内部変数 @forms に配列がキャッシュされているので、このメソッド使用後に #parser が更新されても反映されません。
条件による抽出は #form_with#forms_with で行うことができます。
forms_with(pattern){|tgt| optional_non_ensure_block}

{メソッド名 => 返り値} という条件を満たす Mechanize::Form オブジェクトを #forms から探し、全てを配列で返します。
動作は Mechanize::Form#xxxxs_with を、条件については #form_with を参照してください。
frame_with(pattern){|tgt| optional_non_ensure_block}

{メソッド名 => 返り値} という条件を満たす Mechanize::Page::Frame オブジェクトを #frames から探し、最初のものを返します。
動作は Mechanize::Form#xxxx_with を参照してください。
有効なメソッドと値のペアは Mechanize::Page::Frame のメソッドと返り値になります。
# src が left.html で指し示されるフレームの HTML を取得
agent.page.frame_with(:src => 'left.html').click
# name が left であるフレームの HTML を取得
agent.page.frame_with(:name => 'left').click

#parser から frame 要素を検索し、出現順に Mechanize::Page::Frame オブジェクトにして配列で返します。
frame 要素が無かった場合は空の配列 [] を返します。
内部変数 @frames に配列がキャッシュされているので、このメソッド使用後に #parser が更新されても反映されません。
条件による抽出は #frame_with#frames_with で行うことができます。
frames_with(pattern){|tgt| optional_non_ensure_block}

{メソッド名 => 返り値} という条件を満たす Mechanize::Page::Frame オブジェクトを #frames から探し、全てを配列で返します。
動作は Mechanize::Form#xxxxs_with を、条件については #frame_with を参照してください。
iframe_with(pattern){|tgt| optional_non_ensure_block}

{メソッド名 => 返り値} という条件を満たす Mechanize::Page::Frame オブジェクトを #iframes から探し、最初のものを返します(IFrameクラスというものはありません)。
動作は Mechanize::Form#xxxx_with を参照してください。
有効なメソッドと値のペアは Mechanize::Page::Frame のメソッドと返り値になります。
# src が inner.html で指し示されるインラインフレームの HTML を取得
agent.page.iframe_with(:src => 'inner.html').click

#parser から iframe 要素を検索し、出現順に Mechanize::Page::Frame オブジェクトにして配列で返します(IFrameクラスというものはありません)。
iframe 要素が無かった場合は空の配列 [] を返します。
内部変数 @iframes に配列がキャッシュされているので、このメソッド使用後に #parser が更新されても反映されません。
条件による抽出は #iframe_with#iframes_with で行うことができます。
iframes_with(pattern){|tgt| optional_non_ensure_block}

{メソッド名 => 返り値} という条件を満たす Mechanize::Page::Frame オブジェクトを #iframes から探し、全てを配列で返します(IFrameクラスというものはありません)。
動作は Mechanize::Form#xxxxs_with を、条件については #iframe_with を参照してください。
link_with(pattern){|tgt| optional_non_ensure_block}

{メソッド名 => 返り値} という条件を満たす Mechanize::Page::Link オブジェクトを #links から探し、最初のものを返します。
動作は Mechanize::Form#xxxx_with を参照してください。

有効なメソッドと値のペアは Mechanize::Page::Link のメソッドと返り値になります。
なお、Mechanize::Page::Link に name メソッドがないので、他の xxxx_with のように引数に文字列を渡すとエラーになります。
# href が index.html なリンクを探してクリック
agent.page.link_with(:href => 'index.html'){|link|
  link.click
}
# text の返り値が「ホーム」にマッチするリンクを探してクリック
agent.page.link_with(:text => /ホーム/).click # utf-8

#parser から a 要素と area 要素を検索し、Mechanize::Page::Link オブジェクトにして配列で返します。
a 要素も area 要素も無かった場合は空の配列 [] を返します。
出現順の a 要素の Link オブジェクトのあと、出現順の area 要素の Link オブジェクトが配列に入っています。何らかの理由で混合の出現順配列が欲しい場合は links.sort_by{|link| link.node} してください。
内部変数 @links に配列がキャッシュされているので、このメソッド使用後に #parser が更新されても反映されません。
条件による抽出は #link_with#links_with で行うことができます。
links_with(pattern){|tgt| optional_non_ensure_block}

{メソッド名 => 返り値} という条件を満たす Mechanize::Page::Link オブジェクトを #links から探し、全てを配列で返します。
動作は Mechanize::Form#xxxxs_with を、条件については #link_with を参照してください。

このページが含むリンクオブジェクトやフォームオブジェクトから Mechanize::Page::Link#click 等でアクセスを行う際に使用する Mechanize オブジェクトを返します。
デフォルトはこの Page オブジェクトが Mechanize::Page.new で作成されたときに引数で設定されたものです。設定されなかった場合は nil です。
nil である場合、Mechanize::Page::Link#click メソッドや Mechanize::Form#click_button メソッドによるリンクアクセスやフォームアクセスができなくなります(agent.click(agent.page.links[0]) 等は動作します)。
再設定は #mech= で行います。

#body を HTML パーサ Mechanize#html_parser でパースした結果の解析済みオブジェクトを返します。
デフォルトパーサの Nokogiri では Nokogiri::HTML::Document か Nokogiri::XML::Document クラスのオブジェクトが、オプショナルな Hpricot では Hpricot::Doc クラスのオブジェクトが返ります。
#encoding= にエンコーディング名の引数が渡されたとき、再パースが行われます。パース内容が間違っているときは #encoding= を使用してください。
Nokogiri を使用している場合、ページのパースに失敗したときはこの返り値の errors メソッドに各種エラーオブジェクトが格納されます。
puts agent.page.parser.errors
結果:
input conversion failed due to input error, bytes 0x87 0x40 0x87 0x41
input conversion failed due to input error, bytes 0x87 0x40 0x87 0x41
htmlCheckEncoding: encoder error
input conversion failed due to input error, bytes 0x87 0x40 0x87 0x41
encoder error

サーバから送られてきた HTTP レスポンスヘッダを Mechanize::Headers オブジェクトで返します。
継承元の Mechanize::File#response を参照してください。

alias #parser
save_as(filepath=nil)

#body をバイナリモードでファイルに保存します。
継承元の Mechanize::File#save_as を参照してください。

alias #save_as

引数の条件に該当する HTML ノードを #parser から探し、合致するものをすべて返します。
parser.search(xpath_or_css) を行っています。Mechanize#html_parser がパースで返すオブジェクトの search メソッドの解説を参照してください。
デフォルトパーサの Nokogiri の場合、XPath か CSS3 記法で HTML のノード検索ができます。

<title> に囲まれた文字列(title 要素)を返します。
<title> そのものが無い場合や囲まれた文字列が空の場合は nil を返します。
ただの inner_text なので、文字参照は解決されていますが前後の空白等は HTML で書かれたときのままです。
<html>
  <title>テスト
  </title>
</html>
という HTML だった場合、title メソッドは "テスト \n" を返します。
マルチバイト文字は Mechanize#html_parser が扱うエンコーディング(通常 UTF-8)で返ります。<title> が複数存在する不正な HTML の場合は単純に連結された結果を返します。
内部変数 @title に文字列がキャッシュされているので、このメソッド使用後に #parser が更新されても反映されません。
uri

このファイルを取得した際の最終的な URI オブジェクトを返します。
継承元の Mechanize::File#uri を参照してください。
/

alias #search

#parser から base 要素を検索し、出現順に Mechanize::Page::Base? オブジェクトにして配列で返します。
base 要素が無かった場合は空の配列 [] を返します。
内部変数 @base に配列がキャッシュされているので、このメソッド使用後に #parser が更新されても反映されません。
条件による抽出は #base_with#bases_with で行うことができますが、ユーザーが使用する機会はおそらくないでしょう。
base_with(pattern){|tgt| optional_non_ensure_block}

{メソッド名 => 返り値} という条件を満たす Mechanize::Page::Base? オブジェクトを #bases から探し、最初のものを返します。
動作は Mechanize::Form#xxxx_with を参照してください。
有効なメソッドと値のペアは Mechanize::Page::Base? のメソッドと返り値になります。
bases_with(pattern){|tgt| optional_non_ensure_block}

{メソッド名 => 返り値} という条件を満たす Mechanize::Page::Base? オブジェクトを #bases から探し、全てを配列で返します。
動作は Mechanize::Form#xxxxs_with を、条件については #base_with を参照してください。

サーバから取得して gzip 展開済みの HTML であったものを、引数の文字列で置き換えます。
継承元の Mechanize::File#body= を参照してください。
Ruby1.9 では #parser 内部の Nokogiri が HTML の Encoding を読むことがあるようなので、#encoding での二度手間を避けるためにもできれば正しい Encoding を設定した文字列を引数に指定してください。

このファイルをサーバから取得した際のリザルトコードを3桁の数字の文字列で再設定します。
継承元の Mechanize::File#code= を参照してください。

#save_as で引数なしのときに使用される保存用ファイルパスを返します。
継承元の Mechanize::File#filename を参照してください。

#save_as で引数なしのときに使用される保存用ファイルパスを文字列で設定します。
継承元の Mechanize::File#filename= を参照してください。

#parser から img 要素を検索し、出現順に Mechanize::Page::Image? オブジェクトにして配列で返します。
img 要素が無かった場合は空の配列 [] を返します。
内部変数 @images に配列がキャッシュされているので、このメソッド使用後に #parser が更新されても反映されません。
残念ながら条件による抽出を行う image_with のようなメソッドはありません。

#images に含まれる Image オブジェクトの Mechanize::Page::Image#url? メソッドの返り値を集め、重複を取り除いて配列で返します。
img 要素がページにない場合や、src 属性が空の img だけという嫌がらせがあった場合には空の配列 [] を返します。
内部変数 @image_urls に配列がキャッシュされているので、このメソッド使用後に #parser が更新されても反映されません。
残念ながら条件による抽出を行う image_url_with のようなメソッドはありません。

#parser から label 要素を検索し、出現順に Mechanize::Page::Label? オブジェクトにして配列で返します。
label 要素が無かった場合は空の配列 [] を返します。
内部変数 @labels に配列がキャッシュされているので、このメソッド使用後に #parser が更新されても反映されません。
残念ながら条件による抽出を行う label_with のようなメソッドはありません。Mechanize がラベルを検索する際に使用されるメソッドで、ユーザーが使用することはないでしょう。

ラベル文字列とLabelオブジェクトの対応を表す Hash を返します。
Mechanize がラベルを検索する際に使用されるメソッドで、ユーザーが使用することはないでしょう。

このページから #click 等でアクセスを行う際に使用する Mechanize オブジェクトを再設定します。
設定を行わなかった場合は #mech の値が使用されます。
通常はページ作成時に指定されており、再設定する必要はありません。

#parser から meta 要素を検索し、その中から http-equiv="refresh" なものを Mechanize::Page::Meta オブジェクトにして配列で返します。
上記のいわゆる「リフレッシュ用の meta タグ」が無かった場合は空の配列 [] を返します。
今のところ「リフレッシュ用の meta タグ」以外を解釈することはありません。メソッド名も metas ではなく meta です。
内部変数 @meta に配列がキャッシュされているので、このメソッド使用後に #parser が更新されても反映されません。
残念ながら条件による抽出を行う meta_with のようなメソッドはありません。

サーバから送られてきた HTTP レスポンスヘッダを Hash か Mechanize::Headers で再設定します。
クラス分けは確定してしまっているので、このメソッドでレスポンスヘッダを変更しても Mechanize の挙動に変化はありません。
継承元の Mechanize::File#response= を参照してください。

このファイルを取得した際の最終的な URI オブジェクトを再設定します。
継承元の Mechanize::File#uri= を参照してください。
×

この広告は60日間更新がないwikiに表示されております。

管理人のみ編集できます