« 2004年05月 | メイン | 2005年03月 »
2004年08月05日
二重起動の防止
あるプログラムが走っているときに、同時に同じプログラムを起動させたくないときがある。Windows 環境であれば mutex オブジェクトを使うことができ、Perl にも Win32::Mutex モジュールが存在する。use Win32::Mutex; die "二重起動" if(Win32::Mutex->open('hogehoge')); $mutex=Win32::Mutex->new(1, 'hogehoge'); while(1){ print ++$n,"\n"; sleep(5); };2行目で他に hogehoge という名前の Mutex オブジェクトが作られていないかどうかチェックし、もし他で hogehoge という名の Mutex オブジェクトが作られていれば、先へ進まずに終了する。3行目では hogehoge という Mutex オブジェクトを作成している。
したがって、このスクリプトを2つ起動しようとしても、2つ目は2行目のチェックで引っかかって終了してくれるはずである。
ただし、タイミングによっては完璧ではないようだ。
投稿者 augustus : 22:19 | コメント (0) | トラックバック
2004年08月03日
CSV の行を分解
CSVをコンマで分けるのは一見簡単そうであるが、実は奥が深い。Perl では Text::CSV_XS モジュールを使うのが便利だ。たとえば、split 関数を使って「,」で分ければ、次のような単純な例はうまくいく。
$line='A,BB,CCC,,D'; @values=split(/,/,$line);しかし、これでは「,」や「"」を含む値を適切に扱うことはできない。値の中に「,」や「"」を含むときは値を「"」で囲み、含まれる「"」は「""」と記述するのだが、単純に「,」で切っては当然うまくいかない。
Perlメモ(http://www.din.or.jp/~ohzaki/perl.htm#CSV2Values)に詳しくやり方が書いてあった。難しくて解読困難だ。(^^;
$tmp=$line='"""北海道,札幌市""",ABC,"XX,XX","abc"'; $tmp=~s/(?:\x0D\x0A|[\x0D\x0A])?$/,/; @values=map {/^"(.*)"$/?scalar($_=$1,s/""/"/g,$_):$_} ($tmp =~ /("[^"]*(?:""[^"]*)*"|[^,]*),/g);
Text::CSV_XS を使って以下のようにすることもできる。日本語を扱わないなら {binary=>1} は不要である。
use Text::CSV_XS; $csv=Text::CSV_XS->new({binary=>1}); #create a object $line='"北海道,札幌市",ABC,"XX,XX","""abc"""'; $status=$csv->parse($line); #parse a string @values=$csv->fields(); #get the fields print join("\n",@values);Text::CSV_XS は Active Perl なら標準で含まれているからこれが便利だろう。
投稿者 augustus : 22:36 | コメント (0) | トラックバック
perl でリンクを抽出する
perl でリンクを抽出するには HTML::LinkExtor モジュールを使うのが便利だ。$p = HTML::LinkExtor->new([$callback[, $base]]);
まずは LinkExtor オブジェクトを作るわけだが、 callback 関数を指定しておくと、 リンクを見つけるたびに callback 関数が呼び出される。 callback 関数を指定していないときは $p->links で 含まれるリンクを明示的に読み出すことができる。
$base を指定しておくと、相対パスで指定されたリンクを 自動的に $base を基準にしたものとみなして絶対パスに直してくれる。
文字列からリンクを抽出したいときは $p->parse($strings) とするが、 ファイルからリンクを抽出するときは $p->parse_file($filename) とする。
では、http://www.augustus.to/ に含まれるリンクを抽出してみよう。
use LWP; use HTML::LinkExtor; $url="http://www.augustus.to/"; $browser = LWP::UserAgent->new; $response = $browser->get($url); $p = HTML::LinkExtor->new(\&callback,$url); $p->parse($response->{_content}); sub callback { my($tag, %links) = @_; print "$tag @{[%links]}\n"; }
callback 関数を使わないならこんな感じ。
use LWP; use HTML::LinkExtor; $url="http://www.augustus.to/"; $browser = LWP::UserAgent->new; $response = $browser->get($url); $p = HTML::LinkExtor->new(unlink(),$url); $p->parse($response->{_content}); for $x ($p->links){ print join(" ", @{$x}),"\n"; }
投稿者 augustus : 08:54 | コメント (0) | トラックバック
2004年08月02日
perl で cookie を取得
perl で web ページにアクセスするとき、クッキーを取得したいときもあるだろう。そういうときは HTTP::Cookies モジュールを使えばよい。以下の例のようにするとページのソースが表示されるとともに、クッキーが指定されたファイルに保存される。
use LWP; use HTTP::Cookies; $url="http://www.amazon.co.jp/"; #アクセスする URL $file="cookies_amazon.txt"; #クッキーを保存するファイル $browser = LWP::UserAgent->new; $browser->cookie_jar({file =>$file, autosave=>1 }); $response = $browser->get($url); print $response->{_content};
投稿者 augustus : 21:24 | コメント (0)
2004年08月01日
ユーザ認証を要するページにperlでアクセス
BASIC認証またはDIGEST認証を要求する web ページに perl でアクセスしたいときには LWP::UserAgent モジュールの credentials メソッドが使える。実験用に用意した http://www.augustus.to/test/authtest/ にアクセスしてみよう。領域名は Auth_Test、ユーザ名は authtestuser、パスワードは password である。スクリプトは以下のようになる。
use LWP; use HTTP::Request::Common; $domain="www.augustus.to"; $port=80; $realm="Auth_Test"; #領域名 $user="authtestuser"; #ユーザ名 $passwd="password"; #パスワード $url="http://www.augustus.to/test/authtest/"; $browser = LWP::UserAgent->new; $browser->credentials( "$domain:$port",$realm,$user,$passwd); $response = $browser->get($url); print $response->{_content};