天然パーマです。

Google Analytics API を Perl から扱うスクリプト

とあるサイトのページビューを日別で出さなくてはいけなくなった。 Google Analytics でアクセス解析してるんだけど、いちいち管理画面でPVを見て書き出すのがめんどくさいので、 API 経由で指定したサイトの過去10日間のそれぞれPVをプリントしてくれる Perl のスクリプトを書いた。 さくっと終わらすはずが、認証のところで少々時間を食ってしまった。

その仕組みは

  • Client Login で Auth キーを取得、具体的にはアカウント情報をとあるエンドポイントへPOSTする
  • リクエストする時に「Authorization」ヘッダを加えてその Auth キーを値とする
  • GETリクエスト発行
  • 結果がXMLで返ってくるのでパース

という具合。で、パースした結果を最低限シンプルにYAMLモジュールでDumpしてる。

以下がそのおれおれスクリプトになっているので、ご参考までに。

 #!/usr/bin/perl
use strict;
use warnings;
use DateTime;
use DateTime::Duration;
use HTTP::Request::Common ();
use LWP::UserAgent;
use XML::Simple;
use YAML;

my $email = $ENV{GOOGLE_EMAIL};
my $password = $ENV{GOOGLE_PASSWORD};
my $source = 'yusukebe-GoogleAnalyticsCommand-001';
my ( $req, $res, $auth_key );
my $ua = LWP::UserAgent->new();
my $xs = XML::Simple->new( KeyAttr => [''], ForceArray => ['entry'] );

auth();
if ( defined $ARGV[0] ) {
    if ( defined $ARGV[1] ) {
        analytic( { profile_id => $ARGV[0], date_string => $ARGV[1] } );
    }
    else {
        my $now = DateTime->now( time_zone => 'Asia/Tokyo' );
        for ( 1 .. 10 ) {
            $now = $now - DateTime::Duration->new( days => 1 );
            analytic(
                { profile_id => $ARGV[0], date_string => $now->ymd('-') } );
        }
    }
}
else {
    ls();
}

sub auth {
    my $auth_url = 'https://www.google.com/accounts/ClientLogin';
    my $service = 'analytics';
    $req = HTTP::Request::Common::POST(
        $auth_url,
        [
            accountType => 'GOOGLE',
            Email => $email,
            Passwd => $password,
            service => $service,
            source => $source
        ]
    );
    $res = $ua->request($req);
    die $res->status_line if $res->is_error;
    my $content = $res->content;
    if ( $res->content =~ /Auth=([^\s]+)/ ) {
        $auth_key = $1;
    }
    else {
        die "can't find auth key!";
    }
}

sub analytic {
    my $args = shift;
    my $feed_url = 'https://www.google.com/analytics/feeds/data';
    my $profile_id = $args->{profile_id};
    my $date_string = $args->{date_string};
    $feed_url =
"$feed_url?ids=$args->{profile_id}&metrics=ga:pageviews&start-date=$args->{date_string}&end-date=$args->{date_string}&prettyprint=true"; #xxx
    $res = $ua->request(
        HTTP::Request::Common::GET(
            $feed_url, 'Authorization' => "GoogleLogin Auth=$auth_key"
        )
    );
    my $ref = $xs->XMLin( $res->content );
    my $info = {
        date => $date_string,
        $ref->{entry}->[0]->{'dxp:metric'}->{name} =>
          $ref->{entry}->[0]->{'dxp:metric'}->{value}
    };
    print Dump $info;
}

sub ls {
    $res = $ua->request(
        HTTP::Request::Common::GET(
'https://www.google.com/analytics/feeds/accounts/default?prettyprint=true',
            'Authorization' => "GoogleLogin Auth=$auth_key"
        )
    );
    my $ref = $xs->XMLin( $res->content );
    my @entries;
    for my $entry ( @{ $ref->{entry} } ) {
        push(
            @entries,
            {
                title => $entry->{title}->{content},
                profile_id => $entry->{'dxp:tableId'}
            }
        );
    }
    print Dump @entries;
}