Echando código: ¿Como puedo respaldar mis fotos de las cuentas grátis de Flickr, usando Perl?

Hice la misma pregunta en el foro de ayuda de Flickr; Después de 3 horas uno de sus empleados me indicó lo siguiente:

Eric Flickr Staff says:

Sorry for the lack of reply to your email josevnz!

I’m afraid there is no way to do this automatically. You’ll have to download the photos from the free accounts one by one and re-upload them to your new account.

¡Que ladilla!. Así que empecé a echarle cabeza a la vaina, para ver si podía evitarme esa ladilla o por lo menos minimizar el daño.

Después de mucho pelear con uno de las personas de soporte (coño, estoy pagando, ¿no?), este me dió una idea:

Eric Flickr Staff says:

Well, it is a pain I know but you can actually pull your original sizes by hacking the url. They will end with «_o.jpg» (assuming they are jpgs), so just change the end of the url of your «resized versions» to «_o.jpg» and you’ll have your original.

So photos6.flickr.com/6697434_8332121f37_s.jpg would become photos6.flickr.com/6697434_8332121f37_o.jpg

Resulta que la documentación de el API de Flickr dice como generar el URL. Así que me baje la clave del API y me decidí a bajar un wrapper en Perl ya que me daba una ladilla increible utilizar un protocolo de bajo nivel para obtener todos los nombres y para generar los URL:

Al final me decidí a atacar el problema así:

  1. Se perezoso. Busca un wrapper para el API de Flickr para evitar lidiar con detalles de bajo nivel.
  2. Obtener el identificador de un usuario de Flickr.
  3. Obtener el listado de todas fotos publicas para un identificador de usuario dado.
  4. Bajarse las fotos a un directorio local mientras se recorre la lista de fotos. Eso requiere que armemos el URL a mano.

Primero instalamos el modulo de Perl para Flickr, Flickr::API:

[root@localhost root]# perl -MCPAN -e’install Flickr::API

Tiene un coñazo de dependencias. Pero por lo menos en Fedora Core 2 se dejó sin chistar 🙂

Luego a echar código. Después de 3 cervezas Corona y dos discos completos de Metallica (Reload y Saint Anger), el programa estaba listo:

   1:#!/usr/bin/perl
2:use strict;
3:use Flickr::API;
4:use Data::Dumper;
5:use LWP::UserAgent;
6:
7:
8:use constant API_KEY => 'a8a57025bbe0f7d1889b6cb6d754ad7b';
9:use constant PER_PAGE => 500;
10:use constant PAGE => 1;
11:use constant DEBUG => 0;
12:
13:if (! defined $ARGV[0]) {
14: die "[ERROR]: Please provide the user ID!";
15:} else {
16: printf "Getting list of public pictures for '%s'\n", $ARGV[0];
17:}
18:my $api = new Flickr::API({
19: 'key' => API_KEY}
20: );
21:my $ua = LWP::UserAgent->new;
22:# Get the user NSID first
23:my $response = $api->execute_method(
24: 'flickr.people.findByUsername', {
25: 'username' => $ARGV[0]
26: });
27:if (! $response->{success}) {
28: die "[ERROR]: " . $response->{error_message} . " ($ARGV[0])";
29:}
30:# Parse the tree and get the NSID
31:my %tree = %{$response->{tree}};
32:# Cheat with 'print Dumper($tree);' to get the value I want right away
33:my $id = $tree{children}->[1]->{attributes}->{nsid};
34:if (DEBUG) {
35: printf "%s\n", $id;
36:}
37:# Get now the list of public photos
38:$response = $api->execute_method(
39: 'flickr.photos.search', {
40: 'user_id' => $id
41: });
42:%tree = %{$response->{tree}};
43:# Get the photo information. For that we get a more manageable structure
44:my @subtree = @{$tree{children}->[1]->{children}};
45:if (DEBUG) {
46: print Dumper(\@subtree);
47:}
48:foreach my $ref (@subtree) {
49: my $attributes = $$ref{attributes};
50: next if $attributes == undef;
51: # Construct the URL like this:
52: # http://photos{server-id}.flickr.com/{id}_{secret}_o.(jpg|gif|png)
53: my $url = "http://photos" .
54: $$attributes{'server'} .
55: ".flickr.com/" .
56: $$attributes{'id'} .
57: "_" .
58: $$attributes{'secret'} .
59: "_o.jpg";
60: printf "Downloading: %s -> %s...", $$attributes{'title'}, $url;
61: $ua->mirror(
62: $url,
63: $$attributes{'id'} . "_" . $$attributes{'secret'} . "_o.jpg"
64: );
65: if ($response->is_success) {
66: printf "OK\n";
67: } else {
68: printf "ERROR\n";
69: }
70:
71:}
72:__END__

El programa se corre así:

[josevnz@localhost fotos]$ ../DownloadPublicPictures.plx josevnz2
Getting list of public pictures for ‘josevnz2’
Downloading: I95 snow -> http://photos5.flickr.com/4746321_036bd281f6_o.jpg…OK
Downloading: Teatro Avon Enero 2005 -> http://photos5.flickr.com/4746319_215f0d4490_o.jpg…OK
Downloading: mudanza de servidores -> http://photos4.flickr.com/4640875_5e09991db5_o.jpg…OK
Downloading: rack de servidores -> http://photos3.flickr.com/4640874_8c8648dd32_o.jpg…OK
Downloading: Lanzamiento de CVEBrowser -> http://photos3.flickr.com/4592140_5037d50d90_o.jpg…OK
Downloading: Montes East Village Manhattan New York -> http://photos4.flickr.com/4294649_99a73efb94_o.jpg…OK
Downloading: The Olive Tree East Village Manhattan New York -> http://photos1.flickr.com/4294648_f867326f0a_o.jpg…OK
Downloading: mazinger-flash -> http://photos3.flickr.com/4177404_b1ba64e2f9_o.jpg…OK
Downloading: Regalos de cumpleaños: DVD -> http://photos4.flickr.com/4145436_781e968181_o.jpg…OK
Downloading: Ipod Edición Especial de U2: El objeto de mi deseo -> http://photos3.flickr.com/3573557_0d1a452590_o.jpg…OK
Downloading: Stamford Enero 2005: Frio maldito -> http://photos2.flickr.com/3573556_1bdc308657_o.jpg…OK
Downloading: The Aviator -> http://photos3.flickr.com/3571985_583e39b9f3_o.jpg…OK
Downloading: Blood Rayne 1 y Blood Rayne 2: Las sagas -> http://photos3.flickr.com/3526934_7d3a658771_o.jpg…OK
Downloading: Blood Rayne 2: Yo tomando un descanzo -> http://photos3.flickr.com/3526930_520f38ac88_o.jpg…OK
Downloading: Blood Rayne 2: Final -> http://photos3.flickr.com/3526927_e64cb0a886_o.jpg…OK
Downloading: Battlestar Galatica site -> http://photos3.flickr.com/3431907_6819a3c7bc_o.jpg…OK

¡Chevere!. Ya con esto me bajé todas mis fotos :D. Por cierto, para dejar varias fotos a la vez en Flickr, yo utilizo FlickrUploadr, bien sencilla de usar (escrita en Python) y sobre todo, trabaja muy bien bajo Linux…

Como siempre les dejo el código fuente para que se diviertan.