facebewk ['feɪsbuk] is a Python wrapper for the facebook Graph API. A while ago, there was quite a commotion online when official repositories for Python and C# API clients were removed by facebook without any forewarning. These clients had become neglected and were no longer accurate, and so facebook wanted to stop supporting them. Since then, the hole left in the Python ecosystem doesn't seem to have been plugged - most people seem to be using straight HTTP requests to the API.

I decided to write facebewk - a simple little API client that's designed to minimise HTTP requests and encapsulate data nicely.

Facebook have put an awful lot of work into making the Graph API as friendly and robust as it is. Apps developers have already spent their time familiarising themselves with it. So why mess with a good thing? Instead of coming up with a new API for developers to learn, facebewk provides a developer-friendly Node object, representative of exactly what information facebook returns when queried about a certain node on the social graph.

Some important points:

These Node objects are generated recursively. Therefore, a Node object representing my own facebook profile will, in turn, contain subnodes representing my hometown of Dublin and my current location, for example.

Information contained in subnodes may not be complete, but this is invisible to the developer: facebewk takes care of grabbing a subnode's full information if a key is accessed which doesn't currently exist in the subnode.

This is all very difficult to describe in prose, so instead, here is an example session from a Python interactive shell to show you exactly what facebewk is about:

>>> from facebewk import Client >>> c = Client ( 'FACEBOOK_ACCESS_TOKEN' ) >>> me = c . get ( 'me' ) >>> type ( me ) >>> me [ 'name' ] u 'Aengus Walton' >>> type ( me [ 'hometown' ]) >>> me [ 'hometown' ] { '__fetched__' : False , u 'id' : u '110769XXXXXXXXX' , u 'name' : u 'Dublin, Ireland' } >>> me [ 'hometown' ][ 'checkins' ] 16734 >>> me [ 'hometown' ] { u 'category' : u 'City' , u 'likes' : 146053 , u 'description' : u '<p><b>Dublin</b> is the capital and most populous city of ........' , '__fetched__' : True , u 'talking_about_count' : 115999 , u 'name' : u 'Dublin, Ireland' , u 'link' : u 'http://www.facebook.com/pages/Dublin-Ireland/110769888951990' , u 'location' : { u 'latitude' : 53.344037395687 , u 'longitude' : - 6.2632156999178 }, u 'is_community_page' : True , u 'checkins' : 16734 , u 'id' : u '110769888951990' , u 'is_published' : True } >>> >>> newsfeed = c . get ( '/me/home' ) >>> type ( newsfeed ) >>> type ( newsfeed [ 'data' ]) >>> >>> me [ 'significant_other' ][ 'hometown' ][ 'checkins' ] 222 >>> >>> status_update = c . post ( me , { 'message' : 'writing my blog post innit' , ... 'privacy' : { 'value' : 'CUSTOM' , 'networks' : 1 , 'friends' : 'NO_FRIENDS' }}) >>> status_update { '__fetched__' : False , u 'id' : u '37300126_632748066014' } >>> status_update [ 'message' ] u 'writing my blog post innit' >>> my_comment = c . post ( status_update , { 'message' : 'blablabla' }) >>> c . like ( my_comment ) True

The last few lines result in the following appearing on my profile:

So, the Node is essentially a subclass of dict, with some magic thrown in in order to grab missing information on the fly. The only HTTP GET requests to facebook occur on lines 3, 12, 19, 27 and 34. Information retrieved from the graph is stored, overwriting the previously scant Node objects with more detailed ones. Posting to the graph is possible with the same API as is defined here. facebewk also automatically figures out whether the target node to be posted to is a user profile or page, in which case it posts a normal wall post, or a pre-existing post of some kind, in which case it posts a comment.

Authentication is unsupported and, at the moment, outside the scope of this project. As you can see above, I used an API key generated by the Graph API Explorer, which is probably the best way to get started with facebewk if you want to try it out.

There's a lot more that can be done here, for example, making the privacy controls above configurable with keyword arguments, adding wrappers for grabbing friendlists and newsfeeds, and so on, but I'm publishing this now to gauge interest and see if it's something which would really benefit developers in real-world scenarios.

If you have any thoughts on this project, if there are improvements or additional functionality you'd love to see, then please get in touch via email or the github issue tracker.

Source code available on github