1)LWP::UserAgentによる接続準備
まずは、LWP::UserAgentオブジェクトを生成する。
my $ua = new LWP::UserAgent;
そしてユーザーエージェント文字列を設定する。ユーザーエージェント文字列とは、User-Agentヘッダとして送信される「クライアントの種別」を示す文字列のことだ。どのような名称でも構わない。
$ua->agent('my robot');
そしてもし、最終更新日が引数に渡されているのであれば、If-Modified-Sinceヘッダを付加する。ヘッダを付けるには、default_headerメソッドを呼び出せばよい。
ただし、HTTPプロトコルでは、日時を示す書式として、RFC1123で示されている日時書式を用いる決まりになっている。この日付書式は、例えば次のようなものだ。
Wed, 05 Dec 2007 00:00:00 GMT
この日付書式に変換するのには、HTTP::Dateモジュールに含まれるtime2str関数を利用するとよい。
$ua->default_header('If-Modified-Since',
time2str($modified));
2)接続と結果の取得
実際に接続するには、getメソッドを呼び出す。その結果、HTTP::Responseオブジェクトが戻ってくる。
my $response = $ua->get($url);
ステータスコードはcodeで取得できる。次のようにすれば、「If-Modified-Sinceヘッダを付けた時、その最終更新日以降に変更されていない」ということが確認できる。
if ($response->code == 304)
{
# 最終更新日以降に更新されていない
return (undef, $modified);
}
接続に成功し、コンテンツのデータが得られたかどうかは、is_successで調べることができる。
if (!$response->is_success)
{
die "接続エラー" . $response->status_line;
}
接続に成功しているのであれば、最終更新日を得る。最終更新日は、Last-Modifiedヘッダに入っている。これもまた、RFC1123で示されている日時書式なので、次のようにstr2time関数を用いて変換する。
my $lastmodified =
str2time($response->header('Last-Modified'));
3)文字コードの変換
コンテンツデータそのものは、contentから取得できる。
my $content = $response->content;
このデータは、Webサーバから送信されたボディ部の生データとなる。文字コードが何であるのかは想定ができないため、文字コードを調整する。
文字コードを調整するには、いくつかの方法があるが、ここでは、次のように、Encode::Guessを使って自動判定し、Encode::decodeで文字コード変換する方法とした。
Encode::Guess->set_suspects(
qw/shiftjis euc-jp 7bit-jis/);
$content = Encode::decode("Guess", $content);
多くの場合、この方法でうまく処理されるが、もし自動変換がうまくいかないようであれば、Encode::decode('shiftjis', $content);のように文字コードを直接書くとよい。
多くのWebコンテンツは、次に示すいずれかで文字コードが記述されている。本来ならば、これらの情報を用いて、文字コードを判別するのが正しい対処だ。
a)Content-Typeヘッダ
「Content-Type: text/html; charset=UTF-8」のようにContent-Typeヘッダのcharsetで指定されている場合。
この場合には、$response->header('Content-Type')として取得して、「charset=」の部分で切り出せば、正しい文字コードが分かる。
b)METAタグ
HTMLコンテンツ中に、「META http-equiv="Content-Type" content="text/html; charset=UTF-8"」のように、METAタグとして文字コードが入っているケースもある。この場合には、コンテンツを適当な文字コードで読んで、上記のMETAタグを正規表現で抜き出し、改めて、正しい文字コードで読み直せばよい。
今回は、LWPモジュールを使って、Webコンテンツを取得する関数を作ってみた。
この関数を使い、例えば次のようにすることで、オルタナティブ・ブログのRSSを取得することができる。
my $url =
'http://blogs.itmedia.co.jp/index.rdf';
my ($rssdata, $lastmodified) =
getWebContent($url,undef);
print $rssdata;
次回は、このRSSデータをパースして解析し、それぞれのコンテンツを辿って、「RSSに含まれている記事をコメントの多い順に並べて出力する」という処理を実装していこう。
Copyright © ITmedia, Inc. All Rights Reserved.