読者です 読者をやめる 読者になる 読者になる

自分のブログのGoogle Reader購読者数をPerlでぶっこ抜く

perl google webapi

自分のブログのGoogle Reader購読者数をRubyでぶっこ抜く

Perl版.

コード

仕組みを理解するために Google WebAPI関連のモジュールには頼らず
書いてみました。

#!/usr/bin/env perl
package App::GoogleReader;
use Mouse;

use Carp;
use Furl;
use JSON;
use Feed::Find;
use HTTP::Request::Common;

has 'account'  => (is => 'ro', isa => 'Str', required => 1);
has 'password' => (is => 'ro', isa => 'Str', required => 1);
has 'auth'     => (is => 'rw', isa => 'Str');
has 'req_params' => (is => 'rw', isa => 'HashRef');

has 'ua' => (
    is => 'rw',
    isa => 'Furl',
    default => sub {
        Furl->new(agent => __PACKAGE__ . "/0.01");
    },
);

sub init {
    my $self = shift;

    $self->req_params({
        service => 'reader',
        Email   => $self->account,
        Passwd  => $self->password,
        source  => __PACKAGE__ . "/0.01",
    });

    my $url = 'https://www.google.com/accounts/ClientLogin';

    my $req = POST $url, [ %{$self->req_params} ];

    my $res = $self->ua->request($req);
    unless ($res->is_success) {
        Carp::croak("Error: can't login $url");
    }

    my ($auth) = $res->content =~ m{Auth=(.+)$};
    $self->auth($auth);
}

sub reader_count {
    my ($self, $url) = @_;

    my @feeds = Feed::Find->find($url);
    if (scalar @feeds == 0) {
        Carp::carp("$url has no feed");
        return 0;
    }

    my $base = "http://www.google.com/reader/api/0/stream/details?s=feed/";

    my $subscribers = 0;
    for my $feed (@feeds) {
        my $uri = $base;

        $uri .= $feed;
        $uri .= "&output=json&fetchTrends=false";

        my $req = GET $uri, [%{$self->req_params}];
        $req->header(
            Authorization => "GoogleLogin auth=" . $self->auth,
        );
        my $res = $self->ua->request($req);
        unless ($res->is_success) {
            Carp::carp("Can't get subscribers($uri) ", $res->status_line);
            next;
        }

        my $json = decode_json($res->content);
        (my $num = $json->{subscribers}) =~ s{,}{}g;
        $subscribers += $num;
    }

    return $subscribers;
}

__PACKAGE__->meta->make_immutable;

1;

package main;
use strict;
use warnings;
use Config::Pit;

my $conf = pit_get("google.com", require => {
    "account"  => 'google account',"password" => 'google password',
});

unless (caller) {
    my $app = App::GoogleReader->new(%{$conf});
    die "Usage $0 url..." if scalar @ARGV == 0;

    $app->init;
    for my $url (@ARGV) {
        my $count = $app->reader_count($url);
        print "$url reader => '$count'\n";
    }
}

実行

  % perl google_reader.pl http://d.hatena.ne.jp/syohex/
  http://d.hatena.ne.jp/syohex/ reader => '26'

正しいのかよくわからないですが、まあ僕なんでこんなもんでしょう。


弾小飼さんはやっぱり桁違いでした。

  % perl google_reader.pl http://blog.livedoor.jp/dankogai/
  http://blog.livedoor.jp/dankogai/ reader => '32542'