niedziela, 14 września 2008

Wyszukiwanie zdjeć na flickr.com

W książce Flickr Hacks Paula Bauscha i Jima Bumgardnera do manipulowania danymi w formacie XML przesyłanymi z flickr.com używa się XML::Simple. Jakoś XML::Simple nie wydaje mi się specjalnie simple w tym wypadku. Zdecydowanie wolę XML::LibXML, który pozwala przede wszystkim na dotarcie do poszczególnych fragmentów dokumentów XML w prosty sposób bez używania karkołomnych referencji. Przykładowo poniższy skrypt (fragment) wykonuje zapytanie flickr.photos.search [najistotniejszą częścią skryptu -- zaznaczoną odmiennym kolorem tła -- jest pętla do { ... }]:


use XML::LibXML;
use LWP::Simple;
use Getopt::Long;

require 'login2flickr.rc';

our $api_key;
our $my_flickr_id;

my $tags_txt;
my $show_help;
my ($user_id, $all_users, $report_views);
my @Photos;

GetOptions( "all" => \$all_users,
"user=s" => \$user_id, "views" => \$report_views,
"tags=s" => \$tags_txt);

unless ( $user_id ) { $user_id = $my_flickr_id; }
if ( $all_users ) { $user_id = ''; } ## search all photos

my $parser = XML::LibXML->new;
my $pageno;
my $method = 'flickr.photos.search';
my $max_per_page = 500;
my ($total_pages, $current_page);

my $search_query = "&extras=geo,views"; # http://www.flickr.com/services/api/flickr.photos.search.html
if ( $user_id ) { $search_query .= "&user_id=$user_id"; }
if ( $tags_txt ) { $search_query .= "&tags=$tags_txt" }


do {
$pageno++;

my $resp = get ( "http://www.flickr.com/services/rest/?" .
"method=$method&api_key=$api_key&per_page=$max_per_page&page=$pageno" .
$search_query );

## sprawdź czy jest OK:
my $photos = $parser->parse_string($resp);
unless ( $photos->getElementsByTagName('rsp' )->[0]->getAttribute( 'stat' ) eq 'ok') {
die "Problems with retriving photo list!\n" }

push @Photos, $photos->getElementsByTagName('photo' );

$total_pages = $photos->getElementsByTagName('photos' )->[0]->getAttribute('pages' );
$current_page = $photos->getElementsByTagName('photos' )->[0]->getAttribute('page' );

# Dla dużych zbiorów zdjęć może długo trwać, więc wypisz że coś robisz:
printf STDERR " *** Page %d of %d retreived...\n", $current_page, $total_pages;

} while ( $current_page lt; $total_pages );

## Lista @Photos zawiera wszystkie zdjęcia...
## ... dalsza część skryptu ...

Pętla jest niezbędna ponieważ flickr API organicza wielkość zwracanego dokumentu do maksymalnie 500 zdjęć. Jeżeli zdjęć jest więcej, to zapytanie należy zadać wielokrotnie, zmieniając wartość parametru page. Przy czym liczbę wszystkich stron określa wartość atrybutu pages.

Po ściągnięciu dokumentu skrypt sprawdza czy wszystko jest OK. Jeżeli tak, to za pomocą getElementsByTagName pobiera wszystkie elementy photo i dodaje je do listy @Photos. Teraz pobierane są wartości atrybutów pages/page w celu ustalenia czy wszystko już ściągnięto. Jeżeli pages < page to pętla działa dalej...

Zwracam uwagę, że od jakiegoś czasu zapytanie może zawierać parametr extras, dzięki któremu zwracany dokument XML zawiera dodatkowe informacje, takie jak: tagi, współrzędne geograficzne, liczbę odsłon, itd... Jest to opisane w API na flickr.com a także tutaj. W wyżej przedstawionym skrypcie deklaracja:


my $search_query = "&extras=geo,views";

Oznacza, że do standardowych opisów zdjęć będą dodane także współrzędne geograficzne (oczywiście tylko wtedy gdy zdjęcia będą nimi oznaczone) oraz liczba odsłon. BTW dodanie extras=views powoduje, że kiedyś niemożliwy do wykonania poprzez API problem ustalenia ile razy zdjęcie było oglądane teraz jest jak najbardziej wykonalny. Zatem skrypty -- opisane w Nowa usługa na flickr.com oraz Czy flickr umie liczyć -- lepsze rozwiązanie -- są już niepotrzebne.

Kompletny skrypt pobierający zdjęcia z flickr.com i wypisujący plik GPX dla tych, które zawierają współrzędne geograficzne jest tutaj. Ale uwaga: próba wykonania zestawienia wszystkich wież ciśnień z flickr.com:


flickr_photo_gsearch.pl -a -t 'wieżaciśnień,wasserturm,watertower' > wasserturme-alles.xml

Skończyła się pobraniem ponad 23 tysięcy zdjęć (z tego około 6 tys. było geokodowane). Plik GPX pn. wasserturme-alles.xml miał 1,8 Mb i za nic nie szło tego wyświetlić w przeglądarce. Za duże... Mniejsze pliki są ok: kaplice [mapa ] albo moje wieże ciśnień [mapa ].

Brak komentarzy:

Prześlij komentarz