ATNDの参加者をTwitter情報でランキング!

というわけで、qpstudy04、hbstudy??でLTしたネタの集計プログラムが発掘されたので、今さらながらさらしてみます。


qpstudyのLT資料はこちら


やってることは

  • ATNDから参加者のTwitterIDを取得
  • Twitterから参加者の情報を取得
  • 集計

の3つ。
簡単な説明と合わせて、『qpstudy 1周年記念LT大会!』で同じように集計してみます。

ATNDから参加者のTwitterIDを取得

ATND IDを引数に渡して参加者のTwitterIDを取得します。
ATND IDはURLの最後についてる番号です。
(イベントのURLがhttp://atnd.org/events/14147なら14147)

$ perl get_atnd_member.pl 14147 > atnd_users
$ cat atnd_users
iara
ar1
gogotea3
tmae
...

ソースコード

#!/usr/bin/perl
use strict;
use warnings;

use LWP::Simple;
use XML::Simple;
use Data::Dumper;

my $event_id = shift;

### ATND APIから参加者情報を取得
my $uri = "http://api.atnd.org/events/users/?event_id=$event_id";
my $xml = LWP::Simple::get($uri);
my $data = XML::Simple->new->XMLin($xml);
my @atnd_users = @{$data->{events}{event}{users}{user}};

### TwitterIDのリストを取得
my @twitter_users = map {$_->{twitter_id}}
                    grep {!ref $_->{twitter_id}} @atnd_users;

### 重複除去。なぜかたまにいる。
my %cnt;
@twitter_users = grep {!$cnt{$_}++} @twitter_users;

print "$_\n" for @twitter_users;

ATND APIについてはATND API リファレンスを参照してください。
今回は出欠確認APIを使っています。
(TwitterIDが登録されているかの確認部分がテキトウすぎ)

Twitterから参加者の情報を取得

TwitterIDのリストを食わせてTwitter情報取得、YAMLファイルに出力します

$ mkdir data
$ perl get_twitter_data.pl < atnd_users
$ ls -1 data
0_01
8monolith8
BR_tatsuya
...
$ cat data/mikeda 
---
followers_count: 396
listed_count: 94
lists:
  - conversationlist
  - study
...

ユーザ(とその所属しているリスト)が多いと途中でAPI制限に引っかかるので、実際は以下のようなコマンドを何回かに分けて実行しています。

$ (cat atnd_users;ls data)|sort|uniq -u| perl get_twitter_data.pl

ソースコード

#!/usr/bin/perl
use strict;
use warnings;

use Net::Twitter::Lite;
use YAML;
use Data::Dumper;
use utf8;
binmode(STDOUT, ":utf8");

my @twitter_users = <>;
chomp @twitter_users;

my %CONSUMER_TOKENS = (
    consumer_key    => 'XXXXXXXXXXXXXXX',
    consumer_secret => 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
);
my $ACCESS_TOKEN        = '000000000-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
my $ACCESS_TOKEN_SECRET = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';

my $t = Net::Twitter::Lite->new(%CONSUMER_TOKENS);
$t->access_token($ACCESS_TOKEN);
$t->access_token_secret($ACCESS_TOKEN_SECRET);

for my $user (@twitter_users){
  my $userinfo = $t->show_user($user);

  my @lists;
  my $cursor = -1;
  while($cursor){
    my %opts = (user => $user, cursor => $cursor);
    my $res = $t->list_memberships(\%opts);
    push @lists, map {$_->{name}} @{$res->{lists}};
    $cursor = $res->{next_cursor};
  }

  my $data = {
    followers_count => $userinfo->{followers_count},
    listed_count    => $userinfo->{listed_count},
    lists           => \@lists
  };

  YAML::DumpFile("data/$user", $data);
  warn "$user done\n";
}

集計出力

TwitterIDのリストを食わせると集計結果を出力します

$ perl show_rank.pl < atnd_users
### followers_count ###
riywo	3604
wasaist	3276
matsuu	2845
Wslash	2373
sho7650	2269
ar1	2068
super_rti	2011
H_Shinonome	1895
zembutsu	1864
jmorimt	1749

### listed_count ###
Wslash	326
matsuu	324
wasaist	301
riywo	285
ar1	264
sho7650	254
H_Shinonome	223
hasegaw	207
zembutsu	168
yuuitiro	160

### list search ###
  ### qpstudy ###
  image_	11
  ar1	10
  matsuu	10
  mikeda	10
  sho7650	10
  H_Shinonome	9
  iara	9
  kuwa_tw	9
  mkouhei	9
  nekoruri	9

  ### engineer ###
  riywo	20
  matsuu	14
  ar1	13
  iara	13
  kamipo	13
  hasegaw	12
  kuwa_tw	11
  fujiwara	9
  H_Shinonome	7
  sho7650	7

  ### tech ###
  hasegaw	20
  ar1	18
  riywo	14
  Wslash	13
  matsuu	11
  zembutsu	10
  iara	9
  kamipo	7
  kuwa_tw	7
  mikeda	7

  ### ero|hentai ###
  iara	2
  super_rti	2
  matsuu	1
  riywo	1
  sho7650	1
  tk0miya	1
  xcir	1
  0_01	0
  8monolith8	0
  BR_tatsuya	0

けっこう上位陣が入れ替わってますねぇ


ソースコード

#!/usr/bin/perl
use strict;
use warnings;

use YAML;
use Data::Dumper;
use utf8;
binmode(STDOUT, ":utf8");

my @keywords = qw/qpstudy engineer tech ero|hentai/;

my @twitter_users = <>;
chomp @twitter_users;

my %user_data;
for my $user (@twitter_users){
  $user_data{$user} = YAML::LoadFile("data/$user");
}

print "### followers_count ###\n";
my @followers_count_rank = sort 
  {$user_data{$b}->{followers_count} <=> $user_data{$a}->{followers_count}} 
  @twitter_users;
for my $user (@followers_count_rank[0..9]){
  print "$user\t".$user_data{$user}->{followers_count}."\n";
}
print "\n";

print "### listed_count ###\n";
my @listed_count_rank = sort 
  {$user_data{$b}->{listed_count} <=> $user_data{$a}->{listed_count}} 
  @twitter_users;
for my $user (@listed_count_rank[0..9]){
  print "$user\t".$user_data{$user}->{listed_count}."\n";
}
print "\n";

print "### list search ###\n";
for my $keyword (@keywords){
  print "  ### $keyword ###\n";
  
  my %member_count;
  for my $user (@twitter_users){
    $member_count{$user} = 
	  grep {/$keyword/i} @{$user_data{$user}->{lists}};
  }

  my @member_count_rank = sort 
    {$member_count{$b} <=> $member_count{$a}} 
    @twitter_users;
  for my $user (@member_count_rank[0..9]){
    print "  $user\t".$member_count{$user}."\n";
  }

  print "\n";
}

という感じでした。
注意点は、ATNDにTwitterアカウントでログインしている、もしくはTwitterIDを登録している人しか集計できないことです。
結局フォロワー数の多い人に全部もってかれがちなのですが、リスト検索キーワードをうまく選べばけっこう楽しめるのではないかと思います!