Script PHP pour obtenir la liste de tous ses statuts Twitter
J'ai appris récemment qu'on pouvait changer la pagination pour visualiser la liste de nos statuts sur Twitter en ajoutant manuellement le paramètre ?page=n à la suite de l'URL (http://twitter.com/code18?page=2).
Bien sûr, la liste des status de notre timeline peut être obtenue à partir de l'API. Et si j'essayais de les récupérer sans passer par l'API, juste pour le plaisir d'essayer de les extraire pour en faire un backup pour mes archives personnelles ? Après tout, mes premiers pas sur Twitter datent de mars 2009 et j'ai publié au-delà de 1300 "gazouillis" jusqu'à maintenant.
C'est certain que je rencontrerai des contraintes par rapport à l'API (qu'il est plus prudent d'utiliser en plus de bénéficier de support et d'assurer la compatibilité). D'abord, mon script sera dépendant de la structure du code advenant qu'elle change dans le futur (HTML ou CSS appliqué). Ensuite, je devrai me contenter des statuts qui sont publics parce que ma méthode ne s'authentifiera pas au service Twitter.
Je me mets donc au travail avec comme base les éléments suivants :
- la fonction file_get_contents() servira à récupérer le code HTML d'une page distante selon l'URL passé en paramètre
- la librairie Zend_Dom_Query du Zend Framework sera utilisée pour les sélecteurs du DOM
require_once('Zend/Dom/Query.php');Le résultat : un fichier texte de 163 kb comprenant la totalité de mes tweets depuis près de 2 ans.
header('Content-Type: text/html; charset=utf8');
DEFINE('ACCOUNT', 'code18');
DEFINE('STATUS_PER_PAGE', 20);
$html = file_get_contents('http://twitter.com/' . ACCOUNT);
// obtenir le nombre de tweets total affiché à titre informatif sur la page
$dom = new Zend_Dom_Query($html);
$nodes = $dom->query('#update_count');
$nbUpdates = 0;
foreach($nodes as $node){
// retirer la virgule, le séparateur de milliers en anglais
$nbUpdates = (int)str_replace(',', '', $node->textContent);
}
# calcul du nombre de pages total
$nbPages = ceil($nbUpdates / STATUS_PER_PAGE);
# timeout du script selon le volume de données (2 secondes par tweet)
set_time_limit(2 * STATUS_PER_PAGE * $nbPages);
$buffer = "";
// récupérer les statuts une page à la fois
for($page=1 ; $page<=$nbPages; $page++){
$html = file_get_contents('http://twitter.com/' . ACCOUNT . '?page=' . $page);
$dom = new Zend_Dom_Query($html);
$listLI = $dom->query('#timeline li');
// pour chaque statut qui se trouve dans le LI
foreach($listLI as $li){
$doc = new DOMDocument();
$doc->appendChild($doc->importNode($li, true));
$elem = new Zend_Dom_Query( $doc->saveHTML() );
$listSpan = $elem->query('.published');
$listStatus = $elem->query('.entry-content');
// obtenir la date de publication du tweet
$dateValue = '';
foreach($listSpan as $date){
$dateValue = $date->getAttribute('data');
// attention, ne tient pas compte du fuseau horaire
$dateValue = preg_replace("/^\{time:'(.*)'\}$/", '$1', $dateValue);
}
// obtenir le texte du statut
$text = '';
foreach($listStatus as $status){
$text = $status->textContent;
}
$buffer .= $dateValue . ' | ' . $text . "\n";
}
}
// écrire le tout dans un fichier
$file = 'c:\tweets-' . ACCOUNT . '.txt';
// ou
// $file = '/home/code18/tweets-' . ACCOUNT . '.txt';
$fh = fopen($file, 'w');
fwrite($fh, $buffer, strlen($buffer));
fclose($fh);
echo 'Done';
Enfin, ça fonctionne mais il ne faudrait pas trop s'y fier si on veut construire quelque chose de solide. Aussi, je me rends compte que mes premiers tweets n'étaient vraiment pas pertinents et ça s'est heureusement amélioré avec le temps.