vendredi 18 décembre 2009

API Twitter et métaprogrammation Ruby appliquée

Twitter fournit une API pour accéder à son flux, son moteur de recherche et aux sujets les plus commentés.
Le flux principal appelé 'firehose' (je traduit comme:bouche d'incendie principale) ne sera accessible qu'au premier trimestre 2010. Mais vous pouvez dès à présent vous amuser avec le robinet du jardin (gardenhose) qui est un échantillon du flux principal.
Une série de module existe pour un bonne palette de langage (dont Erlang ou Ruby).

Voici un exemple de base à faire soi-même.

Pour lire l'échantillon du flux des tweets , il faut lancer une requete HTTP authentifiée et lire les réponses au fil de l'eau. Le moyen le plus simple est d'utiliser curl:

L'exemple qui est donné sur le wiki est :
curl http://stream.twitter.com/1/statuses/sample.json -uYOUR_TWITTER_USERNAME:YOUR_PASSWORD


Le résultat est au format json , en remplaçant l'extension json par xml vous aurez un résultat en XML mais le volume à traiter sera plus important.

Le site twitter est à flux continu, cela veut dire qu'il n'y pas un début et une fin de transaction. Tant que vous restez branché, vous recevrez des données. ATTENTION :TWITTER ne veut pas des petits malins qui :
* Se connectent et se reconnectent aussi tôt
* Utilisent plusieurs connexions (controle sur le user ou sur l'adresse IP).

De même, il n'est pas question d'essayer lire le flux ET de le traiter: il suffit de consulter le speedometre de twitter pour comprendre: 25.000 tweets par minute.
(exemple l'effet mickael Jackson)


On va donc avoir deux parties, un premier programme qui va lire le flux de tweets et un deuxième qui va traiter le résultat.
Ce programme de programme va lire le fichier de l'entrée standard et va afficher les tweets: Nom d'utilisateur, son nombre de followers et le texte du message.

require 'rubygems'
require 'json'
require 'tweet'
p [ JSON.parser, JSON.generator ]
#curl http://stream.twitter.com/1/statuses/sample.json -ugermanlinux:xxxxx > twitter.json

#File.open("twitter.json" ).each_line do |line|
ARGF.each_line do |line|
#$in = STDIN.readlines
#$in.each do |line|
line.chomp!
if (line[-1].chr == "}") then
jo= JSON.parse(line)

#puts jo.inspect

#puts jo.keys.sort
my_tweet=Tweet.new do |t|
t.tweet = jo
# t.userinfo =jo["user"]
end
if (my_tweet.text) then
puts "---"

print my_tweet.user["screen_name"]
print "(#{my_tweet.user["followers_count"]})"
print ":"
puts my_tweet.text
end
end

end



Explications :
* les clauses requires chargent les librairies, la librairie 'tweet' est détaillée plus loin.
* La ligne suivante affiche quels sont les drivers JSON (pour controle)
p [ JSON.parser, JSON.generator ]

Pour ma machine :[JSON::Ext::Parser, JSON::Ext::Generator]
*cette ligne détaille la commande curl à lancer sur une deuxième console , la sortie est envoyée dans un fichier twitter.json.
#curl http://stream.twitter.com/1/statuses/sample.json -ugermanlinux:xxxxxx > twitter.json
La ligne suivante montre l'ouverture d'un fichier nommé , les lignes d'apres deux méthodes pour lire l'entrée STANDARD (STDIN) , ARGF est l'équivalent de l'opérateur 'diamant' de Perl.
#File.open("twitter.json" ).each_line do |line| ##ou 
ARGF.each_line do |line| ## ou
#$in = STDIN.readlines
#$in.each do |line|

La suite est simple, il convient de s'assurer que la ligne JSON est complete (le flot arrive parfois tronqué) , le tweet est parsé de JSON vers un tableau de Hash Ruby . Le tweet doit contenir du texte, pas une mise à jour de compte.

Métaprogrammation.

La métaprogrammation Ruby intervient dans la classe Tweet:

class Tweet
attr_accessor :tweet
# def initialize(tweet)
# @tweet= tweet
# end
def initialize
yield self
end
def method_missing(m, *args, &block)
# puts m
@tweet["#{m}"]
end
def source ##exemple de getter
@tweet['source']
end
end

Normalement il faut écrire des 'getters' pour toutes les clés du hashage du tweet.
Exemple : def source ...

Ici, j'utilise la méthode standard methode_missing. Cette méthode est appelée quand la MRI ne trouve pas la méthode pour une instance. L'appel est intercepté et transformé en clé de hashage. L'économie est une cinquantaine de lignes de code et plus de flexibilité.

La methode initialize combinée avec yield permet une initialisation souple laissée au soin du programme appelant. C'est dans la philosophie du Duck typing.

Les méthodes principales de tweet sont les clés de premier niveau à savoir:

created_at
favorited
geo
id
in_reply_to_screen_name
in_reply_to_status_id
in_reply_to_user_id
source
text
truncated
user

User a son propre jeu de clés (clés secondaires)

created_at
description
favourites_count
followers_count
following
friends_count
geo_enabled
id
location
name
notifications
profile_background_color
profile_background_image_url
profile_background_tile
profile_image_url
profile_link_color
profile_sidebar_border_color
profile_sidebar_fill_color
profile_text_color
protected
screen_name
statuses_count
time_zone
url
utc_offset
verified


Résultats.


Mise en route :

a) lancer sur un terminal la commande curl déjà commentée et rediriger la sortie vers un fichier (ex : t.json)

b) Sur un deuxième terminal lancer : tail -n 1000 -F t.json|json2.rb
(le -n 1000 permet de se remettre au début du fichier , le -F garde le fichier en lecture permanente)


C'est presque aussi émouvantque de voir tomber les tweets avec twitterfall.

(clic pour élargir)

Aucun commentaire: