Walrus,Digit. | 一覧 | 検索 | 更新履歴(RSS) | 新規作成
はてなブックマークに追加 はてなブックマークを表示 編集 | 編集(管理者用) | 差分

Perlモジュール/WWW::Mechanize

編集

複数ページを経由しての作業に強いLWP::UserAgentのサブクラス。 ダウンロードはCpanModule:WWW::Mechanizeから。

ドキュメント

編集

ドキュメント和訳。 CpanModule:WWW-Mechanize-1.02を原文にしています。

■ tarボール

■ pod2htmlによるHTMLファイル

■ podファイル

 perldoc.jpへの登録は、白井さんがしてくださいました。ありがとうございました。

旧版(0.70版)のドキュメント

CpanModule:WWW-Mechanize-0.70を原文にしています。 1.02版のドキュメントの和訳が終わりましたので、旧版の分はダウンロード用のtarボールのみを残しておきます。

■ tarボールとメタファイル

最近のサンプルスクリプト

以下は、他サイトに掲載されている有用なWWW::Mechanize使用例です。 私自身、「Amazon アフィリエイトレポート」を見て、本当にこのWWW::Mechanizeを使おう、と思いました。

Yahooニュースの今日の記事一覧を取得。

指定したカテゴリの、今日の一覧を取得。 「次のページ」も追いかけて処理します。

use strict;
use WWW::Mechanize;

my $url = 'http://headlines.yahoo.co.jp/hl';
my $cate_label = 'コンピュータ一覧';
my $next_label = '次のページ';
my @links;

# トップページの取得
my $mech = WWW::Mechanize->new();
$mech->get( $url );

# 指定カテゴリの一覧の取得
$mech->follow_link('text_regex' => qr/\Q${cate_label}\E/);
push(@links, $mech->find_all_links('url_regex' => qr/hl\?a=/));

# 「次のページ」があれば処理
while ( $mech->follow_link(text_regex => qr/\Q${next_label}\E/) ) {
	push(@links, $mech->find_all_links(url_regex => qr/hl\?a=/));
}

# 出力
foreach my $link (@links) {
	printf("%s [%s]\n", $link->text, $link->url);
}

mixiへの日記の投稿

カレントディレクトリの diary.txt を読み込み、1行目をタイトル、2行目以降を本文としてmixiの日記に追加します。

スクリプト中の$mailと$passはそれぞれ、自分のmixiログ引用のメールアドレスとパスワードをセットしてください。 スクリプトと日記ファイル diary.txt は、どちらもeucコードで保存してください。

WWW::Mechanizeのサンプルとしては、refreshを自動で処理させている部分がポイントかも。ログインプロセスの作りとしては、最近良く使われる「cookie設定してrefresh」なのですが、これを自動で追ってはくれませんでした。

use strict;
use WWW::Mechanize;
use Data::Dumper;
$Data::Dumper::Indent = 1;

my $url = 'http://mixi.jp/home.pl';
my $mail = 'mail@address';
my $pass = 'password';

sub message { print @_; }
sub abort { &message(@_); exit 8; }

# 日記の読み込み
my $diary_file = './diary.txt';
&abort("${diary_file}がありません") unless (-f $diary_file);
&message("${diary_file}読み込み中\n");
open(IN, $diary_file);
my $subject = <IN>;
my $content = join('', <IN>);
close(IN);
$subject =~ s/\s+$//;

# トップページの取得
&message("トップページ取得中\n");
my $mech = WWW::Mechanize->new();
my $response = $mech->get( $url );
&abort(Dumper($response)) unless ($mech->success);

# ログイン
&message("ログイン中\n");
$mech->form_number(1);
$mech->set_fields('email' => $mail, 'password' => $pass);
$response = $mech->submit;
&abort(Dumper($response)) unless ($mech->success);

