nDiki : WWW::Mechanize

WWW::Mechanize

Perl モジュールLWP::UserAgent のサブクラス。

ページをキャッシュする機能を持つ WWW::Mechanize のサブクラスとして WWW::Mechanize::Cached がある。

2005年10月29日 (土)

他の Web サイトの情報を URI::Fetchキャッシュ付き取得

WiKickerDiKicker でうまく他のサイトの情報を取り込んで利用できるようにしたい。 相手サイト・自サイトともに負荷をかけないように処理するには、うまくキャッシングする必要がある。

キャッシュ機能のあるPerlHTTPユーザエージェントには

などがある。

WWW::Mechanize::Cached 1.32

WWW::Mechanize::Cached は1度取得したレスポンスを無条件に1日間キャッシュする。 WWW::Mechanize のサブクラスで、便利な機能が利用できるが、キャッシュは適当。

キャッシュCache::FileCache決め打ち。

LWP::UserAgent::WithCache 0.03

LWP::UserAgentのサブクラス。 Expires、Last-Modified、Etag ヘッダを考慮して処理する。

キャッシュCache::FileCache決め打ち。

URI::Fetch 0.04

fetch サブルーチンのみを提供するシンプルなモジュール。

キャッシュは Cache 系APIのモジュールを指定する。実際には Cache::Cache 系でもOK。 Last-Modified、Etag を考慮して処理する。

前回のアクセスから一定時間はキャッシュを返すようにする機能があり、RSS や Atom フィードを取得して利用するのに便利。

今回は

URI::Fetch をチョイス。 our を使っているのでそのままでは Perl 5.005_03 では動かないが、use vars に書き換えれば問題なく動く。

[ 10月29日全て ]

2006年2月18日 (土)

Perl CGI プログラムのテストには WWW::Mechanize::CGI

CGI プログラムを書いていて、いつも困るのがリグレッションテスト

パッケージのビルド時に実行するテストスーツ (make check / make test 用テストプログラム群) に含めておきたいが、さすがにその場で Web サーバの下へセットアップするわけにもいかない。 ミニ Web サーバを同梱してテストスーツ内で起動する方法はちょっとおおがかかりだし、ポート番号の選択やらサーバの停止の問題もあって、かなり面倒。

結局、テストスーツの中で環境変数や標準入力など CGI リクエスト環境をセットアップして、CGI プログラムを実行するという王道(?)かつ泥臭いテストを書くことになったりする。

何かいいものはないかと探していたところ、WWW::Mechanize::CGI というものをみつけた。

LWP::UserAgent を継承した WWW::Mechanize モジュールは Web ブラウジングを容易にする有名どころのモジュールである。

WWW::Mechanize::CGI モジュールはさらにこれを拡張したモジュールで、HTTP リクエストを、仮想的に CGI プログラムやサブルーチンへの呼出しにしてくれる。 これを用いるとあたかも Web サーバ上の CGI プログラムにリクエストしレスポンスを受けとっているかのように、テストプログラムを書くことができる。

素晴しい。

さっそく WiKicker のテストを書き換えてみた:

 use Test::More tests => 2;
 use WiKicker::WikICGI::Controller;
 use WWW::Mechanize::CGI;
 use File::Temp qw(tempdir);
 use File::Spec;
 my $www_dir = tempdir(CLEANUP => 1);
 my $mech = WWW::Mechanize::CGI->new;
 $mech->cgi(sub {
              $ENV{PATH_INFO} = '' if $ENV{PATH_INFO} eq '/';
              WiKicker::WikiCGI::Controller->new->run});
 $mech->env($mech->env,
            SCRIPT_FILENAME => File::Spec
                                 ->catfile($www_dir . '/wiki'),
            SCRIPT_NAME => '/wiki');
 my $response = $mech->get('http://localhost/wiki');
 ok($response->is_success);
 like($response->content,
      qr|<title>WikiForum\[WiKicker\]: FrontPage</title>|);

