Showing posts with label python. Show all posts
Showing posts with label python. Show all posts

Saturday, September 12, 2009

Python API for Flickr Services - Part I

These days I am working on a facebook application that mashes up servises from Facebook and Flickr. The application is hosted by Google Appengine and I am developing on Django web application framework.

Flickr has an easy to use API which is called Flickr Services. Here are some interesting things you can do with the Flickr Services:


  • You can upload photos from anywhere (web application, desktop application or mobile application)
  • You can search for images. Flickr Services lets you search images by
    - tags
    - geo location
    - photo taken time / photo upload time
    - and more...
  • execute methods that require authentication
    - create, edit, remove tags
    - create, edit, remove photo sets
    - replace, remove photos

There are two Python APIs listed in the Flickr Services page:

  1. http://www.stuvel.eu/projects/flickrapi
  2. http://code.google.com/p/flickrpy/

I have implemented Flickr services in Python. Don't think this as "reinventing the wheel" because it was a coding practice for me. Plus, i have my own, customized, shortcut methods ;)

You can download the library from http://code.google.com/p/ilkinulassandbox/. There are also some other javascript and python code snippets there.

Here is a basic usage of the API:

>>> import flickr
>>> api = flickr.FlickrAPI('API_KEY','SECRET_KEY')
>>> api.search({'tags':'python', 'per_page':'3'})
{'photos': {'page': 1,
'pages': 8326,
'perpage': 3,
'photo': [{'farm': 4,
'id': '3911963732',
'isfamily': 0,
'isfriend': 0,
'ispublic': 1,
'owner': '30041312@N03',
'secret': '44aae23e98',
'server': '3090',
'title': 'Centralian Carpet Python (Apophis)'},
{'farm': 3,
'id': '3911184515',
'isfamily': 0,
'isfriend': 0,
'ispublic': 1,
'owner': '30041312@N03',
'secret': '0aae3c8127',
'server': '2513',
'title': 'Centralian Carpet Python (Apophis)'},
{'farm': 3,
'id': '3911127131',
'isfamily': 0,
'isfriend': 0,
'ispublic': 1,
'owner': '31355375@N02',
'secret': '2921fea364',
'server': '2564',
'title': 'Sendra Python Nails 122 01'}],
'total': '24977'},
'stat': 'ok'}

Methods of the API returns a dictionary instance. Caller must handle the returned result.

>>> result = api.search({'tags':'python', 'per_page':'3'})
>>> result['photos']['photo'][0]['id']
'3911751961'


Flickr photo url construction is described here in details. You can easily get the url of a returned photo search result by using build_photo_url. Default image size is 'm' which means 'normal'

>>> api.build_photo_url(result['photos']['photo'][0])
'http://farm4.static.flickr.com/3462/3911751961_43d409cf7c_m.jpg'
>>> api.build_photo_url(result['photos']['photo'][1], size='s')
'http://farm3.static.flickr.com/2613/3911666353_ac0cc98871_s.jpg'


Lets search for pictures tagged 'fun' around point (lat=41.070293, lon=28.24894)

>>> pictures = api.search({'lat':'41.034046', 'lon':'28.980217', 'radius':'10', 'radius_units':'km','tags':'fun'})
>>> api.build_photo_url(fun_pictures['photos']['photo'][20])
'http://farm1.static.flickr.com/116/293251976_ce5337908d_m.jpg'



The next post of "Python API for Flickr Services" will show how you can call methods that require authentication. For the curious readers the api is ready http://code.google.com/p/ilkinulassandbox/. But it lacks documentation :(


NOTE : I use this python API in my facebook application "Türkiye'yi ne kadar iyi tanıyorsun?". Application is a simple guessing game. You see a geo tagged picture from flickr and you answer which city this picture belongs.

UPDATE : This library returns native Python datatypes rather than XML trees or unparsed JSON, which the other Flickr APIs have a tendency to do. (Thanks martian)

Saturday, May 31, 2008

Python Sinema API'si

