flickr ist eine Seite, die ich laufend beobachtet, aber nie so richtig genutzt habe. Bei meinen Streifzügen durch das Netz hab ich sie dann mal wieder seit einiger Zeit in Augenschein genommen und wollte mir die beliebtesten Bilder herausfischen. Es zeigt sich, dass man sehr gut nach einzelnen Stichworten suchen kann, aber als Übersicht über die beliebtesten Bilder nur einen Kalender Interesting findet. Dieser listet eine Übersicht über alle Tage und bietet einen Link zu den 500 beliebtesten Fotos des jeweiligen Tages. Ich hätte mir aber ein Best of über alle Jahre gewünscht.
Erster Gedanke ist also auf diesen Kalender basierend die beliebtesten Bilder zu ermitteln, sprich alle Tage mittels einem Skript parsen und dann jeweils die 10 beliebtesten Bilder auszugeben. Das Ergebnis ist dann eine Seite mit den schönsten Bilder eines Monats, wobei von jedem Tag die 10 beliebtesten Bilder zu sehen sind. Was sich kompliziert anhört ist mit dem Zend Framework in wenigen Zeilen passiert. Da es ein super Beispiel für Zend_Dom und Zend_Http ist, hab ich mich entschlossen die kurze Lösung hier zu präsentieren.
Folgende Dinge müssen im Skript ablaufen:
- Der Start und End Zeitpunkt werden gesetzt
- In einer Schleife werden die nächsten Schritte wiederholt, so lange das aktuelle Datum nicht größer als das Enddatum ist.
- Die URL zu der Kalenderseite auf flickr wird erzeugt (diese hat immer den gleichen Aufbau: http://www.flickr.com/explore/interesting/2008/12/01/page1)
- Der Inhalt der Seite wird mittels Zend_Http geladen
- Die Links zu den Bilder und Bildseiten werden mittels Zend_Dom_Query ausgelesen und in ein Array gesteckt
- Der Tag wird um eins erhöht und es geht bei 2 weiter
Im ersten Schritt wird also der Start und Endzeitpunkt festgelegt. Dafür ist Zend_Date zuständig.
$start = new Zend_Date();
$start->set('01.11.2008',Zend_Date::DATE_MEDIUM);
$stop = new Zend_Date();
$stop->set('05.11.2008',Zend_Date::DATE_MEDIUM);
Die Methode set erwartet einen String, der dann je nach zweiten Parameter geparst wird (so ist als zweiter Parameter z.B. auch Zend_Date::DATE_SHORT möglich, das dem Format dd.MM.YY entspricht).
Als zweiten Schritt wird geprüft ob $start nach $end liegt. Dafür nutzt man die Methode compare des Zend_Date Objektes. -1 als Ergebnis bedeutet das $start zeitlich vor $stop liegt, 1 das $start nach $stop liegt und 0 das $start gleich $stop ist.
while($start->compare($stop)!=1) {
Nun wird die URL erzeugt und die Zielseite mittels Zend_Http geladen:
$url = 'http://www.flickr.com/explore/interesting/' . $start->ToString("YYYY/MM/dd");
$client = new Zend_Http_Client($url);
$response = $client->request();
$flickr = $response->getBody();
Wird ein Objekt vom Typ Zend_Http_Client instanziiert, so muss als Konstruktorparameter die Ziel-URL angegeben werden. Die Methode request fordert die Seite dann an. Hier kann sehr genau festgelegt werden was im Header stehen soll und es besteht auch die Möglichkeit Cookies für einen Request zu setzen. Der HTTP Client von Zend ist mit sehr vielen Funktionen ausgestattet, welche in der Doku sehr gut erklärt werden. Als Ergebnis liefert die Methode request ein Objekt vom Typ Zend_Http_Response, das sämtliche Informationen der Rückantwort enthält (Header und natürlich den Content). Der HTML Text der Zielseite lässt sich mittels getBody als String auslesen.
Zend_Dom hilft uns nun die wichtigen Informationen (die Bilder sowie die Links zu den Detailseiten der Bilder) zu extrahieren. Es parst den Text als eine DOM Struktur und bietet über das Objekt Zend_Dom_Query die Möglichkeit mittels CSS Selektoren oder XPath Elemente abzufragen. Vor allem das Arbeiten mit CSS Selektoren ist an der Stelle ein Luxus, da sehr viele bereits mit CSS oder auch JavaScript Frameworks Erfahrung haben und so intuitiv Zend_Dom_Query verwenden können. In diesem Beispiel werden die Bilder über ihren CSS Klassennamen selektiert:
$dom = new Zend_Dom_Query($flickr);
$images = $dom->query('.pc_img');
$links = $dom->query('.pc_m a');
$images und $links sind Objekte vom Typ Zend_Dom_Query_Result, welches das Iterable Interface implementiert und somit in einer foreach Schleife durchlaufen werden kann. Das wird auch gleich genutzt um das Zielarray zu befüllen (optional könnte man das Ergebnis auch in eine Datenbank schreiben oder direkt ausgeben):
foreach($images as $image) {
$photos[] = array(
"src" => $image->getAttribute("src"),
"title" => $image->getAttribute("alt"),
"href" => $links->current()->getAttribute("href"),
);
$links->next();
}
Schließlich wird der Tag um eins erhöht und das Ganze kann von vorne beginnen:
$start->add('1', Zend_Date::DAY);
Am Ende hat man dann das Array, welches auf vielfältige Weise weiterverarbeitet werden kann. In diesem Beispiel wird es einfach nur ausgegeben.
Das gesamte Skript kann hier heruntergeladen werden. Es ist eine sehr reduzierte Version, die nur das Wesentliche enthält. Für den Eigengebrauch habe ich ein komfortables Skript geschrieben, das zuvor eine JavaScript basierte Zeitauswahl bietet und auch größere Mengen (ganze Jahre) von flickr laden kann (mit Statusanzeige, Browsefunktion etc.). Wer sich hier interessiert kann sich gerne melden.
3. Februar 2009 um 09:46 Uhr
this is a very helpfull tutorial.thank you very much.
18. März 2010 um 18:21 Uhr
[...] habe in diesem Blog ja bereits einmal darüber geschrieben, wie man mit Hilfe des Zend Frameworks fremde Seiten verarbeiten kann. Einen zweiten, sehr eleganten Weg, wie man fremde HTML Seiten verarbeiten kann, bietet die [...]