Le YAPC::EU 2009 s'est tenu début de cette semaine. Du 3 au 5 août pour être
précis. Cela se passait à Lisbonne, et malheureusement, je n'y étais pas. Pas
vraiment de bonnes excuses, d'autant plus que le programme était vraiment
intéressant. Néanmoins, à l'heure actuelle, les conférences se déroulent
localement, et c'est le plus intéressant bien entendu, mais il y également
moyen de les suivre en ligne. D'une part sur IRC, où cela se passait sur
#yapc du serveur irc.perl.org, et d'autre part sur le web, avec le
microblogging. Un des sites les plus connus pour cette activité est
Twitter.
Mais comme cela a été mis en avant par d'autres (ou là), il est intéressant de
conserver une version des tweets publiés lors des conférences (et plus
généralement aussi d'ailleurs), je me suis donc assigné comme tâche de
reprendre le code PHP, et d'en faire une version Perl. Cela me donne ainsi
l'occasion de jouer avec de nouveaux modules.
Mes compagnons seront :
-
DBI, et DBD::SQLite : en effet, les tweets seront sauvés dans une base de
données. A l'origine, c'était une base de données MySQL, mais dans mon cas,
je vais utiliser SQLite ;
-
Net::Twitter pour interroger l'API de Twitter ;
-
et finalement, DBIx::Class pour accéder à la base de données d'une manière
plus abstraite.
Voici le code de récupération des tweets pour le YAPC::EU 2009 (le hashag
était #yapceu2009 :
#!/usr/bin/env perl
use Modern::Perl;
package KeepTweet::Schema::Result::Tweet;
use base 'DBIx::Class';
__PACKAGE__->load_components( qw/ Core / );
__PACKAGE__->table('tw_hashtag_search');
__PACKAGE__->add_columns(
'id' => {
'data_type' => 'bigint',
'is_auto_increment' => 1,
'default_value' => undef,
'is_foreign_key' => 0,
'name' => 'id',
'is_nullable' => 0,
'size' => '20'
},
'tw_hashtag' => {
'data_type' => 'varchar',
'is_auto_increment' => 0,
'default_value' => 'null',
'is_foreign_key' => 0,
'name' => 'tw_hashtag',
'is_nullable' => 1,
'size' => '32'
},
'tw_id' => {
'data_type' => 'bigint',
'is_auto_increment' => 0,
'default_value' => 'null',
'is_foreign_key' => 0,
'name' => 'tw_id',
'is_nullable' => 1,
'size' => '20'
},
'tw_lang' => {
'data_type' => 'char',
'is_auto_increment' => 0,
'default_value' => 'null',
'is_foreign_key' => 0,
'name' => 'tw_lang',
'is_nullable' => 1,
'size' => '2'
},
'tw_source' => {
'data_type' => 'varchar',
'is_auto_increment' => 0,
'default_value' => 'null',
'is_foreign_key' => 0,
'name' => 'tw_source',
'is_nullable' => 1,
'size' => '255'
},
'tw_text' => {
'data_type' => 'varchar',
'is_auto_increment' => 0,
'default_value' => 'null',
'is_foreign_key' => 0,
'name' => 'tw_text',
'is_nullable' => 1,
'size' => '160'
},
'tw_created_at' => {
'data_type' => 'varchar',
'is_auto_increment' => 0,
'default_value' => 'null',
'is_foreign_key' => 0,
'name' => 'tw_created_at',
'is_nullable' => 1,
'size' => '64'
},
'tw_to_user_id' => {
'data_type' => 'bigint',
'is_auto_increment' => 0,
'default_value' => 'null',
'is_foreign_key' => 0,
'name' => 'tw_to_user_id',
'is_nullable' => 1,
'size' => '20'
},
'tw_to_user' => {
'data_type' => 'varchar',
'is_auto_increment' => 0,
'default_value' => 'null',
'is_foreign_key' => 0,
'name' => 'tw_to_user',
'is_nullable' => 1,
'size' => '32'
},
'tw_from_user_id' => {
'data_type' => 'bigint',
'is_auto_increment' => 0,
'default_value' => 'null',
'is_foreign_key' => 0,
'name' => 'tw_from_user_id',
'is_nullable' => 1,
'size' => '20'
},
'tw_from_user' => {
'data_type' => 'varchar',
'is_auto_increment' => 0,
'default_value' => 'null',
'is_foreign_key' => 0,
'name' => 'tw_from_user',
'is_nullable' => 1,
'size' => '32'
},
'record_add_date' => {
'data_type' => 'datetime',
'is_auto_increment' => 0,
'default_value' => 'null',
'is_foreign_key' => 0,
'name' => 'record_add_date',
'is_nullable' => 1,
'size' => 0
},
);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->add_unique_constraint('tw_id', [ 'tw_id' ] );
package KeepTweet::Schema;
use base 'DBIx::Class::Schema';
# __PACKAGE__->load_namespaces();
__PACKAGE__->load_classes( qw( Result::Tweet ) );
package main;
use Net::Twitter;
use Getopt::Long;
use Data::Dump;
my $db_file = shift or die "Usage: $0 twitter_db.sqlite\n";
my $schema = KeepTweet::Schema->connect("dbi:SQLite:$db_file");
$schema->deploy() unless -e $db_file;
my $bird = Net::Twitter->new( traits => [ qw( API::Search ) ]);
$bird->username($ENV{TWITTER_LOGIN});
$bird->password($ENV{TWITTER_PASS});
my $count = 0;
foreach my $page (1..15) {
my $tweets = $bird->search({ q => '#yapceu2009', rpp => 100, page => $page });
next unless scalar(@{$tweets->{results}}) > 0;
foreach my $tweet (@{$tweets->{results}}) {
my $ktweet = $schema->resultset('Result::Tweet')->new( {
tw_text => $tweet->{text},
tw_hashtag => '#yapceu2009',
tw_id => $tweet->{id},
tw_lang => $tweet->{iso_language_code},
tw_source => $tweet->{source},
tw_created_at => $tweet->{created_at},
tw_to_user_id => $tweet->{to_user_id},
tw_to_user => $tweet->{to_user},
tw_from_user_id => $tweet->{from_user_id},
tw_from_user => $tweet->{from_user},
record_add_date => 'now()',
});
$schema->txn_do( sub { $ktweet->insert } );
}
$count += scalar(@{$tweets->{results}});
}
say 'Finished: ', $count, ' tweets processed';
Le code n'est pas vraiment compliqué à comprendre. Mais il n'est pas non plus
assez abstrait, et j'ai bien envie de créer un App::KeepTweet qui permettrait
de gérer la récupération de tweets. Je retravaillerais la base de données
dans un premier temps, puis l'interface utilisateur, probablement
une CLI,
de manière à pouvoir mettre l'exécution du programme dans
une crontab. Donc,
probablement plus de nouvelles dans quelques jours.
Et cela m'aura ainsi permis de récupérer les 413 tweets concernant cette
conférence. Je n'ai pas encore pris le temps de tout lire, mais cela m'aura
permis de glâner quelques liens vers les diapositives de quelques
présentations intéressantes.