WWW::Mechanize::CGI オブジェクトを new した後、cgi メソッドで CGI サブルーチンを指定するか、cgi_application メソッドで外部 CGI プログラムを指定する。 ここでは直接、CGI サブルーチン (WiKicker::WikiCGI::Controller->new->run を実行)を指定した。

なおここで WWW::Mechanize::CGI が使っている HTTP::Request::AsCGI 0.5 における PATH_INFO の扱いが Apache などとは違って、空でも必ず '/' が入るようになっている。 これだと WiKicker では困るので、サブルーチンのところで修正している。

後は必要ならば WWW::Mechanize::CGI::env で、追加の環境変数設定を行っておく。

セットアップが済めば通常の WWW::Mechanize と同様に get 等でリクエストを行いレスポンスを受けとることができるようになる。

いい。しばらく試してみて不具合がなさそうなら、定番のテストスタイルにしたい。

ちなみに Test::Harness 用の Test::WWW::Mechanize にあわせて、Test::WWW::Mechanize::CGI というものもある。 これらを用いるとさらにテストを書くのが楽になるが、依存するモジュールも多いので無理に使わないほうがいいかもしれない。

[ 2月18日全て ]

2006年7月15日 (土)

一般ユーザで Apache 2.0 を起動する最小限の httpd.conf

Perl CGI プログラムのテストの自動化には

などがある。 Apache を使うのがより実際の環境に近いテストができるのだが、通常動いている Apache を使って make test でテストできるようにするとすると「どこに配置するか」などの問題がでてくる。

となればいっその事、自分(一般ユーザ)で専用に Apache を起動した方が良さそうだ。 httpd.conf を用意するのが面倒だが、highperformance.conf 等をみる限り実はそれほど必須の設定は多くないようである。

httpd.conf を書く

ということで Debian GNU/Linux sidApache (2.0.55-4) で必要な設定は何か試してみた。少なくとも以下の設定は書いておく必要があるようだ。

 # httpd.conf for Debian GNU/Linux Apache 2.0.55-4
 Listen       9100
 ServerRoot   .
 DocumentRoot /home/naney/htdocs
 ErrorLog     error_log
 TypesConfig  /etc/mime.types
 PidFile      apache2.pid

これを httpd.conf として保存して、

 /usr/sbin/apache2ctl -f httpd.conf

で起動すればアクセスできるようになる。

 /usr/sbin/apache2ctl -f httpd.conf -k stop

で停止。

ServerRoot は起動時の -d オプションでも指定できるのだが、httpd.conf に書いておかないとうまく起動してくれなかった (-X を一緒に指定してデバッグモードにする場合は ServerRoot 無しに -d 指定だけでも動く)。

CGI プログラムを動くようにする。

CGI プログラムを動くようにするとすると例えば次のような感じ。

 # httpd.conf for Debian GNU/Linux Apache 2.0.55-4
 Listen       9100
 ServerRoot .
 DocumentRoot /home/naney/htdocs
 ErrorLog     error_log
 TypesConfig  /etc/mime.types
 PidFile      apache2.pid

 LoadModule cgi_module /usr/lib/apache2/modules/mod_cgi.so
 Options +ExecCGI
 AddHandler cgi-script .cgi

make test で動くようにするには……

ディストリビューション独自のパッケージングなどに対応するように、多少泥臭く環境検出する必要があるが、なんとか make test から呼べそうだな。

最近は WWW::Mechanize::CGIお気に入りなのだが、2つ以上の CGI プログラムにまたがるようなアプリケーションのテストには向かなさそうなので、今度この方法でも試してみたい。

[ 7月15日全て ]

2006年9月13日 (水)

Test::WWW::MechanizeWeb アプリケーションテストファースト開発

テストファースト開発に慣れてしまうと、テストコード無しにプログラムを書くというのは不安でたまらなく感じてくる。

テストが欲しい。安らぎが欲しい。

今開発している WiKicker ベースの Web アプリケーションもだんだん機能が増えてきて、コードを触るのがコワくなってきた。

今回は Basic 認証等もあるので、WWW::Mechanize::CGI ではなくてきちんと deploy してから Test::WWW::Mechanize でテストすることにした。

