Many Internet websites provide a web services interface through their REST APIs. Flickr, a famous photo sharing website, has a REST interface. Let's try to gather some photo information to build a specialized database or other photo-related application.
We need the REST URLs for making the HTTP requests. For simplicity's sake, the URLs are hard coded in this recipe. We can use the third-party requests
module to make the REST requests. It has the convenient get()
, post()
, put()
, and delete()
methods.
In order to talk to Flickr web services, you need to register yourself and get a secret API key. This API key can be placed in a local_settings.py
file or supplied via the command line.
Listing 8.4 gives the code for collecting some photo information from Flickr using REST, as shown:
#!/usr/bin/env python # Python Network Programming Cookbook -- Chapter – 8 # This program is optimized for Python 2.7. # It may run on any other version with/without modifications. import argparse import json import requests try: from local_settings import flickr_apikey except ImportError: pass def collect_photo_info(api_key, tag, max_count): """Collects some interesting info about some photos from Flickr.com for a given tag """ photo_collection = [] url = "http://api.flickr.com/services/rest/?method=flickr.photos.search&tags=%s&format=json&nojsoncallback=1&api_key=%s" %(tag, api_key) resp = requests.get(url) results = resp.json() count = 0 for p in results['photos']['photo']: if count >= max_count: return photo_collection print 'Processing photo: "%s"' % p['title'] photo = {} url = "http://api.flickr.com/services/rest/?method=flickr.photos.getInfo&photo_id=" + p['id'] + "&format=json&nojsoncallback=1&api_key=" + api_key info = requests.get(url).json() photo["flickrid"] = p['id'] photo["title"] = info['photo']['title']['_content'] photo["description"] = info['photo']['description']['_content'] photo["page_url"] = info['photo']['urls']['url'][0]['_content'] photo["farm"] = info['photo']['farm'] photo["server"] = info['photo']['server'] photo["secret"] = info['photo']['secret'] # comments numcomments = int(info['photo']['comments']['_content']) if numcomments: #print " Now reading comments (%d)..." % numcomments url = "http://api.flickr.com/services/rest/?method=flickr.photos.comments.getList&photo_id=" + p['id'] + "&format=json&nojsoncallback=1&api_key=" + api_key comments = requests.get(url).json() photo["comment"] = [] for c in comments['comments']['comment']: comment = {} comment["body"] = c['_content'] comment["authorid"] = c['author'] comment["authorname"] = c['authorname'] photo["comment"].append(comment) photo_collection.append(photo) count = count + 1 return photo_collection if __name__ == '__main__': parser = argparse.ArgumentParser(description='Get photo info from Flickr') parser.add_argument('--api-key', action="store", dest="api_key", default=flickr_apikey) parser.add_argument('--tag', action="store", dest="tag", default='Python') parser.add_argument('--max-count', action="store", dest="max_count", default=3, type=int) # parse arguments given_args = parser.parse_args() api_key, tag, max_count = given_args.api_key, given_args.tag, given_args.max_count photo_info = collect_photo_info(api_key, tag, max_count) for photo in photo_info: for k,v in photo.iteritems(): if k == "title": print "Showing photo info...." elif k == "comment": " Photo got %s comments." %len(v) else: print " %s => %s" %(k,v)
You can run this recipe with your Flickr API key either by placing it in a local_settings.py
file or supplying it from the command line (via the --api-key
argument). In addition to the API key, a search tag and maximum count of the result arguments can be supplied. By default, this recipe will search for the Python
tag and restrict the result to three entries, as shown in the following output:
$ python 8_4_get_flickr_photo_info.py Processing photo: "legolas" Processing photo: ""The Dance of the Hunger of Kaa"" Processing photo: "Rocky" description => Stimson Python Showiing photo info.... farm => 8 server => 7402 secret => 6cbae671b5 flickrid => 10054626824 page_url => http://www.flickr.com/photos/102763809@N03/10054626824/ description => " 'Good. Begins now the dance--the Dance of the Hunger of Kaa. Sit still and watch.' He turned twice or thrice in a big circle, weaving his head from right to left. Then he began making loops and figures of eight with his body, and soft, oozy triangles that melted into squares and five-sided figures, and coiled mounds, never resting, never hurrying, and never stopping his low humming song. It grew darker and darker, till at last the dragging, shifting coils disappeared, but they could hear the rustle of the scales." (From "Kaa's Hunting" in "The Jungle Book" (1893) by Rudyard Kipling) These old abandoned temples built around the 12th century belong to the abandoned city which inspired Kipling's Jungle Book. They are rising at the top of a mountain which dominates the jungle at 811 meters above sea level in the centre of the jungle of Bandhavgarh located in the Indian state Madhya Pradesh. Baghel King Vikramaditya Singh abandoned Bandhavgarh fort in 1617 when Rewa, at a distance of 130 km was established as a capital. Abandonment allowed wildlife development in this region. When Baghel Kings became aware of it, he declared Bandhavgarh as their hunting preserve and strictly prohibited tree cutting and wildlife hunting... Join the photographer at <a href="http://www.facebook.com/laurent.goldstein.photography" rel="nofollow">www.facebook.com/laurent.goldstein.photography</a> © All photographs are copyrighted and all rights reserved. Please do not use any photographs without permission (even for private use). The use of any work without consent of the artist is PROHIBITED and will lead automatically to consequences. Showiing photo info.... farm => 6 server => 5462 secret => 6f9c0e7f83 flickrid => 10051136944 page_url => http://www.flickr.com/photos/designldg/10051136944/ description => Ball Python Showiing photo info.... farm => 4 server => 3744 secret => 529840767f flickrid => 10046353675 page_url => http://www.flickr.com/photos/megzzdollphotos/10046353675/
This recipe demonstrates how to interact with Flickr using its REST APIs. In this example, the collect_photo_info()
tag takes three parameters: Flickr API key, a search tag, and the desired number of search results.
We construct the first URL to search for photos. Note that in this URL, the value of the method parameter is flickr.photos.search
and the desired result format is JSON.
The results of the first get()
call are stored in the resp
variable and then converted to the JSON format by calling the json()
method on resp
. Now, the JSON data is read in a loop looking into the ['photos']['photo']
iterator. A photo_collection
list is created to return the result after organizing the information. In this list, each photo information is represented by a dictionary. The keys of this dictionary are populated by extracting information from the earlier JSON response and another GET
request to get the information regarding the specific photo.
Note that to get the comments about a photo, we need to make another get()
request and gather comment information from the ['comments']['comment']
elements of the returned JSON. Finally, these comments are appended to a list and attached to the photo dictionary entry.
In the main function, we extract the photo_collection
dictionary and print some useful information about each photo.
3.144.91.24