WWW-Mechanize-1.02 > WWW::Mechanize

名前

WWW::Mechanize - Perlオブジェクト中のハンディWebブラウザ

VERSION

Version 1.02

    $Header: /cvsroot/www-mechanize/www-mechanize/lib/WWW/Mechanize.pm,v 1.129 2004/04/10 05:30:10 petdance Exp $

概要

WWW::Mechanize、あるいは縮めてMechはWebサイトとのやりとりの自動化を 助けます。これはリンク先やフォームデータの送信を含む、複数のページの取得を サポートします。取得したページはそれぞれ解析され、そのリンクやフォームが 抽出されます。リンクやフォームを選択し、フォームを埋め、次のページを取得 することが可能です。Mechは訪れたURLの履歴を保持しますので、これを問い あわせたり再訪することも可能です。

    use WWW::Mechanize;
    my $mech = WWW::Mechanize->new();

    $mech->get( $url );

    $mech->follow_link( n => 3 );
    $mech->follow_link( text_regex => qr/download this/i );
    $mech->follow_link( url => 'http://host.com/index.html' );

    $mech->submit_form(
        form_number => 3,
        fields      => {
            username    => 'yourname',
            password    => 'dummy',
        }
    );

    $mech->submit_form(
        form_name => 'search',
        fields    => { query  => 'pot of gold', },
        button    => 'Search Now'
    );

MechはWebアプリケーションのテストにも良くあいます。Test::HTML::Lint モジュールなど、Test::*の内の一つを使えば、取得したコンテンツを チェックし、testコールへの入力に使うことができます。

    use Test::More;
    like( $mech->content(), qr/$expected/, "Got expected content" );

ページ取得を行う度にそのURLはスタックに保持され、これを前後に移動 することができます。

    $mech->back();

ページ取得の過程をよりうまくコントロールしようと思ったら、以下の メソッドを使うことができます。follow_linksubmit_formは、 つまるところこれらの高レベルのラッパーです。

    $mech->follow( $link );
    $mech->find_link( n => $number );
    $mech->form_number( $number );
    $mech->form_name( $name );
    $mech->field( $name, $value );
    $mech->set_fields( %field_values );
    $mech->set_visible( @criteria );
    $mech->click( $button );

WWW::MechanizeはまさしくLWP::UserAgentのサブクラスであり、 LWP::UserAgentのどのメソッドも利用可能です。

    $mech->add_header($name => $value);

重要なリンク

コンストラクタと開始

new()

WWW::Mechanizeの新規オブジェクトを生成し、返します。 以下ではこのオブジェクトを'agent'と呼びます。

    my $mech = WWW::Mechanize->new()

WWW::Mechanizeのコンストラクタは、LWP::UserAgentのコンストラクタへの パラメータのうち2つを上書きします。

    agent => "WWW-Mechanize/#.##"
    cookie_jar => {}    # an empty, memory-only HTTP::Cookies object

コンストラクタにパラメータを渡すことで、この上書き値を変更することが できます。以下のようになります:

    my $mech = WWW::Mechanize->new( agent=>"wonderbot 1.01" );

cookie jarでのオーバーヘッドを避けたい時や、botにcookieを受け入れ させたくない時は、明示的にこれを禁止します。こんな感じです:

    my $mech = WWW::Mechanize->new( cookie_jar => undef );

以下はWWW::Mechanizeが認識できるパラメータです。 これらはLWP::UserAgentが認識するパラメータには含まれていません。

  • autocheck => [0|1]

    ここのリクエストについてそれが成功していそうか否かをチェックします。 これはあなたが自分でマニュアルでチェックすることによるトラブルを防ぎ ます。エラーが見つかれば、それはワーニングではなくエラーになります。 デフォルトはオフです。

  • onwarn => \&func()

    Carp::carpのようなwarn互換の、ワーニングを表示する必要が あるときに呼び出される関数へのリファレンスです。

    ここにundefが設定されると、ワーニングはまったく表示されなくなります。 とはいえ、その振る舞いを制御するのにquietを使うよりは良いでしょう。

    この値が渡されなければ、MechはCarpがインストールされていれば Carp::carpを、そうでなければCORE::warnを使用します。

  • onerror => \&func()

    Carp::croakのようなdie互換の、知恵意的なエラーが発生した 際に呼び出される関数へのリファレンスです。

    ここにundefが設定されると、エラーはまったく表示されなくなります。

    この値が渡されなければ、MechはCarpがインストールされていれば Carp::croakを、そうでなければCORE::dieを使用します。

  • quiet => [0|1]

    ワーニングを出しません。quiet => 1に設定するのと、 $agent->quiet(1)を呼び出すのは同じです。デフォルトではオフです。