Test::WWW::Mechanize、使ってみると WWW::Mechanize + Test::More よりテストを書くのも読むのも楽になった。

deploy が必要なリグレッションテストはさすがに t/ の下に入れておくのはどうかと思う。 プロジェクト的にはビルドサーバを用意して、そこで自動的にテストできるような環境を用意するのが良さそうだ。

[ 9月13日全て ]

2006年12月12日 (火)

PAR::Repositoryビルド済み Perl モジュールをネットワーク配信

実行可能ファイル作成としての PAR

PAR といえば Perl スクリプトを実行可能ファイル(Windows なら EXE 形式ファイル)に変換するモジュールとして有名である。

ちなみに実行可能ファイルを作成する部分はは PAR 0.97 より PAR-Packer パッケージに分けられ、PAR 自体はインストールしやすい pure Perl なパッケージになっている。

PAR モジュールアーカイブからのローダとしての PAR

PAR が提供するもう一つの(こちらが本来はメイン?)機能は、プログラムの実行時に必要な Perl モジュールPAR ファイルと呼ばれる Perl モジュールアーカイブファイルからロードする機能である。 XS モジュールなどもコンパイルすることができるどこかの環境で1度ビルドして PAR ファイルにしておけば、同じアーキテクチャのホスト上でそのまま利用することができる。

PAR リポジトリ

ロードしたい PAR ファイルはファイルパスだけではなく URL でも指定することができ、必要な時にオンデマンドでフェッチさせることができる。 これを使えば Perl プログラムの集中管理可能だ。

PAR 0.951 からは PAR リポジトリというコンセプトが追加され、パッケージ毎に作った PAR ファイルをサーバ上(あるいはローカル)のリポジトリに蓄積してオンデマンドでロードできるようになった。

個別に PAR ファイルを指定する従来の方式に比べてかなり便利そうである。 ということで試用してみた。

まずは

あたりをインストールし準備 OK。

1. PAR リポジトリを作成する

最初に PAR-Repository に含まれている parrepo で。

 parrepo create -r /tmp/PAR

PAR リポジトリファイルの中にはデータベースファイルが作成されるが、これは DBM::Deep というアーキテクチャ非依存のものを使っているので、Linux でも Windows でもどちらからでもアクセス可能である (つまり Linux 上でリポジトリをメンテできるということだ)。

2. Perl パッケージを PAR ファイル化する

次に必要な PAR ファイルを作成する。 作成したいパッケージを展開してビルドし、blib ができている状態で PAR::Dist を使ってパッケージ化する。

 perl Makefile.PL
 make
 make test
 perl -MPAR::Dist -e blib_to_par

例えば ActivePerl*1 上で WWW-Mechanize-1.20 を PAR ファイル化すると

 WWW-Mechanize-1.20-MSWin32-x86-multi-thread-5.8.8.par

というファイルが作成される。

普段から ActivePerl で必要なライブラリは基本的に自前で PPM パッケージ化して、動作確認した上で PPM リポジトリに蓄積するようにしているので、合わせて次の手順でパッケージを作ることになる。

 perl Makefile.PL
 nmake
 nmake test
 perl -MPAR::Dist -e blib_to_par
 make_ppm

*1ここでは Windows 上の

3. PAR リポジトリPAR ファイルを登録する

PAR ファイルができたら parrepo でリポジトリに登録する。

 parrepo inject -r /tmp/PAR -f xxx.par

4. PAR リポジトリ上のライブラリを使用してみる

例えば先ほどの WWW::Mechanize がリポジトリに登録されている状態で

 #!/usr/bin/perl
 use PAR { repository => 'file:///tmp/PAR/' };
 use WWW::Mechanize;
 my $mech = WWW::Mechanize->new;
 $mech->get('http://www.example.com');
 print $mech->content;

というスクリプトを書いて実行すると、PAR リポジトリから WWW::Mechanize がロードされて正しく実行される。

ここでリポジトリを Web サーバアップロードして、repository のところに URL を指定するようにすることもできる。 例えばリポジトリを http://www.example.com/PAR/ に配置したとすると

 #!/usr/bin/perl
 use PAR { repository => 'http://www.example.com/PAR/' };
 use WWW::Mechanize;
 my $mech = WWW::Mechanize->new;
 $mech->get('http://www.example.com');
 print $mech->content;

