potass' blog

ポタシウムのことが書いてないブログ。

Python 3.2 への Facebook-sdk のインストール

はじめに

ある Facebook アカウントを RSS リーダ*1で読みたいなと思ったのでその方法をググってみた。

Facebook捨て垢(というかそういった概念があるのかも不明)すら作ってないのでよくわからん。ただこの件に関しては該当アカウントの Facebook ID とやらをゲットして

https://www.facebook.com/feeds/page.php?format=rss20&id=[Facebook ID]

RSS リーダに読ませればいい。Facebook ID の取得方法は

https://graph.facebook.com/[Facebook Username]

にアクセスすれば簡単に見つけられる。

これ自体は大したこと無いが「PythonFacebook ID 拾ってこれるんじゃね?」と思ってしまったのが運の尽き…。

facebook-sdk のインストール

条件

OS : Windows 8.1 (64 bit)
Python : 3.2.5
facebook-sdk : 0.4.0 (pip でインストール)

インストール

1. まずは pip でインストールする。requests は GitHub の install.rst で required だったので インストールした。*2

$ pip install requests
$ pip install facebook-sdk

2. 試しに import してみたら次のような Syntax Error が出る。

>>> import facebook
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python32\lib\site-packages\facebook.py", line 222
    except urllib2.HTTPError, e:
                            ^
SyntaxError: invalid syntax

とりあえず該当箇所の 222 行付近を調べてみると、

try:
    data = urllib2.urlopen(req).read()
#For Python 3 use this:
#except urllib2.HTTPError as e:
except urllib2.HTTPError, e:
    data = e.read()  # Facebook sends OAuth errors as 400, and urllib2
                    # throws an exception, we want a GraphAPIError

とコメントされてた。ふむふむ、facebook.py は Python 2.x 向けなのね。
他にも該当箇所あるし、そもそも urllib2 は Python 3 で変わってる*3し、ちまちま治すのは面倒だな。
3. てなわけで 2to3 で変換する。

$ python c:\Python32\Tools\Scripts\2to3.py -w --no-diffs c:\Python32\lib\site-packages\facebook.py

これで 2to3.py による変換終了。これで import 時のエラーは消える。
4. import はうまくいくものの、まだバグはある。

maintype バグ

facebook-sdk で読み込もうとすると 308 行目をさして

AttributeError: 'HTTPMessage' object has no attribute 'maintype'

となっている。fileInfo は HTTPMessage object だが maintype を取ってくるには get_content_maintype メゾットで拾ってくる必要がある。(参考:
Issue 4773: HTTPMessage not documented and has inconsistent API across Py2/Py3 - Python tracker
よって 308-310 行目を次のように変える。(旧ソースはコメントアウトした。)

if fileInfo.get_content_maintype() == 'text':#fileInfo.maintype == 'text':
    response = _parse_json(file.read())
elif fileInfo.get_content_maintype() == 'image':#fileInfo.maintype == 'image':
_parse_json (実態は json.loads) の decode

_parse_json なる謎コマンドは 56 行で

_parse_json = json.loads

と定義されている。はっきり言って見にくい(しわざわざ定義する意味を感じない)のでこの定義をコメントアウトする。その後に _parse_jsonjson.loads にエディタで一斉置換しておく。
さて、json.loads() の仕様は 19.2. json — JSON エンコーダおよびデコーダ — Python 3.4.1 ドキュメント にある通り。
別に問題ないはずだが facebook-sdk で読み込もうとすると次のエラーが出る。

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python32\lib\site-packages\facebook.py", line 100, in get_object
    return self.request(id, args)
  File "C:\Python32\lib\site-packages\facebook.py", line 309, in request
    response = json.loads(file.read())
  File "C:\Python32\lib\json\__init__.py", line 319, in loads
    return _default_decoder.decode(s)
  File "C:\Python32\lib\json\decoder.py", line 353, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
TypeError: can't use a string pattern on a bytes-like object

よくわからんが json.loads() の default decoder がうまく機能してないっぽいので decode を指定してしまえばいいと思う。
日本語を含むものも utf-8 ならきれいに読み込めたので
309 行目を

response = json.loads(file.read().decode('utf-8'))#response = json.loads(file.read())

とする。他にも json.loads() は使われているが今のとこエラーを吐かないのでそのままにしておく。

facebook-sdk による facebook ID の取得

さて、やっと facebook-sdk を使える。
インタラクティブシェルから

>>> import facebook
>>> gap = facebook.GraphAPI()
>>> gob = gap.get_object("Google")
>>> print(gob)

とすると Googlefacebook アカウントの情報が得られる。
gob は辞書型なので key を指定すればそれだけを表示させられる。
例えば、

>>> gob.keys() # key の確認
>>> print("id : ", gob['id'], "\nusername : ", gob['username'], "\n")

とすれば id と username のみを表示させられる。

参考文献みたいなもの

Facebook Python Library
http://facebook-python-library.docs-library.appspot.com/facebook-python/facebook-python-library.html

Facebook-SDK のインストールから使い方まで。使い方はひとまずこれを見ようかな。
インストールはあまり参考にならなかった。

Python for Facebook
http://www.pythonforfacebook.com/

Developer のサイト。GitHub ではα版が公開されている。
これは pip じゃなくて GitHub からインストールすべきだったか?
みたところ、urllib2 のバグは消えている。maintype は別の方法で回避している。
ただ、json.loads のやつは変な定義式を消したくらいで decode 指定はない。
これで上手くいくのか?それとも俺の環境が悪いのか?
doc/install.rst を見ると Python 2.6/2.7/3.3 推奨とな。これが原因…なのか…?

Lookup any Username on FACEBOOK
http://www.go4expert.com/articles/lookup-username-facebook-t27093/

facebook-sdk を使わないで

http://graph.facebook.com/[facebook username]

から情報を取得するスクリプト。まあ一番シンプルだな。

*1:私は Google ReaderFeedly と使っている人間です。

*2:なお、実際は全部終わったあとで気づいてインストールした。requests がなくても問題なく動いたが他の機能で必要なのかな?

*3:参考:20.6. urllib2 — URL を開くための拡張可能なライブラリ — Python 2.7ja1 documentation