$mech->agent_alias( $alias )

実際にユーザーが渡した文字列からバージョンなどを拡張したものをuser agentに設定します。$aliasには以下のうち一つを使用できます。

  • Windows IE 6

  • Windows Mozilla

  • Mac Safari

  • Mac Mozilla

  • Linux Mozilla

  • Linux Konqueror

すると、最も関連深いものの一つに置き換えられます。例えば、

    $mech->agent_alias( 'Windows IE 6' );

ではUser-Agentは以下に設定されます。

    Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)

適切な別名の一覧はknown_agent_aliases()から返されます。

known_agent_aliases()

Mechが知っている全てのエージェントの別名のリストを返します。

ページ取得メソッド

$mech->get($url)

URL/URIを与えられると、それを取得します。HTTP::Response オブジェクトが帰り値です。$urlは適切に整形されたURL文字列か、 URIオブジェクトです。

この結果はagentオブジェクトに内部的に保持されますが、それを知っている 必要はありません。以下にリストされているアクセッサを使うだけです。 内部の詮索はしないように祈りますし、サブジェクトは将来変更されます。

get()LWP::UserAgentのメソッドをよりよい振る舞いをするように オーバーライドしたバージョンです。これは

    $mech->get( $url, ":content_file"=>$tempfile );

のようなことを可能にしますし、このパラメータが適当にフィルタされて 取得されることとみなして構いません。

$mech->reload()

ブラウザのリロードボタンのように振舞います: 現在のリクエストを 再実行します。

リロードによるHTTP::Responseオブジェクトか、まだリクエストが実行 されていない時は現在のリクエストがない時にはundefを返します。

$mech->back()

ブラウザの"back"ボタンを叩くのと等価です。前のページに戻ります。 過去の最初のページに戻りたくはありませんか?(実際、それが可能だと したらそうするでしょう?)

リンク追跡メソッド

$mech->follow_link(...)

そのページの指定されたリンクをたどります。find_link()で使うのと 同じパラメータを使い、それにマッチするものを指定します。

以下がその例です:

  • "download"と名づけられた3番目のリンク

        $mech->follow_link( text => "download", n => 3 );
  • 大文字小文字を区別せず、"download"をURL中に含む最初のリンク:

        $mech->follow_link( url_regex => qr/download/i );

    または

        $mech->follow_link( url_regex => qr/(?i:download)/ );
  • ページ内の3番目のリンク

        $mech->follow_link( n => 3 );

リンクが見つかれば、GETメソッドの実行結果(HTTP::Response オブジェクト)が返されます。ページ内にリンクがないか、または指定された リンクが見つからなかった時は、undefを返します。

このメソッドは、将来の開発では使用されない$mech->follow()の置き 換えにあたります。

フォームフィールド入力メソッド

$mech->form_number($number)

ページ中のnumber番目のフォームを副手順でfield()click()で呼び出す際のターゲットとして選択します。返り値も選択 されたフォームです。選択されたものが存在しない場合には、ワーニングを 出し、undefを返します。フォームは1番からインデックスが付けられるので 最初のフォームは0ではなく、1です。

$mech->form_name($name)

フォームを名前で選択します。ページ上にその名前のフォームが複数ある 時は、そのうち最初のものが選択され、ワーニングが生成されます。 通常はフォームそれ自体を、見つからなかった時にはundefを返します。

この機能はlibwww-perl 5.69以降を必要としますのでご注意ください。

$mech->field( $name, $value, $number )

$mech->field( $name, \@values, $number )

フィールド名を受け取り、指定された値をそこにセットします。これは 現在のフォーム(form()で設定されたものか、デフォルトである ページ内の最初のフォーム)に適用されます。

オプションの$numberパラメータは、2つ以上の同じ名前のフィールドが ある時に、それらを区別するのに使われます。フィールドは1から番号が ふられます。

$mech->set_fields( $name => $value ... )