と書き換えることで、インストールしていない WWW::Mechanize を使用できるようになる。

Perl プログラムを実行形式化する

先ほどの Perl スクリプトを get_top_page.pl という名前で保存して pp で実行可能ファイル化する。

 pp -o get_top_page.exe -M PAR::Repository::Client get_top_page.pl

とすれば get_top_page.exe という実行可能ファイルが作成される。 WWW::Mechanize はオンデマンドで http://www.example.com/PAR/ からフェッチされるので、アップデートが必要な場合は新しい PAR ファイルを作成してリポジトリを更新するだけでよい。 EXE ファイルを作成しなおして利用者に配付しなすといった作業も不要だ。

スクリプトもリポジトリにおく

さらには実行するスクリプトをも PAR リポジトリに置いておくことが可能だ。

例えば WWW-Mechanize に含まれている mech-dump をオンデマンドにフェッチして実行する実行形式ファイルは以下のコマンドで作成できる。

 pp -o mech-dump.exe -M PAR::Repository::Client \
   -e "use PAR { repository => 'http://www.example.com/PAR/', \
                 run => 'mech-dump' }"

まとめ

ActivePerl では PPM があるとはいえ、普通のユーザにちょっとしたプログラムを使ってもらうのに「ActivePerl をインストールして、PPM パッケージをインストールして、……」というのは手間すぎる。

pp で プログラムに必要なものを全てバンドルした実行形式化ファイルにするという方法ももちろんあるのだが、頻繁にアップデートするようなスクリプトの場合には、起動のための部分だけ pp で作成しておいてあとは PAR リポジトリで集中管理するというのもちょっと魅力的である。

[ 12月12日全て ]

2008年3月13日 (木)

TwitterアイコンPerl スクリプトで更新する

API 経由では Twitterアイコンを変更できなさそうなので、WWW::Mechanizeアイコン画像をアップロードする Perl スクリプトを書いてみた。

 #!/usr/bin/perl

 use strict;
 use warnings;
 use WWW::Mechanize;

 die "no file name" if @ARGV == 0;
 my $file_name = $ARGV[0];

 my $name     = 'ユーザ名';
 my $password = 'パスワード';

 my $mechanize = WWW::Mechanize->new();
 $mechanize->get('http://twitter.com/');
 die unless $mechanize->success;
 $mechanize->submit_form(form_number => 1,
                         fields      => {
                                    username_or_email => $name,
                                    password          => $password});
 die unless $mechanize->success;
 $mechanize->follow_link(text => 'Settings');
 die unless $mechanize->success;
 $mechanize->follow_link(text => 'Picture');
 die unless $mechanize->success;
 $mechanize->submit_form(
                      form_number => 1,
                      fields => {'profile_image[uploaded_data]' => $file_name}
 );
 die unless $mechanize->success;
[ 3月13日全て ]

2008年3月14日 (金)

今日のさえずり - ホワイトデーはシガールにした

rimage:/nDiki/Flickr/2331224506.jpg

2008年03月13日

2008年03月14日

[ 3月14日全て ]

2008年4月29日 (火)

今日のさえずり: 一緒に洗濯機で雑巾を洗ってしまっていた

[ 4月29日全て ]

2008年7月27日 (日)

今日のさえずり - 新聞の集金かなと思ったら黄金のキョロ缶

2008年07月24日

  • 09:37 今日はスーツ日なので半袖ワイシャツ着てみた。長袖と比べると着てない感じだ。[mb]
  • 12:23 来年のアクションプランナー昨日発売開始か。早いなー。
  • 14:27 イマココ! L:千葉駅[mb]
  • 14:45 浴衣姿を見ると「今日はどっかで花火大会?」と思ってしまう短絡さ。[mb]
  • 16:53 イマココ! L:蘇我駅[mb]
  • 17:46 モバイル Gmail で archive が効かない。[mb]
  • 18:40 今日も例の方法でウナギを温めますよ。 http://tinyurl.com/6chg4p
  • 24:53 twitter.com トップページがちょっと変わって WWW::Mechanizeエラー返してたので今日修正しといた。username_or_email と password がそれぞれ session[〜] になったようだ。

