2010-06-02 3 views
17

다음에 페이지를 방문 할 때 쿠키 정보가 반환되도록 양식 데이터를 게시하고 반환 된 쿠키 정보를 저장하는 함수를 작성하려고합니다. 서버에 전송됩니다 (예 : 일반적인 브라우저 동작).urllib2를 사용하는 Python 양식 POST (쿠키 저장/사용에 관한 질문)

필자는 curlib를 사용하여 C++에서 이것을 비교적 쉽게 작성했지만, urllib2를 사용하여 파이썬으로 작성하려고 거의 하루 종일을 보냈다. 내가 로그인 할 때

import urllib, urllib2 
import logging 

# the path and filename to save your cookies in 
COOKIEFILE = 'cookies.lwp' 

cj = None 
ClientCookie = None 
cookielib = None 


logger = logging.getLogger(__name__) 

# Let's see if cookielib is available 
try: 
    import cookielib 
except ImportError: 
    logger.debug('importing cookielib failed. Trying ClientCookie') 
    try: 
     import ClientCookie 
    except ImportError: 
     logger.debug('ClientCookie isn\'t available either') 
     urlopen = urllib2.urlopen 
     Request = urllib2.Request 
    else: 
     logger.debug('imported ClientCookie succesfully') 
     urlopen = ClientCookie.urlopen 
     Request = ClientCookie.Request 
     cj = ClientCookie.LWPCookieJar() 

else: 
    logger.debug('Successfully imported cookielib') 
    urlopen = urllib2.urlopen 
    Request = urllib2.Request 

    # This is a subclass of FileCookieJar 
    # that has useful load and save methods 
    cj = cookielib.LWPCookieJar() 


login_params = {'name': 'anon', 'password': 'pass' } 

