#!/usr/bin/env python # Download images using the Flickr API. # Adam Sampson import sys, os, getopt, re, flickrapi, ConfigParser, time from xml.etree.ElementTree import tostring def usage(): print """flickr-get by Adam Sampson Usage: flickr-get [OPTION] URL ... Download sets or user photostreams from Flickr. -a, --auth Authenticate using a Flickr account -h, --help Show usage Report bugs to .""" def wget(url, outputfile = None, referer = None, args = []): args = ["wget", "-U", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041219"] + args if outputfile: args += ["-O", outputfile] if referer: args += ["--referer", referer] args += [url] print "Fetching: " + url if os.spawnvp(os.P_WAIT, args[0], args) != 0: die("Command failed: ", args) def safe_fn(s): return re.sub(r'[^A-Za-z0-9_.:\&, -]', '_', s) def get_photo(flickr, photo_id, filename): if os.access(filename, os.F_OK): print "Already exists; not fetching: " + filename return resp = flickr.photos_getSizes(photo_id = photo_id) biggest = None biggest_area = -1 for size in resp.find("sizes").findall("size"): area = int(size.get("width")) * int(size.get("height")) if area > biggest_area: biggest = size biggest_area = area source = biggest.get("source") if source.find("/mobile/") != -1: print "Not a picture: " + source return wget(source, filename) def maybe_mkdir(dir_name): try: os.makedirs(dir_name) except OSError: pass def get_photoset(flickr, photoset_id): resp = flickr.photosets_getInfo(photoset_id = photoset_id) photoset = resp.find("photoset") photoset_title = photoset.find("title").text owner_id = photoset.get("owner") resp = flickr.photosets_getPhotos(photoset_id = photoset_id, extras="owner_name") photoset = resp.find("photoset") owner_name = photoset.get("ownername", owner_id) dir_name = safe_fn(owner_name + " - " + photoset_title) print "Set: %s" % dir_name maybe_mkdir(dir_name) n = 0 for p in reversed(photoset.findall("photo")): n += 1 photo_id = p.get("id") photo_title = p.get("title", photo_id) filename = dir_name + "/" + safe_fn("%03d %s.jpg" % (n, photo_title)) print " Image %d: %s" % (n, filename) get_photo(flickr, photo_id, filename) def get_photostream(flickr, user_url): resp = flickr.urls_lookupUser(url = user_url) user_id = resp.find("user").get("id") print "User ID: " + user_id resp = flickr.people_getInfo(user_id = user_id) person = resp.find("person") dir_name = safe_fn(person.find("username").text + " - Photostream") maybe_mkdir(dir_name) page = 1 while True: resp = flickr.people_getPublicPhotos(user_id = user_id, safe_search = "3", extras = "owner_name,date_upload,tags", page = str(page), per_page = "500") photos = resp.find("photos") for p in reversed(photos.findall("photo")): photo_id = p.get("id") photo_date = p.get("dateupload") format_date = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(int(photo_date))) photo_title = p.get("title") filename = dir_name + "/" + safe_fn("%s %s %s.jpg" % (format_date, photo_id, photo_title)) print " Image: " + filename get_photo(flickr, photo_id, filename) page += 1 if page > int(photos.get("pages")): break def main(args): try: opts, args = getopt.getopt(args, "ah", ["auth", "help"]) except getopt.GetoptError: usage() sys.exit(1) use_auth = False for (o, a) in opts: if o in ("-h", "--help"): usage() sys.exit(0) elif o in ("-a", "--auth"): use_auth = True config = ConfigParser.ConfigParser() config.read(os.getenv("HOME") + "/.flickrrc") key = config.get("config", "key") secret = config.get("config", "secret") flickr = flickrapi.FlickrAPI(key, secret) if use_auth: (token, frob) = flickr.get_token_part_one(perms = "read") if not token: raw_input("Press enter once authenticated") flickr.get_token_part_two((token, frob)) for a in args: m = re.search(r'/sets/([^/]+)/', a) if m is not None: get_photoset(flickr, m.group(1)) continue else: get_photostream(flickr, a) if __name__ == "__main__": main(sys.argv[1:])