このメソッドはフォームの複数のフィールドを設定します。これはフィールド 名と値のペアのリストを引数に取ります。もし同じ名前のフィールドが複数 あれば、そのうち最初に見つかったものに値がセットされます。この複製 されたフィールドのいずれかを選択したいときは、値として、値と番号の 2つの要素をもつ無名配列を使用します。

        # set the second foo field
        $mech->set_fields( $name => [ 'foo', 2 ] ) ;

フィールドは1から番号がふられます。

これは現在のフォーム(form()で設定されたものか、デフォルトである ページ内の最初のフォーム)に適用されます。

$mech->set_visible( @criteria )

このメソッドはフォームフィールドを、そのフィールド名を知る必要なく セットします。したがって、もしユーザー名とパスワードを要求するログイン 画面があるなら、そのフィールド名を知るためにフォームを取得してソース から調査する(あるいはWWW::Mechanizeといっしょにインストールされる mech-dumpを使う)必要はありません; こう命じるだけで

    $mech->set_visible( $username, $password ) ;

これにしたがって、1番目と2番目のフィールドがセットされます。この メソッドは、可視(visible)フィールドのみに働くので、set_visibleと 呼ばれます; 不可視(hidden)のフォームインプットは無視されます。 フィールドの順番はHTMLソース中に出てくる順番と同じで、多くの場合は ページ上で見える順番と同じですが、テーブルを使ったクリエイティブな デザインでは異なることがあることは警告しておきます。

@criteriaの個々の要素はフィールド値またはフィールド指定値です。 フィールド値はスカラです。フィールド指定値では値をセットしたい フィールドのタイプを指定でき、二つの要素をもつ配列リファレンスで 表わされます。したがって、最初のラジオボタンを次のように指定できます

    $mech->set_visible( [ radio => "KCRW" ] ) ;

フィールド値とフィールド指定値は混在させることができ、したがって

    $mech->set_visible( "fred", "secret", [ option => "Checking" ] ) ;

は1、2番目のフィールドを"fred"と"secret"に、そして次のOPTION メニューフィールドを"Checking"にセットします。

フィールド指定値のタイプには以下を使用できます: "text"や"password"、 "hidden","textarea"、"file"、"image"、"submit"、"radio"、"checkbox"、 "option"。

$mech->tick( $name, $value [, $set] )

現在のフォーム中の、その名前と値を持つ最初のチェックボックスに '印を 付け(Ticks)' ます。その値を持つ名前月のチェックボックスがない時は dieします。オプションの三番目の引数でFalseの値を渡すと、チェック ボックスは印がはずされます。

$mech->untick($name, $value)

チェックボックスの印をはずします。tick($name,$value,undef)の短い 書き方です。

フォーム送信メソッド

$mech->click( $button [, $x, $y] )

ボタンをクリックする効果を持ちます。最初の引数は、クリックするボタンの 名前です。2番目と3番目の(オプションの)引数ではクリックする(x,y) 座標を指定できます。

フォーム上にボタンが一つしかなければ、引数なしで$mech->click()と するだけで、そのボタンをクリックしたことになります。

HTTP::Responseオブジェクトを返します。

$mech->click_button( ... )

フォーム上の名前、値、またはインデックスで指定されたボタンをクリック する効果をもちます。引数はキーと値のペアです。一つの名前、番号、または 値だけを指定しなければいけません。

TODO: この関数はテストされていません。

  • name => name

    nameという名前のボタンをクリックします。

  • number => n

    フォームのn番目のボタンをクリックします。

  • value => value

    値がvalueのボタンをクリックします。

  • x => x =item * y => y

    この(オプションの)引数でクリックする(x,y)座標を指定できます。

$mech->select($name, $value)

$mech->select($name, \@values)

selectフィールド名を与えると、その値を指定された値にセットします。 フィールドが<複数選択>ではなく、$valueが配列の時は、その 最後の値がセットされます。これは現在のフォーム(form()メソッドで セットされたものか、デフォルトではページの最初のフォーム)に適用され ます。

$mech->submit()

ボタンをクリックしないまま、そのページをsubmitします。実際には、どの ボタンもクリックされなかったことになります。

これは$mech->click("submit")の別名として使用されてきましたが、 今後、いずれかのバージョンでなくなるでしょう。

$mech->submit_form( ... )

