페이스북 억세스 토큰을 얻는 것은 트위터에 비해 조금 귀찮습니다.
브라우저를 사용해야 하기 때문입니다~
 

페이스북 억세스 토큰을 얻어내는 코드에 파이썬 브라우저 모듈인 mechanize 를 붙여보았습니다



# vi: set sw=4 sts=4 expandtab:
import os
import os.path
import json
import urllib2
import urllib
import urlparse
import BaseHTTPServer
import webbrowser
import mechanize
CODE_BEGIN = 'code='
CODE_END = '"'

APP_ID = '페이스북_앱_아이디'
APP_SECRET = '페이스북_앱_시크릿'
ENDPOINT = 'graph.facebook.com'
REDIRECT_URI = '콜백처리_URL'
ACCESS_TOKEN = None
LOCAL_FILE = '.fb_access_token'

STATUS_TEMPLATE = u"{name}\033[0m: {message}"

def get_url(path, args=None):
args = args or {}
if ACCESS_TOKEN:
args['access_token'] = ACCESS_TOKEN
if 'access_token' in args or 'client_secret' in args:
endpoint = "https://"+ENDPOINT
else:
endpoint = "http://"+ENDPOINT
return endpoint+path+'?'+urllib.urlencode(args)

def get(path, args=None):
return urllib2.urlopen(get_url(path, args=args)).read()


class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):

def do_GET(self):
global ACCESS_TOKEN
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()

code = urlparse.parse_qs(urlparse.urlparse(self.path).query).get('code')
code = code[0] if code else None
if code is None:
self.wfile.write("Sorry, authentication failed.")
sys.exit(1)
response = get('/oauth/access_token', {'client_id':APP_ID,
'redirect_uri':REDIRECT_URI,
'client_secret':APP_SECRET,
'code':code})
ACCESS_TOKEN = urlparse.parse_qs(response)['access_token'][0]
open(LOCAL_FILE,'w').write(ACCESS_TOKEN)
self.wfile.write("You have successfully logged in to facebook. "
"You can close this window now.")

def print_status(item, color=u'\033[1;35m'):
print color+STATUS_TEMPLATE.format(name=item['from']['name'],
message=item['message'].strip())


def main(email, password):
url = get_url('/oauth/authorize',
{'client_id':APP_ID,
'redirect_uri':REDIRECT_URI,
'scope':'read_stream'})

browser = mechanize.Browser()
browser.set_handle_refresh(False)
browser.set_handle_robots(False)
cookies = mechanize.CookieJar()
browser.set_cookiejar(cookies)
response = browser.open(url)
open("response.html", "wb").write(response.get_data())
browser.addheaders = [('User-agent', 'Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.517.41 Safari/534.7')]


try:
browser.select_form(predicate=lambda f:"login.php" in f.action and f.method.lower() == "post")
except mechanize.FormNotFoundError:
print "WRONG_LOGIN_PAGE"
return -1

browser.form["email"] = email
browser.form["pass"] = password

response = browser.submit()
responseData = response.read()
relocationPos = responseData.find("window.location.replace")
open("response2.html", "wb").write(responseData)

if relocationPos < 0:
try:
browser.select_form(predicate=lambda f:f.action.endswith("uiserver.php") and f.method.lower() == "post")
except mechanize.FormNotFoundError:
print "RETRY_LOGIN_LATER"
return -2

response = browser.submit(name="grant_clicked")
responseData = response.read()
relocationPos = responseData.find("window.location.replace")
open("response3.html", "wb").write(responseData)


if relocationPos > 0:
tagBeginPos = responseData.find(CODE_BEGIN, relocationPos)
if tagBeginPos > 0:
tagEndPos = responseData.find(CODE_END, tagBeginPos)

code = responseData[tagBeginPos+len(CODE_BEGIN):tagEndPos].decode("unicode-escape")

response = get('/oauth/access_token', {'client_id':APP_ID,
'redirect_uri':REDIRECT_URI,
'client_secret':APP_SECRET,
'code':code})
ACCESS_TOKEN = urlparse.parse_qs(response)['access_token'][0]
open(LOCAL_FILE,'w').write(ACCESS_TOKEN)
print "LOGIN_SUCCESS"
return 0
else:
print "UNKNOWN_REDIRECT"
return -4
else:
print "INVALID_CODE"
return -3

if __name__ == '__main__':
import sys
if len(sys.argv) >= 3:
sys.exit(main(sys.argv[1], sys.argv[2]))
else:
print "USAGE:"
print "\t%s [email] [password]" % os.path.split(sys.argv[0])[1]


UNKNOWN_REDIRECT 는 뭔가 페이스 북이 특수 기능 - 이메일 친구 스캔 하기 - 을 처리하기 위해

로그인 절차와는 상관없는 페이지를 보여주는 경우가 있습니다. 이 때는 진짜 웹 브라우저를 띄워서 처리해주는 수밖에 없을 듯 합니다.

끝 ~(-_-)~

이올린에 북마크하기(0) 이올린에 추천하기(0)
2011/03/31 17:26 2011/03/31 17:26

파이썬에서 트위터 날리기 tweepy

Posted at 2011/03/31 17:11// Posted in python/py-sns

tweepy 를 사용해서 트위터 OAuth 로그인을 한 다음 타임 라인을 보는 예제입니다~


USERNAME = "아이디"
PASSWORD = "비밀번호"

import tweepy

import re
roToken = re.compile("<\w+|>|/>|</\w+>|\w+|=|\"[^\"]+\"")

def GetTagAttrd(tokens, beginTag, endTag, curIndex, endIndex):
itokens = []
try:
curIndex = tokens.index(beginTag, curIndex)
except ValueError:
return curIndex, None

if curIndex >= endIndex:
return endIndex, None

while tokens[curIndex] != endTag:
itokens.append(tokens[curIndex])
curIndex += 1

return curIndex, dict(zip(itokens[1::3], [val[1:-1] for val in itokens[3::3]]))

from urllib import *
from urllib2 import *

def Main():
CONSUMER_KEY = '트위터_앱_키'
CONSUMER_SECRET = '트위터_앱_시크릿'

auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
aurl = auth.get_authorization_url()
data = urlopen(aurl).read()
lines = data.splitlines()
tokens = []
for line in lines:
tokens += roToken.findall(line)

curIndex, formd = GetTagAttrd(tokens, "<form", ">", 0, len(tokens))
endIndex = tokens.index("</form>", curIndex)
actionURL = formd["action"]

valued = {}
while True:
curIndex, inputd = GetTagAttrd(tokens, "<input", "/>", curIndex, endIndex)
if inputd:
if inputd["type"] == "hidden":
valued[inputd["name"]] = inputd["value"]
elif inputd["type"] == "text":
valued[inputd["name"]] = USERNAME
elif inputd["type"] == "password":
valued[inputd["name"]] = PASSWORD
elif inputd["type"] == "submit":
valued["submit"] = inputd["value"]
else:
print inputd
else:
break

params = urlencode(valued)
req = Request(actionURL, params)
res = urlopen(req)
data = res.read()
lines = data.splitlines()
tokens = []
for index, line in enumerate(lines):
if "div" in line and "oauth_pin" in line:
index += 1
break

verifier = lines[index].strip()
auth.get_access_token(verifier)

api = tweepy.API(auth)

if 0:
api.update_status(u"~tweepy test")
else:
for s in api.user_timeline():
print s.text.encode("utf8")

Main()
이올린에 북마크하기(0) 이올린에 추천하기(0)
2011/03/31 17:11 2011/03/31 17:11