My photo captions have
evolved into a form of milliblogging. Milliposts (milliblog posts) are terse and
tiny; many are single sentences or paragraphs. Taken one-at-a-time
milliposts seldom impress but when gathered in hundreds or
thousands accidental epics emerge. So, to prevent "epic loss" I want
a simple way of downloading and archiving my captions off-line.

When I started blogging I knew
that you could not depend on blogging websites to archive and
preserve your documents. We had already seen cases of websites mangling content, shutting
down without warning, and even worse, censoring bloggers. It was a classic case
of, “If you don't control it you cannot trust it." I resolved to maintain complete off-line version
controlled copies of my blog posts.

Maintaining off-line copies was made easier by
WordPress.com's excellent blog export
utility. A
simple button push downloads a large XML file that contains all your
blog posts with embedded references to images and other inclusions. XML
is not my preferred archive format. I am a huge fan of LaTeX and
Markdown: two text formats that are directly supported in Jupyter
Notebooks. I wrote a little system that parses the WordPress XML file and generates
LaTeX and Markdown files. Yet, despite milliblogging long before blogging, I don't have a similar system for
downloading and archiving Smugmug metadata. This Jupyter notebook addresses this omission
and shows how you can use Python and the Smugmug API to extract gallery
and image metadata and store it in version controlled local directories as CSV files.

The originals did not run in the Python 3.6/Jupyter/Win64 environment and lacked some of
the facilities I wanted so I adjusted, tweaked and modified the scripts. The result
is incompatible with the originals so I renamed the main class SmugPyter to avoid confusion.
Finally, being new to Python and Jupyter, I used the 2to3 tool to help make the changes.

The SmugPyter class constuctor reads a config file. If this file is missing
you cannot create instances of the SmugMug class or connect to your SmugMug account.

In [2]:

# the SmugPyter class constuctor reads a config file in this location.os.path.join(os.path.expanduser("~"),'.smugpyter.cfg')

Out[2]:

'C:\\Users\\john\\.smugpyter.cfg'

The following prompts for your SmugMug API keys. You can apply for SmugMug keys on your SmugMug account by browsing to the API KEYS section of your account settings.

In [ ]:

# code from https://github.com/speedenator/smuploader/blob/master/bin/smregister# modified for python 3.6/jupyter environment - modifications assisted by 2to3 tool fromrauth.serviceimportOAuth1Serviceimportrequestsimporthttp.clientimporthttplib2importhashlibimporturllib.request,urllib.parse,urllib.errorimporttimeimportsysimportosimportjsonimportconfigparserimportreimportshutil# depends on previously run cells #from smuploader import SmugMugdefwrite_config(configfile,params):config=configparser.ConfigParser()config.add_section('SMUGMUG')forkey,valueinparams:config.set('SMUGMUG',key,value)withopen(SmugMug.smugmug_config,'w')asf:config.write(f)if__name__=='__main__':print("\n\n\n#######################################################")print("## Welcome! ")print("## We are going to go through some steps to set up this SmugMug photo manager and make it connect to the API.")print("## Step 0: What is your SmugMug username?")username=input("Username: ")print('## Step 1: Enter your local directory, e.g. c:/SmugMirror/')localdir=input("Directory: ")print("## Step 2: Go to https://api.smugmug.com/api/developer/apply and apply for an API key.")print("## This gives you unique identifiers for connecting to SmugMug.")print("## When done, you can find the API keys in your SmugMug profile.")print("## Account Settings -> Me -> API Keys")print(("## Enter them here and they will be saved to the config file ("+SmugMug.smugmug_config+") for later use."))consumer_key=input("Key: ")consumer_secret=input("Secret: ")write_config(SmugMug.smugmug_config,[("username",username),("consumer_key",consumer_key),("consumer_secret",consumer_secret),("access_token",''),("access_token_secret",'')])smugmug=SmugMug()authorize_url=smugmug.get_authorize_url()print(("## Step 2: Visit this address in your browser to authenticate your new keys for access your SmugMug account: \n## "+authorize_url))print("## After that, enter the 6-digit key that SmugMug provided")verifier=input("6-digit key: ")access_token,access_token_secret=smugmug.get_access_token(verifier)write_config(SmugMug.smugmug_config,[("username",username),("consumer_key",consumer_key),("consumer_secret",consumer_secret),("access_token",access_token),("access_token_secret",access_token_secret)])print("## Great! All done!")

Try out the SmugPyter class with credentials saved in the previous cell.¶

The next cell calls the main function that walks SmugMug folders and writes metadata to local directories. Metadata is saved in TAB delimited CSV manifest files. TAB delimited files are also called TSV files. The function writes one file per album. If local directories do not exist they are created. If manifest files already exist they are are overwritten. The entire SmugMug tree is walked. You might want to adjust where the walk starts if you have hundreds or thousands of albums.

visiting album GreatandGreaterForebearers
visiting album MinnieRaver
visiting album Grandparents
visiting album MyKids
visiting album TheWayWeWere
visiting album FromHazelsAlbums
visiting album InlawsOutlawsandFriends
visiting album MyWifesFamily
visiting album HelenHamilton
visiting album Video
visiting album IdahoInstants
visiting album InandAroundOttawa
visiting album MontanaNowandThen
visiting album IndianaImages
visiting album Minnesota
visiting album NewMexicoMontage
visiting album MissouriMoments
visiting album KingstonOntario
visiting album CaliforniaCaptures
visiting album Iran1960s
visiting album Ghana1970s
visiting album BeirutLebanon1960s
visiting album DivingatBellairsBarbadosBW
visiting album Weekenders
visiting album WesternRoadTrip2015
visiting album NorthbyNorthwest
visiting album TetonsYellowstone2013
visiting album ArizonaToodling
visiting album AlongtheYukonRiver
visiting album VirginiaFall2010
visiting album Chicago2007
visiting album NewYork2005
visiting album BanffandJasper2006
visiting album SouthAmerica1979
visiting album EnewetakAtoll1980s
visiting album ACSSchoolTrips1960s
visiting album ZambiaEclipseTrip
visiting album BrieflyBermuda
visiting album Panoramas
visiting album ImageHacking
visiting album Restorations
visiting album PartialRestorations
visiting album LogosScreenshotsCovers
visiting album Abodes
visiting album CaughtMyEye
visiting album DoesNotFit
visiting album FlatThings
visiting album CellPhoningItIn
visiting album BeenThereDoneThat
visiting album Fiscal2009
visiting album ToMuchInformation
visiting album CrippleChronicles
visiting album 63
visiting album DirectCellUploads
visiting album utilimages
visiting album MySmugMugSiteFiles
visiting album smugsitefiles
visiting album CameraAwesomePhotos
empty album CameraAwesomePhotos
visiting album CameraAwesomeArchive
empty album CameraAwesomeArchive
visiting album Email
empty album Email
done

Remember how "no good dead goes unpunished." Well, running code will be "enhanced" whether it's necessary or not.
Now that I have a local directories that contain relevant SmugMug metadata in an easily consumed CSV form other notebooks will use these directories to generate what I call "long duration documents." My prefered long duration sources are Markdown and LaTex. Both of these text formats will be readable for centuries if printed on high quality acid free paper and stored in numerous "secure and undisclosed locations."