このメソッドは、直前に取得したページのフォームを選択し、フィールドを 埋め、それをsubmitするためのものです。これはform_number/form_name、 set_fields、clickメソッドを一つの高レベルの呼び出しに結合したものです。 これの引数はkey/valueの組み合わせのリストで、そのいずれもオプション です。

  • form_number => n

    n番目のフォームを選択します(form_number()を呼びます)。この パラメータが指定されなかった場合、現在選択されているフォームが使用 されます。

  • form_name => name

    nameと名づけられたフォームを使用します(form_name()を呼び ます)。

  • fields => fields

    fieldsハッシュリファレンスの値でフィールド値をセットします (set_fields()を呼びます)。

  • button => button

    buttonボタンをクリックします(click()を呼びます)。

  • x => x, y => y

    click()にxおよびyの値をセットします。

フォームが選択されていない時は、最初に見つかったフォームが使用 されます。

buttonが渡されなかった時は、代わりにsubmit()メソッドが使われ ます。

HTTP::Responseオブジェクトを返します。

ステータスメソッド

$mech->success()

最後のリクエストが成功したか否かをtrue(1)かfalse(0)で返します。まだ リクエストを実行していなければ、falseを返します。

これは$mech->res->is_successをラップする便利な関数です。

$mech->uri()

現在のURIを返します。

$mech->response() / $mech->res()

現在のレスポンスをHTTP::Responseオブジェクトとして返します。

$mech->response()の短縮形です。

$mech->status()

レスポンス中のHTTPステータスコードを返します。

$mech->ct()

レスポンスのコンテントタイプを返します。

$mech->base()

現在のレスポンスのベースURIを返します。

$mech->content()

レスポンスのコンテントを返します。

$mech->forms()

リストコンテキストで呼ばれたときは、最後に取得したページ内で見つかった フォームのリストを返します。スカラーコンテキストのときは、これらの フォームの配列リファレンスを返します。これで返されるフォームはいずれも HTML::Formオブジェクトです。

$mech->current_form()

現在のフォームをHTML::Formオブジェクトとして返します。私は form()が既に存在してcurrent_formがセットされている場合を除いては こちらのform()を呼んでいます。

$mech->links()

リストコンテキストで呼ばれたときは、最後に取得したページ内で見つかった リンクのリストを返します。スカラーコンテキストのときは、これらの リンクの配列リファレンスを返します。これで返されるリンクはいずれも WWW::Mechanize::Linkオブジェクトです。

$mech->is_html()

現在のコンテントがHTMLか否かをHTTPヘッダーを元に判断して、trueまたは falseを返します。

$mech->title()

HTML::HeadParserの解析結果を元に、<TITLE>タグの内容を返します。 コンテントがHTMLではない場合はundefを返します。

コンテントハンドリングメソッド

$mech->find_link()

このメソッドは現在取得されているページ内のリンクを検索します。これは そのリンクについて記述しているWWW::Mechanize::Linkオブジェクトを 返します。(きっとURLの記述より、こちらに魅力を覚えるでしょう。) リンクが見つからなかったときにはundefを返します。

URL部分を取り出し、get()メソッドに渡すことができます。もしこれを したいのであれば、直接follow_link()メソッドを呼ぶのも良い でしょう。これは、自動的にget()を実行します。

<FRAME SRC="...">タグはHTMLとして解析され、リンクとして扱われ ますので、このメソッドを使えることを覚えておいてください。

