北海道苫小牧市出身の初老PGが書くブログ

永遠のプログラマを夢見る、苫小牧市出身のおじさんのちらしの裏

WWW::Mechanizeでbackすると・・・?

「このブログ→はてなTOP→もっとはてな」と遷移して、ブラウザのBACKボタンを2回押す以下のスクリプトだが、直感的な動作をしない。

use WWW::Mechanize;
my $m = WWW::Mechanize->new( autocheck => 1 );
print "start here.?n";
$m->get('http://d.hatena.ne.jp/hiratara/');
print $m->uri(), "?n";
print "click link.?n";
$m->get('http://www.hatena.ne.jp/');
print $m->uri(), "?n";
print "click link.?n";
$m->get('http://www.hatena.ne.jp/info');
print $m->uri(), "?n";
print "back to hatena TOP.?n";
$m->back();
print $m->uri(), "?n";
print "back to here.?n";
$m->back();
print $m->uri(), "?n";


【結果】
start here.
http://d.hatena.ne.jp/hiratara/
click link.
http://www.hatena.ne.jp/
click link.
http://www.hatena.ne.jp/info
back to hatena TOP.
http://www.hatena.ne.jp/
back to here.
http://www.hatena.ne.jp/

2回目のバックが利いていない。これは、Mechanizeがforwardされた時にも履歴を残すため。http://www.hatena.ne.jp/info へアクセスすると /info → /info/ とforwardが起こるので、ここで履歴がダブってしまうことになる。よって、backを2回呼ばなければ元のページに戻れない。

直感的な動作をさせるには、forwardされた部分はbackを複数回呼べばいいので、$m->back()を以下のようなコードにすればいい。

sub natural_back($){
my $m = shift;
# (1)まずはリダイレクトで上乗せされている分をBACK
my $p_res = $m->res();
while($p_res = $p_res->previous()){
# レスポンスチェーンを辿る
$m->back() ;
}

# (2)普通にバック
$m->back();
}

natural_back($m);