Vizyondaki filmleri, şehirdeki salonları , filmlerin hangi salonda saat kaçta gösterildiğini bulmaya yarayan bir API yazmaya karar verdim. (Kardeşim ne derdin var durduk yere insan API yazmaya karar verir mi diyenleriniz olabilir. Neden böyle bir API'ye ihtiyaç duyduğumu ilerleyen yazılarda anlatacağım.) Filmler ile ilgili bilgileri, seçeceğim bir sinema sitesinden HTML ayıklama yöntemi (screen scraping) ile almaya karar verdim. Daha doğrusu bu şekilde yapmak zorunda kaldım çünkü delicious, flickr, digg gibi kullanıcılarına API desteği veren türkçe sinema sitesi bulamadım.

Sinema sitelerini teker teker gezerken MyNet'in satın aldığı Beyazperde sitesi dikkatimi cekti.
Beyazperde sitesi anlaşılabilir, temiz URL'ler kullanan ender türkçe sitelerden birisi. Ne demek istediğimi aşağıdaki URL'lere bakınca anlayabilirsiniz.
  • http://beyazperde.mynet.com/salon/10
  • http://beyazperde.mynet.com/film/3945
  • http://beyazperde.mynet.com/seanslar/3945/sehir/462
    Genelde sinemaya Mecidiyekö-Profilo AFM'de gidiyorum. Profilo AFM'nin Beyazperde'deki salon numarası 10 olduğu için gösterimdeki filmleri görmek için uzun uzun ana sayfaya git, şehir seç, salon seç işlemleri yapmıyorum. Firefox'ta adres çubuğuna http://beyazperde.mynet.com/salon/10 yazman AFM Profilo'da gösterimdeki filmlere erişmeme yetiyor.

    Beyazperde sitesindeki filmleri, salonları, seanslari html içerisinden ayıklayabilmek için BeautifulSoup html-xml parser'ını kullandım. BeautifulSoup'tan bu yazımda da bahsetmiştim. Ve ortaya sinema.py adresinden indirebileceğiniz basit bir sinema sever API'si çıktı.

    Örneklerle API'nin nasıl kullanıldığına bakalım.
    Vizyondaki filmleri listelemek için aşağıdaki örnekteki gibi vizyondakiFilmler fonksiyonu kullanılıyor.

    >>> import sinema
    >>> filmler=sinema.vizyondakiFilmler()
    >>> len(filmler)
    75
    >>> filmler.keys()
    [u'3922', u'3949', u'3920', u'3711', u'3808', u'3902', u'3835', u'3869', u'3941', u'3634',
    u'3867', u'3800', u'3946', u'3947', u'3916', u'3958', u'3956', u'3926', u'3734', u'2601',
    u'3910', u'3305', u'3911', u'3934', u'3948', u'2812', u'3964', u'3793', u'3845', u'1694',
    u'3855', u'3898', u'3918', u'3862', u'3978', u'3897', u'3805', u'3844', u'3780', u'3915',
    u'3873', u'3816', u'3847', u'3809', u'3833', u'3953', u'3952', u'3872', u'3950', u'3957',
    u'3930', u'3919', u'3945', u'3870', u'3936', u'3876', u'3932', u'3959', u'3885', u'3887',
    u'3837', u'3931', u'3883', u'3882', u'3612', u'3888', u'3871', u'3758', u'1683', u'3143',
    u'3962', u'3963', u'3960', u'3961', u'3825']
    >>> filmler['1694']
    u'Indiana Jones ve Kristal Kafatas\u0131 Krall\u0131'

    Seçilen filmin gösterimde olduğuşehirlerin listesi için filminGosterildigiSehirler fonksiyonu çağırılır.

    >>> sehirler=sinema.filminGosterildigiSehirler('1694')
    >>> sehirler
    {u'216': u'\u0130stanbul Anadolu', u'318': u'K\u0131r\u0131kkale', u'212': u'\u0130stanbul
    Avrupa', u'312': u'Ankara', u'452': u'Ordu', u'242': u'Antalya', u'454': u'Giresun', u'332':
    u'Konya', u'392': u'K\u0131br\u0131s', u'258': u'Denizli', u'252': u'Mu\u011fla', u'236':
    u'Manisa', u'256': u'Ayd\u0131n', u'232': u'\u0130zmir', u'248': u'Burdur', u'322': u'Adana',
    u'288': u'K\u0131rklareli', u'346': u'Sivas', u'326': u'Hatay', u'342': u'Gaziantep', u'422':
    u'Malatya', u'362': u'Samsun', u'284': u'Edirne', u'286': u'\xc7anakkale', u'324': u'Mersin',
    u'442': u'Erzurum', u'462': u'Trabzon', u'262': u'\u0130zmit', u'246': u'Isparta', u'266':
    u'Bal\u0131kesir', u'386': u'K\u0131r\u015fehir', u'264': u'Adapazar\u0131', u'226': u'Yalova',
    u'224': u'Bursa', u'222': u'Eski\u015fehir', u'282': u'Tekirda\u011f', u'272': u'Afyon', u'352':
    u'Kayseri', u'412': u'Diyarbak\u0131r', u'372': u'Zonguldak', u'374': u'Bolu'}
    >>> sehirler['212']
    u'\u0130stanbul Avrupa'

    Seçilen filmin şehirde hangi salonlarda gösterildiğini bulmak için sehirdekiSalonlar fonksiyonu kullanılıyor.

    >>> salonlar = sinema.sehirdekiSalonlar('1694','212')
    >>> salonlar
    [(u'1120', u'Adapazar\u0131 Cinebonus (Ada)', [u'11:00', u'12:15', u'13:30', u'15:00', u'16:15',
    u'17:45', u'19:00', u'20:30', u'21:45', u'23:15']), (u'1000', u'Akatlar Finansbank AFM
    Mayadrom', [u'11:15', u'13:45', u'16:15', u'18:45', u'21:15']), (u'1081', u'Bak\u0131rk\xf6y
    Cinebonus (Capacity)', [u'11:00', u'11:00', u'12:00', u'13:30', u'13:45', u'16:15', u'16:30',
    u'19:00', u'19:15', u'21:45', u'22:00', u'24:30', u'(Cuma, Cmts 24:45']), (u'1118',
    u'Beylikd\xfcz\xfc Cine Marka', [u'11:00', u'12:15', u'13:30', u'14:45', u'16:00', u'17:15',
    u'18:30', u'19:45', u'21:00', u'22:15']), (u'1082', u'Beylikd\xfcz\xfc Fox City', [u'11:30',
    u'14:00', u'16:30', u'19:00', u'21:30']), (u'1117', u'Esentepe Cinebonus (Astoria)', [u'11:00',
    u'12:15', u'13:30', u'14:45', u'16:15', u'17:30', u'19:00', u'20:15', u'21:45', u'(Cuma, Cmts
    23:0............

    >>> salonlar[11]
    (u'1067', u'\u0130stinye AFM Park', [u'10:50', u'11:30', u'12:25', u'13:55', u'14:15', u'15:30',
    u'17:00', u'17:15', u'18:30', u'19:00', u'20:00', u'21:30', u'21:50'])
    >>> salonlar[11][2]
    [u'10:50', u'11:30', u'12:25', u'13:55', u'14:15', u'15:30', u'17:00', u'17:15', u'18:30',
    u'19:00', u'20:00', u'21:30', u'21:50']

    Ve son olarak seçilen salonda gösterilen filmleri bulmak için salondakiFilmler fonksiyonu kullanılıyor.

    >>> filmler=sinema.salondakiFilmler('10')
    >>> filmler
    [(u'3945', u'88 Dakika', [u'11:50', u'14:20', u'16:50', u'19:30', u'21:50']), (u'1694', u'Indiana
    Jones ve Kristal Kafatas\u0131 Krall\u0131\u011f\u0131', [u'10:50', u'11:10', u'13:30', u'13:50',
    u'16:20', u'16:30', u'19:00', u'19:10', u'21:30', u'21:45']), (u'3964', u'O... \xc7ocuklar
    \u0131', [u'11:20', u'14:00', u'16:45', u'19:15', u'21:55']), (u'3949', u'\xd6l\xfcmc\xfcl
    Oyunlar', [u'11:30', u'14:10', u'16:40', u'19:20', u'22:00']), (u'3800', u'Sex and the City',
    [u'10:40', u'12:15', u'13:50', u'15:30', u'17:10', u'18:50', u'21:30', u'22:10', u'(Cuma, Cmts
    23:50'])]
    >>> filmler[0][1]
    u'88 Dakika'


    Söylemeden geçemeyeceğim python ile yazılan bu API dokumantasyonu ile beraber 100 satırı geçmiyor. Beyazperde sitesi gününbirinde html arayüzünde bir değişiklik yaparsa bu API'nin de güncellenmesi gerekiyor.

  •