以下のkey/valueの組み合わせを一つまたは複数渡すことで、リンクを選択 することができます:

  • text => string および text_regex => regex

    textは、stringと一致するテキストのリンクにマッチします。正確に "download"というテキストを持つリンクを選択するには、以下のようにします

        $mech->find_link( text => "download" );

    text_regexは、regexに該当するテキストのリンクにマッチします。 大文字小文字を問わず、"download"というテキストが含まれるリンクを選択 するには、以下のようにします

        $mech->find_link( text_regex => qr/download/i );

    ページのリンクから抽出されたテキストはトリムされることに注意して ください。<a> foo </a>は'foo'として保持され、先頭および末尾の 空白の検索は失敗します。

  • url => string および url_regex => regex

    stringまたはregexに該当するURLのリンクにマッチします。 このURLは、そのページのコードによっては、foo/bar.htmlのような相対 URLかも知れません。

  • url_abs => string および url_abs_regex => regex

    リンクの絶対URLを、stringまたはregexに対して代わりにマッチング します。このURLは、ページ中では相対URLであるとしても、絶対URLになり ます。

  • name => string および name_regex => regex

    stringまたはregexに該当する名前のリンクにマッチします。

  • tag => string および tag_regex => regex

    stringまたはregexに該当するタグのリンクにマッチします。 tag_regexはおそらく、以下のように複数のタグをチェックするのに最も 便利でしょう:

        $mech->find_link( tag_regex => qr/^(a|img)$/;
  • n => number

    n番目のリンクにマッチします。

    nパラメータは、上述の他のパラメータと番号を指定するために組み 合わせることができます。たとえば、text => "download", n => 3 では"download"というテキストに一致する3番目のリンクが検索されます。

nが指定されなかった場合、デフォルトは1です。したがって、もし一切 パラメータを指定しなかった場合には、このメソッドはデフォルトで ページ中の最初のリンクを検索します。

複数のテキストまたはURLパラメータを指定でき、これらはすべてand条件 として扱われることを覚えておいてください。例えば、テキストが"News"で、 URLに"cnn.com"を含む最初のリンクを探すには、以下のようにします:

    $mech->find_link( text => "News", url_regex => qr/cnn\.com/ );

$mech->find_link() : link format

$self->content中のリンクに対応するWWW::Mechanize::Link オブジェクトをすべて含んだ配列リファレンスが返り値です。

リンクは、以下から取得されます:

<A HREF=...>
<AREA HREF=...>
<FRAME SRC=...>
<IFRAME SRC=...>

$mech->find_all_links( ... )

判定基準にマッチするすべてのリンクを返します。このメソッドへのリンク の判定基準の指定方法は、find_link()と同じです。すべてのリンクは WWW::Mechanize::Linkとして返されます。

リストコンテキストでは、find_all_links()はリンクのリストを返します。 そうでなければ、リンクのリストへのリファレンスを返します。

find_all_links()をパラメータなしで呼ぶと、ページ中のすべての リンクが返されます。

その他のメソッド

$mech->add_header( name => $value [, name => $value... ] )

エージェントにHTTPリクエスト時に追加または削除するhttpヘッダーを設定し ます。

    $mech->add_header( Encoding => 'text/klingon' );

もしvalueundefであれば、そのヘッダーは以降のリクエストでは削除 されます。例えば、Refererヘッダーをもう送らないようにするには:

    $mech->add_header( Referer => undef );

もしヘッダーを削除したいのであれば、delete_headerを使います。

追加された名前/値の組み合わせの個数を返します。

NOTE: このメソッドは1.00以前のWWW::Mechanizeとは異なります。 以前は、ヘッダーはオブジェクトインスタンスのメンバーではなく、パッケー ジのハッシュに保持されました。add_header()の呼出しは、仮にそのオブ ジェクトがすぐになくなる場合でも、全てのWWW::Mechanizeオブジェクトの ヘッダーを変更しました。

$mech->delete_header( name [, name ... ] )

Removes HTTP headers from the agent's list of special headers. For instance, you might need to do something like:

    # Don't send a Referer for this URL
    $mech->add_header( Referer => undef );

    # Get the URL
    $mech->get( $url );

    # Back to the default behavior
    $mech->delete_header( 'Referer' );

$mech->quiet(true/false)

画面へのワーニングを抑制することができます。

    $mech->quiet(0); # ワーニングを有効にします (デフォルト)
    $mech->quiet(1); # ワーニングを無効にします
    $mech->quiet();  # 現在のquiet設定状態を返します

LWP::UserAgentメソッドのオーバーライド

$mech->redirect_ok()

LWP::UserAgentredirect_ok()をオーバーライドしたバージョンです。 このメソッドはリダイレクションを追跡すべきか否かを判定するために 使われます。

$mech->request( $request [, $arg [, $size]])

LWP::UserAgentrequest()をオーバーライドしたバージョンです。 現在のリクエストを実行します。通常は、WWW::Mechanizeを使っていれば、 このようなレベルで作業し様とはまったく思わないでしょうから、こう すべきでしょう

$requestが修正されていることは覚えておいてください。

HTTP::Responseオブジェクトを返します。

$mech->update_html( $html )

mechが見つけたHTMLを置き換えることができます。リンクやフォームを更新 します。

もし不恰好な出力をされたページを持っており、更新する気があるというので あればリンクは正しい形で出てくるでしょう:

    my $html = $mech->content;
    $html =~ s[</option>.?.?.?</td>][</option></select></td>]isg;
    $mech->update_html( $html );

$mech->_parse_html()

HTMLドキュメントから得られるフォームとリンクを初期化する内部メソッド です。もしサブクラスでこれをオーバーライドしたり、複数回これを呼び出し たくなったら、どうぞそうしてください。

$mech->_modify_request( $req )

ずたずたに切り裂かれた内部ヘッダによってリクエストを編集します。

$mech->_make_request()

WWW::Mechanize::Cachedのように、サブクラスでリクエストを中断させる のに便利なメソッドです。

使用が推奨されないメソッド

このメソッドはより正しく柔軟なメソッドで置き換えられています。そちら 代わりにお使いください。

$mech->follow($string|$num)

非推奨になっており、より柔軟なfollow_link()を使うことが 勧められます。

リンクを追跡します。文字列を与えれば、そのテキストがこの文字列にマッチ する最初のリンクが追跡されます。番号を与えれば、ページ中の $num番目のリンクになります。リンクは0から始まることに注意して ください。

ページ中にリンクが見つかればtrueを、そうでなければundefを返します。

$mech->form($number|$name)

非推奨になっておりform_name()またはform_number()を 使うことが勧められます。

渡されたのが数字だけの文字列か否かによって、フォームを番号または名前で 選択します。これは、もし数字だけの名前をもつフォームがあった場合に、 このメソッドは正しく動かないかも知れないことを意味しています。

内部使用限定のメソッド

これらのメソッドは内部でのみ使われます。これらについて知る必要は多分 ないでしょう。

$mech->_reset_page()

ページを解析した際のガラクタのような内部フィールドをリセットします。

$mech->_extract_links()

Webページの今テントからリンクを抽出するもので、WWW::Mechanize::Link{links}プロパティを一般化します。

$mech->_push_page_stack() / $mech->_pop_page_stack()

エージェントは訪れたページをスタックしており、BACKの際など必要になった 時にはこれで取り出します。

現在のページは新しいページを取得する前にスタックに追加されなければ いけませんし、BACKが発生した際にはスタックから取り出されなければ いけません。

どちらも引数を与えられても、$mechオブジェクトを操作します。

warn( @messages )

Fatalでない問題と診断用のための、中心となるワーニングメソッドです。 デフォルトではCORE::warnを呼びますが、コンストラクタでonwarnを セットすることで上書きできます。

die( @messages )

中心となるエラーメソッドです。デフォルトではCORE::dieを呼びますが、 コンストラクタでonerrorをセットすることで上書きできます。

この他のドキュメント

Spidering Hacks, by Kevin Hemenway and Tara Calishain

O'Reilly(http://www.oreilly.com/catalog/spiderhks/)刊の Spidering Hacksはscreen-scrapingとspideringについてもっと知りたい 人にとってすばらしい本です。

この本には6つのMechハックおよびMechの派生物があります:

#21 WWW::Mechanize 101
#22 Scraping with WWW::Mechanize
#36 Downloading Images from Webshots
#44 Archiving Yahoo! Groups Messages with WWW::Yahoo::Groups
#64 Super Author Searching
#73 Scraping TV Listings

この本はSlashdotで積極的にレビューされています: http://books.slashdot.org/article.pl?sid=03/12/11/2126256

Web上のリソース

その他のMechanizeを使用するモジュール

以下はMechanizeを使用しているかサブクラスになっているモジュールです。 他にあれば教えてください:

要望とバグ

要望や示唆、バグ(ヤバッ!)は http://rt.cpan.org/ のRTバグ トラッキングシステムか、 bug-WWW-Mechanize@rt.cpan.org へのemailで 報告してください。これは私が追跡するのを簡単にしてくれます。

http://rt.cpan.org/NoAuth/Bugs.html?Dist=WWW-Mechanize はMechanize へのRTキューです。あなたのバグが既に報告されていないか見るにはこちらを チェックしてください。

Author

Copyright 2004 Andy Lester <andy@petdance.com>

Artistic Licenseに基づきリリースされています。 Kirrily RobertのすばらしいWWW::Automateパッケージをベースにしました。