def login(theurl, login_params): 
    init_cookies(); 

    data = urllib.urlencode(login_params) 
    txheaders = {'User-agent' : 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'} 

    try: 
    # create a request object 
    req = Request(theurl, data, txheaders) 

    # and open it to return a handle on the url 
    handle = urlopen(req) 

    except IOError, e: 
    log.debug('Failed to open "%s".' % theurl) 
    if hasattr(e, 'code'): 
     log.debug('Failed with error code - %s.' % e.code) 
    elif hasattr(e, 'reason'): 
     log.debug("The error object has the following 'reason' attribute :"+e.reason) 
     sys.exit() 

    else: 

    if cj is None: 
     log.debug('We don\'t have a cookie library available - sorry.') 
    else: 
     print 'These are the cookies we have received so far :' 
     for index, cookie in enumerate(cj): 
     print index, ' : ', cookie 

     # save the cookies again 
     cj.save(COOKIEFILE) 

     #return the data 
     return handle.read() 



# FIXME: I need to fix this so that it takes into account any cookie data we may have stored 
    def get_page(*args, **query): 
    if len(args) != 1: 
     raise ValueError(
      "post_page() takes exactly 1 argument (%d given)" % len(args) 
     ) 
    url = args[0] 
    query = urllib.urlencode(list(query.iteritems())) 
    if not url.endswith('/') and query: 
     url += '/' 
    if query: 
     url += "?" + query 
    resource = urllib.urlopen(url) 
    logger.debug('GET url "%s" => "%s", code %d' % (url, 
                resource.url, 
                resource.code)) 
    return resource.read() 

, 내가 올바른 사용자 이름과 비밀번호가 ,.을 통과 :

이것은 내가 지금까지 무엇을 가지고 로그인이 실패하고 쿠키 데이터가 저장되지 않습니다.

내 두 가지 질문은 다음과 같습니다

  • 는 사람이 무슨 잘못 로그인() 함수를 볼 수 있습니다, 어떻게 고칠 수 있을까요?
  • 저장 한 쿠키 정보를 사용하기 위해 get_page() 함수를 어떻게 수정할 수 있습니까?

답변

29

게시 한 코드에 몇 가지 문제가 있습니다. 일반적으로 리디렉션, https 등을 처리 할 수있는 사용자 정의 오프너를 만드는 것이 좋습니다. 그렇지 않으면 문제가 발생합니다. 쿠키 자체까지는 cookiejar에로드 및 저장 메서드를 호출하고 MozillaCookieJar 또는 LWPCookieJar과 같은 하위 클래스 중 하나를 사용해야합니다.

다음은 내가 바보 같은 웹 게임을 할 때 페이스 북에 로그인하기 위해 작성한 수업입니다. 방금 메모리가 아닌 파일 기반 쿠키를 사용하도록 수정했습니다.

import cookielib 
import os 
import urllib 
import urllib2 

# set these to whatever your fb account is 
fb_username = "[email protected]" 
fb_password = "secretpassword" 

cookie_filename = "facebook.cookies" 

class WebGamePlayer(object): 

    def __init__(self, login, password): 
     """ Start up... """ 
     self.login = login 
     self.password = password 

     self.cj = cookielib.MozillaCookieJar(cookie_filename) 
     if os.access(cookie_filename, os.F_OK): 
      self.cj.load() 
     self.opener = urllib2.build_opener(
      urllib2.HTTPRedirectHandler(), 
      urllib2.HTTPHandler(debuglevel=0), 
      urllib2.HTTPSHandler(debuglevel=0), 
      urllib2.HTTPCookieProcessor(self.cj) 
     ) 
     self.opener.addheaders = [ 
      ('User-agent', ('Mozilla/4.0 (compatible; MSIE 6.0; ' 
          'Windows NT 5.2; .NET CLR 1.1.4322)')) 
     ] 

     # need this twice - once to set cookies, once to log in... 
     self.loginToFacebook() 
     self.loginToFacebook() 

     self.cj.save() 

    def loginToFacebook(self): 
     """ 
     Handle login. This should populate our cookie jar. 
     """ 
     login_data = urllib.urlencode({ 
      'email' : self.login, 
      'pass' : self.password, 
     }) 
     response = self.opener.open("https://login.facebook.com/login.php", login_data) 
     return ''.join(response.readlines()) 

test = WebGamePlayer(fb_username, fb_password) 

사용자 이름과 암호를 설정 한 후, 당신은 당신의 쿠키, 파일, facebook.cookies을 볼 수 있습니다. 실제로는 쿠키를 수정하여 사용중인 쿠키가 있는지 확인한 다음 액세스가 거부 된 경우 다시 로그인하는 것이 좋습니다.

+0

+1 코드 스 니펫의 경우. 코드가 너무 깔끔하고 깨끗합니다. (글쎄 파이썬 스타가되는 법을 배우기 시작했습니다.) 나는 당신의 게시물을 다시 읽었습니다. 분명하지 않은 두 가지가 있습니다. 1). 왜 loginToFacebook()을 두 번 호출해야하는지 이해가 안됩니다. loginToFacebook() 메소드 ID가 호출 될 때마다 쿠키가 설정되는 것처럼 보입니다. 분명히 해줄 수 있니?. 2). ACTIVE 쿠키가 있는지 확인하는 방법에 대한 지침을 줄 수 있습니까? – morpheous

+1

쿠키 기반 로그인을 사용하면 서버가 먼저 쿠키를 할당하고 * 다음 * 로그인합니다. 로그인 중 하나를 제거하면 로그인하지 않은 것입니다. FB가 사용자의 응답을 확인했는지 확인했습니다 쿠키가 없으며 로그인 페이지로 다시 리디렉션되었습니다.더 명확한 방법은 첫 번째 호출을 FB 프론트 페이지를 'def getFBCookie (self) : self.opener.open ('https://www.facebook.com/ ')' 과 같이 바꾸는 것입니다. 똑같은 일을하십시오. 그리고 예, 그것은 꽤 산뜻한 코드입니다. 그건 좀 더 시간이 좀 걸리지 만 나중에 읽거나 재사용 할 필요가있을 때 돈을 지불합니다 :) –

2

(로그인 양식을 가지고 있었던 것처럼) POST 요청을 수행하는 데 어려움을 겪고 있다면, Firefox에 실시간 HTTP 헤더 확장을 신속하게 설치해야합니다 (http://livehttpheaders.mozdev.org). /index.html). 이 작은 확장은 수동으로 로그인 할 때 보내지는 정확한 POST 데이터를 보여줍니다.

내 경우에는 사이트가 추가 필드를 주장했기 때문에 몇 시간 동안 벽에 머리를 두드렸다. 'action = login'(doh!)을 사용하십시오.

1

쿠키를 저장하는 동안 ignore_discardignore_expires을 사용하십시오. 내 경우에는 OK를 저장하십시오.

self.cj.save(cookie_file, ignore_discard=True, ignore_expires=True)