LWP(libwww-perl)

2002/02/28

概要

 インターネット上にあるページから自動的にデーターを拾いたいことはよくあります。
このような場合以下のようなアプローチがあります。
 
  1. open( "w3m -dump_source url |") で外部プログラムに仕事を投げる
  2. wgetでいったんセーブしたファイルを処理する。
  3. 自分でsocketを使ってアクセスする。
  4. LWPを使う
これらの方法には、それぞれに短所と長所があります。LWPは良くできたライブラリで手軽さと柔軟性を兼ね備えています。
マルチスレッドで動作しないLWPはw3mやwgetに比べて、どうしても遅くなります。大量のページを取得するにはむいていません。
LWPの使い方としては、GETはもちろんのことPOSTメソッドでの引数を柔軟に設定できるので、サーバーのCGIプログラムを相手にする場合や、自作CGIのテストなどに適していると思われます。


LWPの使い方


 lwpの使い方は libwww-cookbok がperlとともにインストールされているはずなので、そちらを見た方がいいです。日本語訳は河馬屋2000年堂さんのページにあります。
 大変詳しい説明なので、私の説明する余地はありませんが、おさらいとして、テストした結果です。

普通の使い方は、下のようになります。
 

  use LWP::UserAgent;
  $ua = LWP::UserAgent->new;

  $req = HTTP::Request->new(GET => 'http://www.foo.bar/');
  $req->header('Accept' => 'text/html');

  # リクエストの送信
  $res = $ua->request($req);

  # 出力のチェック
  if ($res->is_success) {
     print $res->content;
  }

 

headerにはより多くの情報を与えないと、サーバーが相手にしてくれない場合もあります。Acceptはダウンロードする物によって変更します。
ヘッダーのUser-Agentに与える文字列は $uaに対して指定します。

たとえばNetScapeでアクセスするときはこれだけのものをヘッダーに入れています。
ヘッダーの確認はローカルホストにAnHTTPdを入れて、ログを取って確認しました。
 

GET / HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/4.7 [ja] (WinNT; I)
Host: aaa.bbb.ccc.co.jp
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*
Accept-Encoding: gzip
Accept-Language: ja
Accept-Charset: Shift_JIS,*,utf-8

リクエストした結果は $resに帰ります。ここにはいろいろな情報が詰まっています。$res->contentにはサーバーが返すヘッダーも含まれています。コールバックを設定することもできますが、適当なところで切られたサーバーからの返答データーを引数にして呼び出されるので、プログラムを作るのは難しいです

CGIプログラムをアクセスする場合はGETよりもむしろPOSTを使う機会のほうが多いでしょう。UserAgentを使うこともできますが、フォーム内容のエンコードが面倒です。この場合は、LWP::Commonモジュールを使った方が楽です。
 
 

説明だけではつまらないので、実用になりそうなものも書いてみます。ヤフーの株価情報から時系列情報を連続ダウンロードします
これぐらいなら、wgetを使った方がよさそうな気もしますが、サンプルということで。
 
 

#!/usr/bin/perl

use LWP::UserAgent; 
 

$baseurl = "http://chart.yahoo.co.jp/t";

y = 2001;
 for($m = 1 ; $m < 13 ; $m ++){
  &GetPage($y,$m,"998407.o");
 }

#
#
#
sub GetPage
{
my($year,$month,$code)=@_;
my($start,$end,$etc);
   $start = "c=$year&a=$month&b=1";
   $end   = "f=$year&d=$month&e=31";
   $etc   = "g=d&s=$code&y=0&z=$code";
   my $url = "$baseurl?$start&$end&$etc";
   print "$url\n";  #実行状況の表示のため残す
   my $ua = LWP::UserAgent->new; 
   my $req = HTTP::Request->new(GET =>$url); 
   $req->header('Accept' => 'text/html'); 

   # リクエストの送信 
   my $res = $ua->request($req); 

   # 出力のチェック 
   if ($res->is_success) { 
 my $filename = sprintf("%04d%02d.html",$year,$month);
 open( O , ">$filename");
      print O $res->content; 
 close O;
   } 
}
 


 


<もどる>
1