PlaggerとWeb::Scraperでアクセスランキングを出してみる
久々にPlaってみました。アクセスログを集計して結果(上位10件)をRSSで出力するようにしてみました。
処理の流れ(変に遠回りしてる気もしますが)
- ログファイルをもとにアクセス数をカウント
- アクセス数が多い順にソート
- ページにアクセス
- Web::Scraperでスクレイピングしてtitleとメタタグのdescriptionを取得
- エントリーオブジェクトを生成
- エントリーオブジェクトをPlagger(Publish::Feed)に渡して出力
そこまでスクリプト書いたんならPlaggerに渡さなくても(XML::Feed使え)...とか言われるかなぁ。
まぁ一応やってみたんで。
以下レシピとスクリプトです。
- rank.yaml
global: timezone: Asia/Tokyo plugins: - module: CustomFeed::Script - module: Subscription::Config config: feed: - script: /home/akihito/rank.pl - module: Publish::Feed config: format: RSS dir: /home/akihito/ filename: rank.rss
- rank.pl
use strict; use YAML::Syck; use IO::File; use Web::Scraper; use URI; my $log = '/etc/httpd/logs/access_log'; my $domain = 'http://example.com'; my $f = new IO::File(); $f->open($log); my %url; while(my $line = <$f>){ if( $line =~ /[GET|POST]+\ (\S+)\ HTTP/ ){ $url{$1} = $url{$1}?$url{$1}+1:1; } } $f->close; my @rank; my $count = 0; for my $key ( reverse sort {$url{$a} <=> $url{$b}} keys %url){ last if( $count >= 10 ); if( $key !~ /\.(jpeg|jpg|gif|png|css|js|ico)$/ ){ my $uri = $domain.$key; $count++; my $links = scraper { process 'title','title[]' => 'TEXT'; process 'meta','description[]' => sub{ return $_->attr_get_i('content') if($_->attr_get_i('name') =~ /description/i && $_->attr_get_i('content')); return; }; result qw/title description/ }->scrape(URI->new($uri)); push @rank,{ link => $uri, title => $links->{title}->[0], body => $links->{description}->[0], }; } } my $output = {}; $output->{entry} = \@rank; print YAML::Syck::Dump $output;