Twitter で自分宛てのリプライを収集する

最近は Twitterbot 作りばかりやっている。

元気玉 なのであ〜る おうじょったー


リプライの収集はどのボットにも出てくる、定番っぽい感じなんでさらしてみる。

手順としては、

  1. BASIC認証
  2. RSS取得
  3. RSS解析
  4. ループでハッシュの配列を作成

ReTweet されたのは除外するようにちょっとだけ工夫してある。
その他の部分は、ライブラリ使っているので簡単にできる。

#!/usr/bin/perl
use strict;
use warnings;
use Encode qw(encode);
use LWP::UserAgent;
use XML::RSS;


sub get_reply
{
    my ( $username, $password, $sinceId ) = @_;
    my $url = "http://twitter.com/statuses/replies.rss";
    
    my $ua = LWP::UserAgent->new;
    $ua->credentials('twitter.com:80', 'Twitter API', $username => $password);
    my $req = new HTTP::Request GET => $url;
    my $res = $ua->request($req);
    return unless ($res->is_success);
    
    my $rss = XML::RSS->new;
    eval {
        $rss->parse($res->content);
    };
    return if $@;
    
    my @statuses;
    for my $ref ( @{$rss->{items}} ) {
        my ( $title, $guid ) = ( $ref->{title} , $ref->{guid} );
        
        next if ($title =~ m/RT.*?\@$username/i);
        
        my ( $fromUser, $msg, $statusId ) = ( '', '', 0 );
        
        next unless ($guid =~ /.*statuses\/(\d+).*/);
        $statusId = $1;
        
        last unless ($statusId > $sinceId);
        
        next unless ($title =~ /^([_0-9a-zA-Z]+): (.*)$/);
        $fromUser = $1;
        $msg = encode('utf8', $2);
        
        push @statuses,{ statusId => $statusId, fromUser => $fromUser, msg => $msg };
    }
    
    return \@statuses;
}


リプライの表示

my $reply_statuses = get_reply($username, $password, $sinceId);

for ( @{$reply_statuses} ) {
    print "$_->{statusId} : $_->{fromUser} : $_->{msg}\n";
}

同じユーザから複数のリプライがあっても、最新のリプライだけを集めたい場合は、

my $reply_statuses = get_reply($username, $password, $sinceId);
my %seen;
my @recent_reply = grep { $seen{$_->{fromUser}}++ == 0    }
                   sort { $a->{statusId} < $b->{statusId} } @{$reply_statuses};

for ( @recent_reply ) {
    print "$_->{statusId} : $_->{fromUser} : $_->{msg}\n";
}

最新のステータスIDを取得する場合(最新のステータスIDは次回のリプライ検索時の scinceId に使う)

my $reply_statuses = get_reply($username, $password, $sinceId);
my $recentId = (sort { $a < $b } map { $_->{statusId} } @{$reply_statuses})[0];

print "$recentId\n";