while ($response->header('refresh')) {
	my $refresh = $response->header('refresh');
	&message("リフレッシュ($refresh)の処理中\n");
	if ($refresh =~ /url=([^\s;]+)/) {
		$response = $mech->get(URI->new($1, $mech->uri));
		$refresh = $mech->uri;
	} else {
		$response = $mech->reload;
	}
	&abort(Dumper($response)) unless ($mech->success);
}

# 日記ページに移動
&message("日記ページに移動中\n");
$response = $mech->follow_link(url_regex => qr/list_diary.pl/i);
&abort(Dumper($response)) unless ($mech->success);

# 日記の追加ページへ移動
&message("日記の追加ページに移動中\n");
$response = $mech->submit;
&abort(Dumper($response)) unless ($mech->success);

# タイトルと本文をセットして確認画面へ
&message("日記を送信中\n");
$mech->set_visible($subject, $content);
$response = $mech->submit;
&abort(Dumper($response)) unless ($mech->success);

# 投稿
&message("日記を投稿中\n");
$response = $mech->click_button('value' => ' 作  成 ');
&abort(Dumper($response)) unless ($mech->success);

# 終了
&message("終了\n");
exit 0;

余談ですけど、cookieさえセットされていれば他のページには移動できるので、follow_linkメソッドは捨てて直接getメソッドを使う分には、refreshに付き合ってやる必要はないようです。

Windowsのコマンドプロンプトのようにeucコードの出力が化けてしまうときには、messgeサブルーチンでメッセージをすべてsjis等に変換してから出力するように修正するのが簡単でしょう。

WWW::MechanizeのFAQ

WWW::Mechanizeで「https://」で始まるSSL使用サイトにアクセスできますか?

できます。実際にAmazonアフィリエイトレポートはSSLアクセスを使用しています。

WWW::Mechanizeは、Webページの取得にはLWPを使用しているので、LWPでアクセスできれば良いということになります。このため、Crypt::SSLeayモジュールがインストールされていることが前提です。詳しくはPerlモジュール/LWPの「LWPで、『https://』で始まるSSL使用サイトにアクセスできますか?」の項を参照してください。

WWW::Mechanizeでプロキシは使えますか?

使えます。

あらかじめ環境変数「HTTP_PROXY」、「HTTPS_PROXY」などにプロキシを設定しておくと、これが利用されます。内部ではコンストラクタ(newメソッド)内で、$self->env_proxyが呼び出されています(これの働きはもちろん、親クラスであるLWP::UserAgentのenv_proxyメソッドと同じです)。

最初にこれが確認されるだけで、リアルタイムで現在の環境変数を見ているわけではないことには注意してください。

どんなフォームフィールドがあるか調べることはできますか?

できます。

WWW::Mechanize->formsメソッドは、そのページにある全てのフォームについて、HTML::Formオブジェクトを返します。さらに、HTML::Form->inputsメソッドを使うと、各入力フィールドについて、INPUTSオブジェクトが得られ、これのnameメソッドでフォームフィールド名、typeメソッドでフィールドタイプ、valueメソッドで現在の値が取得できます。

したがって、例えば以下のようにすれば、あるページ内の全てのフォームフィールドについて、フィールド名、タイプ、値を書き出すスクリプトを作れます。

use WWW::Mechanize;
my $url = "フォームがあるページのURL";
my $mech = WWW::Mechanize->new( cookie_jar => undef );
my $response = $mech->get( $url );
foreach my $form ($mech->forms) {
  foreach my $input ($form->inputs) {
    printf("%s (%s) ... %s\n", $input->name, $input->type, $input->value);
  }
}

試してみるのに大きなフォームフィールドのあるページを探すのであれば、Googleで「お客様アンケート」等を検索してみると良いでしょう。ただし、間違っても送信(回答の実行)まではしないように!

コメント

コメントスパムがひどいためこのページのコメント欄を削除しました。コメントしたい方は暫定的に「掲示板」のページへお願いいたします。