Analyze関数

「#--Analyze」で検索すると確実にヒットします。

この関数は、指定されたURLからRSSのURLを取り出しアクセスし、RSSファイルを取得後RSSファイルを各要素に分解します。

引数はありませんが、指定されたURLと、読み込むRSSファイルサイズのリミッターをかけている値にはグローバル変数を使っています。

戻り値は、RSSファイルを各要素に分けた連想配列リファレンスです。

それでは、処理の流れを見ていきましょう。

URLチェック

まずは、指定されたURLの書式を整形しチェックします。

unless ($URL) {return;}
unless ($URL =~ /^http/) {$URL = 'http://' . $URL;}
unless ($URL =~ /^https?:\/\/[a-zA-Z0-9_\-\+\.\/\?~#=&%@]+$/) {
&Page('error', 'URL INPUT ERROR');
}

ここでは、指定されたURLが存在するのかというところではなく…。

何らかの文字が書かれているのか?

書かれていなければ関数終了。

もし書かれていれば、使用されている文字がURL指定に使われるべき文字なのかということを評価しています。

RSSURL取得

次に、指定されたURLから、Feed::Findモジュールを使ってRSSファイルまでのURLを取得します。

Feed::Findモジュールは、指定したウェブページからRSSファイルへのURLを抽出します。

my @feeds = Feed::Find->find($URL);
&Page('error', 'Nothing RSS URL') unless scalar @feeds;

配列「@feeds」に、RSSファイルまでのURLをリスト形式で格納します。

もし1つも格納できないとき(@feedsの要素がない場合)は、Page関数を呼び出しエラーメッセージを表示させ終了します。

RSSファイルの取得

次に、配列「@feeds」に格納したRSSファイルまでのURL群に対して、ひとつひとつアクセスします。

これは、適切なバージョンのRSSであるかを判定するためです。

このRSSリーダーが対応しているのは、RSS1.0とRSS2.0ですので、それ以外は無視します。

逆に、適切なバージョン(この場合はRSS1.0かRSS2.0)が見つかった場合は、それ以外のRSSURLを無視します。

RSSファイルへのアクセスと取得には、LWP::UserAgentとHTTP::Requestモジュールを使います。

my $UserAgent = LWP::UserAgent->new(keep_alive => 1);
my $request = HTTP::Request->new (GET => $feed);

$UserAgent->timeout(10);
$UserAgent->agent('kimurashuuichi.com Browser 1.0');
$request->referer('http://kimurashuuichi.com');

RSSURLへのアクセスに当たって…。

最大待ち時間を10秒、ブラウザ名を「kimurashuuichi.com Browser 1.0」、アクセス元を「http://kimurashuuichi.com」に設定しています。

このあたりは、設置するサーバーに応じて自由に設定してください。

そして、RSSURLに実際にアクセスしレスポンスを評価している部分は以下になります。

my $response = $UserAgent->request($request);

if ($response->is_success) {
...
...
} else {
my $message = $response->message;
&Page('error', $message);
}

RSSURLにアクセスが成功すればif文が成立し、失敗すればelse以降が実行されます。

if文が成立(RSSURLへのアクセスが成功)した場合には、RSSファイル本体とそのサイズを取得します。

my $size = $response->content_length;
my $content = $response->content;

これで、RSSファイル本体と、そのサイズを取得できました。

RSSサイズの取得と判定

RSSファイルサイズ取得に関して、上記のやり方では取得できない場合があります。

なので、以下でバックアップしています。

unless ($size) {
my $content_utf8flagoff = &Utf8Flag($content, 'off');
$size = length($content_utf8flagoff);
}

取得したRSSファイルサイズの測定には、length関数を使用します。

しかし、Utf8フラグが立っていた場合、バイト数ではなく文字数のカウントになってしまいます。

なので、Utf8Flag関数でUtf8フラグを解除し、文字数ではなくバイト数をカウントさせるようにしています。

そして、バイト数で指定されたグローバル変数「$LIMITER」を実際のバイト数の値に変換したものと比較しています。

if ($size > ($LIMITER * 1000000)) {
$size = &Comma($size);
&Page('error', "RSS File Size Over ${size}bytes");
}

もし、取得したRSSファイルサイズが設定値($LIMITERで指定したバイト数)より大きければ、if文が成立し関数終了。

その際、Comma関数でRSSファイルサイズ値を3桁ごとにカンマで区切り、見やすく整形し表示させています。

RSSファイルの分析

RSSファイルの分析には、XML::RSSモジュールを使っています。

my $rss = new XML::RSS;
$rss->parse($content);

newで定義した「$rss(XML::RSS)」モジュールのparseに、先ほど取得したRSSデータを渡すだけです。

あとは、RSSを構成している要素名で呼び出せば、その内容を取得できます。

例えば、RSSのバージョンを取得するときには以下のように書きます。

$rss_info{'version'} = $rss->{'version'};

連想配列「$rss_info{'version'}」にRSSバージョンが格納されました。

次はこのRSSバージョンを評価し、1.0もしくは2.0であれば、残りのRSS情報を取得しに行きます。

if (($rss_info{'version'} eq "1.0") or ($rss_info{'version'} eq "2.0")) {
$rss_info{'channel'} = $rss->{'channel'};
$rss_info{'image'} = $rss->{'image'};
$rss_info{'items'} = $rss->{'items'};
$rss_info{'feed'} = $feed;
$rss_info{'size'} = &Comma($size);
}

これで連想配列「%rss_info」に取得したRSSの情報が格納されました。

ついでに、RSSファイルのURLとそのサイズも格納します。

これでこの関数での処理は完了です。

return \%rss_info;

作成した連想配列をリファレンス形式にして戻り値にしています。