2008年07月25日

2008年07月26日

2008年07月27日

  • 15:58 去年の帰省の際に(電子的に)持ち物リストを作ったと思ったのだが見当たらぬ。
[ 7月27日全て ]

2014年10月24日 (金)

PerlCasual #06 - 秋だからPerlとかの話でも #perlcasual

2013年3月29日のPerlCasual #05以来の PerlCasual。 前回と同じ渋谷ヒカリエで今回はディー・エヌ・エーが会場(前回は NHN Japan (現 LINE))。ディー・エヌ・エーが会場のイベントに出るの初めて。横長会場。

メモ:

基調講演 @xaicron 氏

  • ハッカドールの紹介からのスクレイピング。
  • WWW::Mechanize 健在。

Ramen Challenge の可視化 @Niratama 氏

Perlによるコマンドラインツール開発Tips」 @songmu 氏

Google BigQueryを使ってみた!」 @yusukebe 氏

  • Twitter の statuses/sample を流しこんでみた紹介。

Perl::Lint @moznion 氏

  • Perl::Lint 0.10 リリース。
  • Perl::Lint 開発で学んだこと。

LT

  • @bayashi 氏
    • Benchmarks.pm penchmarks。たしかに Benchmark の使い方は毎回 perldoc して思い出す必要がある。
  • @sugyan 氏
    • EmacsPerl (helm、helm-perldoc、undo-tree など)。そろそろ anything から helm に移行しないとな。
  • 「僕がwebアプリケーションのコードを書く時に考えていること 〜短縮版〜」 @dameninngenn 氏
  • @kfly8 氏
    • Benchmark。@bayashi 氏とまさかのかぶり。
  • @akihiro_0228 氏
    • 僕がPerlに慣れるまで。
  • @__papix__ 氏
    • Docker 関連。

今日のさえずり: one-on-one ミーティングで「ヤヌスの鏡」と「プロゴルファー祈子」を紹介した

  • 07:36 Facebook の「フォロワー」設定の「フォロワーコメント」で「自分の公開投稿にコメントできるユーザー」を「全員」から「友達の友達」に変更。
  • 07:59 一昨日・昨日とカレーだったんだけれど「2度辛い」がきたっぽい。
  • 08:54 本日の「PerlCasual #06 - 秋だからPerlとかの話でも」 現在 87/90人でまだ空きアリ。 https://atnd.org/events/57398 #perlcasual
  • 13:23 one-on-one ミーティングで「ヤヌスの鏡」と「プロゴルファー祈子」を紹介した。
  • 14:15 考え方の一つとして「ナチュラル・プランニングモデル」を紹介するのに自分のメモを探そうとサイト内検索したら「鏡といえばヤヌス」という自分の記事がひっかかったというだけで、ミーティングドラマの話をし続けていたとかはないです。
  • 18:57 「PerlCasual #06 - 秋だからPerlとかの話でも」キマシタ。 #perlcasual (@ 株式会社ディー・エヌ・エー (DeNA) in 渋谷区, 東京都) http://4sq.com/1sgvgVN
  • 19:01 PerlCasual #06 スタート! #perlcasual
  • 19:16 まだまだ WWW::Mechanize 現役。 #perlcasual
  • 19:42 これ? http://remarkjs.com/ #perlcasual
  • 19:48 「将来的に壊れる心配が少ない」ココが重要。 #perlcasual
  • 19:52 @Niratama ありがとうございます。使ってみます!
  • 22:59 オーブZERO!大感謝ガチャの前にランク 50 に上げた。
[ 10月24日全て ]

About

Naney Naneymx

Naney (なにい) です。株式会社MIXIで SNS 事業の部長をしています。

※本サイトの内容は個人的見解であり所属組織とは関係ありません。

Process Time: 0.050113s / load averages: 0.32, 0.26, 0.25