Flickr-to-Picasa Migration tool


/ Published in: Python
Save to your folder(s)

A command line tool to transfer all photos from Flickr to Picasa


Copy this code and paste it in your HTML
  1. import flickrapi
  2. import sqlite3
  3. import gdata.photos.service
  4. import gdata.media
  5. import gdata.geo
  6. import urllib
  7. import re
  8. import os
  9. import time
  10. import urllib2
  11. import socket
  12. import sys
  13.  
  14. #===============================================================================
  15. # o = MyFLickrPicasa()
  16. # o.flickr_init()
  17. # o.do_loopbackup()
  18. # o.flickrdb_release()
  19. #===============================================================================
  20.  
  21. class MyFLickrPicasa:
  22. """Flickr"""
  23. flickr_api_key = '------------------------------------'
  24. flickr_api_secret = '------------------------------------'
  25. flickr_token = None
  26. flickr_frob = None
  27. flickr = None
  28.  
  29. """Sqlite"""
  30. conn = None
  31. c = None
  32.  
  33. """Picasa Web API"""
  34. picasa_email = '[email protected]'
  35. picasa_pass = '------------------------------------'
  36. gd_client = None
  37.  
  38. def __init__(self):
  39. # Kiem tra internet connection den google
  40. if self.picasa_checkinternetconn() <> True:
  41. sys.exit("Internet connection failed!")
  42. self.flickrdb_init()
  43. self.picasa_auth()
  44.  
  45. def flickr_init(self):
  46. self.flickr = flickrapi.FlickrAPI(self.flickr_api_key, self.flickr_api_secret)
  47. (self.flickr_token, self.flickr_frob) = self.flickr.get_token_part_one(perms='write')
  48. if not self.flickr_token: raw_input("Press ENTER after you authorized this program")
  49. self.flickr.get_token_part_two((self.flickr_token, self.flickr_frob))
  50.  
  51. def flickr_walkall(self):
  52. print 'fetch all your photos...'
  53. for photo in self.flickr.walk(user_id='me', content_type=7, media='photos'):
  54. x = photo.get('id')
  55. self.flickrdb_add(x)
  56. print x
  57.  
  58. def flickrdb_init(self):
  59. self.conn = sqlite3.connect('flickr.db')
  60. self.conn.isolation_level = None
  61. self.c = self.conn.cursor()
  62. # Create table
  63. self.c.execute('''CREATE TABLE IF NOT EXISTS photos (photoid text)''')
  64.  
  65. def flickrdb_add(self, photoid):
  66. self.conn.execute("insert into photos(photoid) values ('%s')" % photoid)
  67.  
  68. def flickrdb_release(self):
  69. self.conn.close()
  70.  
  71. def picasa_auth(self):
  72. self.gd_client = gdata.photos.service.PhotosService()
  73. self.gd_client.email = self.picasa_email
  74. self.gd_client.password = self.picasa_pass
  75. self.gd_client.source = 'exampleCo-exampleApp-1'
  76. self.gd_client.ProgrammaticLogin()
  77.  
  78. def picasa_test(self):
  79. albums = self.gd_client.GetUserFeed()
  80. for album in albums.entry:
  81. print 'Album: %s (%s)' % (album.title.text, album.numphotos.text)
  82.  
  83. def picasa_checkinternetconn(self):
  84. try:
  85. s = socket.socket()
  86. s.connect(('www.google.com', 80))
  87. s.shutdown(socket.SHUT_RDWR)
  88. s.close()
  89. return True
  90. except:
  91. return False
  92.  
  93. def picasa_privatizealbum(self, album):
  94. album.access.text = 'private'
  95. updated_album = self.gd_client.Put(album, album.GetEditLink().href, converter=gdata.photos.AlbumEntryFromString)
  96. return updated_album
  97.  
  98. def flickrdb_count(self):
  99. self.c.execute("SELECT count(*) FROM photos")
  100. photoid = self.c.fetchone()
  101. photoid = str(photoid[0])
  102. print "Hien co: " + photoid + " photos"
  103.  
  104. def do_downloadfile(self, remotef, localf):
  105. try:
  106. os.remove(localf)
  107. except:
  108. print ""
  109.  
  110. try:
  111. u = urllib2.urlopen(remotef)
  112. localFile = open(localf, 'wb')
  113. localFile.write(u.read())
  114. localFile.close()
  115. remote_bytes = int(u.info().getheader('Content-Length', None))
  116. local_bytes = int(os.path.getsize(localf))
  117.  
  118. if remote_bytes <> local_bytes:
  119. return False
  120. else:
  121. return local_bytes
  122.  
  123. except:
  124. return False
  125.  
  126. return False
  127.  
  128. def do_getalbum(self, photoid):
  129. defaultalbum_maxno = 0
  130. defaultalbum_object = {}
  131. # Thu lay ten album tren Flickr
  132. try:
  133. sets = self.flickr.photos_getAllContexts(photo_id=photoid)
  134. sets = sets.find('set').attrib['title']
  135. sets = re.sub(r"(?i)[^\x2D\sa-zA-Z0-9]", "a", sets)
  136. except:
  137. # Khong co set, thu gan ten album mac dinh cua Picasa
  138. sets = None #'Default Album'
  139.  
  140. albums = self.gd_client.GetUserFeed()
  141. for album in albums.entry:
  142. # album.title.text,album.numphotos.text, album.gphoto_id.text
  143. if album.title.text == sets and int(album.numphotosremaining) > 3:
  144. return album
  145.  
  146. match = re.search(r"Default Album (\d{1,5})", album.title.text, re.IGNORECASE)
  147. if match:
  148. x = int(match.group(1))
  149. if x > defaultalbum_maxno:
  150. defaultalbum_maxno = x
  151. if int(album.numphotosremaining) > 3:
  152. defaultalbum_object[x] = album
  153.  
  154. # Khong co album nao duoc tim thay, tao moi 1 album
  155. if sets <> None:
  156. album = self.gd_client.InsertAlbum(title=sets, summary='This is an album')
  157. return album
  158. else:
  159. if len(defaultalbum_object) > 0:
  160. # Lay bat ky album nao va add vao
  161. for k, v in defaultalbum_object.iteritems():
  162. album = v
  163. return album
  164. else:
  165. album = "Default Album " + str(defaultalbum_maxno + 1)
  166. album = self.gd_client.InsertAlbum(title=album, summary='This is an album')
  167. return album
  168.  
  169. def picasa_checkquota(self):
  170. # Kiem tra quota upload cua user
  171. x = self.gd_client.GetUserFeed()
  172. x = float(x.quotacurrent.text) / float(x.quotalimit.text)
  173. if x > 0.8:
  174. # Da het quota
  175. return False
  176. else:
  177. return True
  178.  
  179. def do_loopbackup(self):
  180. m_time = 0
  181. while True:
  182. now_time = time.time()
  183. if m_time == 0:
  184. m_time = time.time()
  185. if (now_time - m_time) > (5*60*60):
  186. m_time = 0
  187. ok = raw_input('Nhan y de tiep tuc, nhan n de thoat chuong trinh:')
  188. if ok in ('n', 'no', 'nop', 'nope'):
  189. return False
  190.  
  191. self.do_flickr2picasa()
  192.  
  193.  
  194. def do_flickr2picasa(self):
  195. # Kiem tra internet connection den google
  196. if self.picasa_checkinternetconn() <> True:
  197. print "Internet connection failed!"
  198. time.sleep(30) # Dung 30s truoc khi thu lai
  199. return None
  200.  
  201. # Kiem tra quota
  202. if self.picasa_checkquota() <> True:
  203. print "Out of quota! Please upgrade!"
  204. return None
  205.  
  206. # Lay mot photoid bat ky trong FlickrDB
  207. try:
  208. self.c.execute("select photoid from photos limit 1")
  209. photoid = self.c.fetchone()
  210. photoid = photoid[0]
  211. except:
  212. print "Khong co bat ky ID nao trong DB"
  213. return None
  214. # Ket noi voi Flickr de nhan thong tin ve Photo
  215. #photoid = '3278705476'
  216. print "---------------------------------------------------------"
  217. self.flickrdb_count()
  218. print "Backing up photo #" + str(photoid)
  219. photo = self.flickr.photos_getInfo(photo_id=photoid)
  220. if photo.attrib['stat'] <> 'ok':
  221. return None
  222. # Chuan bi cac bien de post len Picasa
  223. photo_url = "http://farm"+photo.find('photo').attrib['farm']+".static.flickr.com/"+photo.find('photo').attrib['server']+"/"+photo.find('photo').attrib['id']+"_"+photo.find('photo').attrib['originalsecret']+"_o."+photo.find('photo').attrib['originalformat']+""
  224. photo_local = photo.find('photo').attrib['id'] +"."+ photo.find('photo').attrib['originalformat']
  225. photo_title = str(photoid)
  226. photo_summary = "Photo: " + unicode(photo.find('photo').find('title').text) + " - " + unicode(photo.find('photo').find('description').text) + " . FlickrID:" + str(photoid)
  227. photo_summary = photo_summary[:250]
  228.  
  229. #unicode
  230. photo_title = photo_title.decode("utf-8", "replace")
  231. #photo_summary = photo_summary.decode("utf-8", "replace")
  232. # Them tag, geotag vao photo
  233. # <dates posted="1234610523" taken="2009-02-14 03:37:11" takengranularity="0" lastupdate="1278990813" />
  234. try:
  235. e_taglist = []
  236. for e in photo.find('photo').find('tags').findall('tag'):
  237. if int(e.attrib['machine_tag']) == 0:
  238. e_taglist.append(re.sub(r"(?i)[^\x2D\sa-zA-Z0-9]", "a", e.text))
  239. e_tag = ",".join(e_taglist)
  240. print "Tags: " + e_tag
  241. except:
  242. e_tag = ""
  243.  
  244. try:
  245. e_geotag = photo.find('photo').find('location')
  246. e_geotag = '%s %s' % (e_geotag.attrib['latitude'], e_geotag.attrib['longitude'])
  247. except:
  248. e_geotag = '%s %s' % ('16.04389', '108.19944')
  249.  
  250. # Download anh goc ve may tinh
  251.  
  252.  
  253. try:
  254. #x = None
  255. #urllib.urlretrieve (photo_url, photo_local)
  256. photo_bytes = self.do_downloadfile(photo_url, photo_local)
  257. if photo_bytes < 1 or photo_bytes is False:
  258. raise Exception()
  259. except:
  260. print "Khong the download duoc file"
  261. return None
  262.  
  263. # File da download, connect den Picasa
  264. # Tim va xu ly Album
  265. photo_picasa_album = self.picasa_privatizealbum(self.do_getalbum(photoid))
  266. photo_picasa_album_url = '/data/feed/api/user/%s/albumid/%s' % ('default', photo_picasa_album.gphoto_id.text)
  267.  
  268.  
  269. try:
  270. new_entry = self.gd_client.InsertPhotoSimple(photo_picasa_album_url, photo_title, photo_summary, photo_local)
  271. # kiem tra tinh xac thuc cua anh duoc upload
  272. uploaded_bytes = int(new_entry.size.text)
  273. if uploaded_bytes <> photo_bytes:
  274. # Xoa anh da upload
  275. self.gd_client.Delete(new_entry)
  276. raise Exception()
  277. except:
  278. print "Khong the upload duoc file"
  279. print sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]
  280. return None
  281.  
  282. try:
  283. new_entry.media.keywords = gdata.media.Keywords()
  284. new_entry.media.keywords.text = e_tag
  285. except:
  286. print sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]
  287.  
  288. new_entry.geo = gdata.geo.Where()
  289. new_entry.geo.Point = gdata.geo.Point()
  290. new_entry.geo.Point.pos = gdata.geo.Pos(text=e_geotag)
  291. updated_entry = self.gd_client.UpdatePhotoMetadata(new_entry)
  292.  
  293. # Da upload thanh cong, xoa file local
  294. try:
  295. os.remove(photo_local)
  296. except:
  297. print ""
  298.  
  299. # Sau khi da xoa file, xoa entry trong database Sqlite
  300. self.c.execute("delete from photos where photoid='"+photoid+"'")
  301. print "Successfully backed up #" + str(photoid)
  302. return True
  303.  
  304. #print photo_picasa_album.title.text
  305. #print photo_picasa_album.gphoto_id.text
  306. #print photo_url
  307. #print e_geotag
  308. #print photo_picasa_album_url

Report this snippet


Comments

RSS Icon Subscribe to comments

You need to login to post a comment.