2010-06-02 7 views
17

Próbuję napisać funkcję, aby wysłać dane formularzy i zapisać zwrócone informacje cookie w pliku, aby przy następnym odwiedzeniu strony informacje cookie były wysyłane na serwer (np. normalne zachowanie przeglądarki).Formularz Python POST za pomocą urllib2 (również pytanie dotyczące zapisywania/używania plików cookie)

Napisałem to stosunkowo łatwo w C++ za pomocą curlib, ale spędziłem prawie cały dzień próbując napisać to w Pythonie, używając urllib2 - i wciąż bez powodzenia.

To, co mam tak daleko:

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() 

Gdy próbuję się zalogować, mijam prawidłową nazwę użytkownika i pwd ,. jednak logowanie nie powiedzie się i nie zapisano żadnych danych cookie.

Moje dwa pytania:

  • ktoś może zobaczyć co jest nie tak z logowania function(), i jak mogę to naprawić?
  • Jak mogę zmodyfikować funkcję get_page(), aby wykorzystać wszelkie zapisane przeze mnie informacje o plikach cookie?

Odpowiedz

29

Występuje sporo problemów z opublikowanym przez Ciebie kodem. Zazwyczaj chcesz zbudować niestandardowego otwierającego, który może obsługiwać przekierowania, https, itp. W przeciwnym razie będziesz mieć kłopoty. Jeśli chodzi o same pliki cookie, musisz wywołać metody ładowania i zapisywania na swoim cookiejar i użyć jednej z podklas, takich jak MozillaCookieJar lub LWPCookieJar.

Oto klasa, którą napisałem, aby zalogować się na Facebooku, kiedy grałem w głupie gry internetowe. Po prostu zmodyfikowałem go tak, aby używał pliku cookiejar, a nie w pamięci.

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) 

Po skonfigurowaniu nazwy użytkownika i hasła, powinieneś zobaczyć plik facebook.cookies z plików cookie w nim. W praktyce prawdopodobnie będziesz chciał go zmodyfikować, aby sprawdzić, czy masz aktywny plik cookie i użyć go, a następnie zaloguj się ponownie, jeśli odmówiono dostępu.

+0

+1 za fragment kodu. Twój kod jest o wiele lepszy i czystszy niż mój (no cóż, dopiero zaczynam się uczyć, jak być Pythonistą!); Czytałem ponownie przeczytałem twój post - są dwie rzeczy, które nie są dla mnie jasne. 1). Nie rozumiem, dlaczego musisz dwukrotnie wywoływać loginToFacebook(). Wygląda na to, że ciasteczko zostanie ustawione za każdym razem, gdy zostanie wywołany identyfikator metody loginToFacebook(). Czy mógłbyś wyjaśnić?. 2). czy możesz podać wskazówki, jak sprawdzić, czy istnieje AKTYWNY plik cookie? – morpheous

+1

Przy logowaniu opartym na plikach cookie serwer najpierw przypisuje Ci plik cookie, * następnie * logujesz się. Jeśli spróbujesz usunąć jedno z loginów, okaże się, że nie jesteś zalogowany - FB sprawdził Twoją odpowiedź, widział że nie masz pliku cookie i przekierował cię z powrotem na stronę logowania.Bardziej wyraźnym sposobem byłoby zastąpienie pierwszego połączenia jednym z nich, aby uzyskać stronę główną FB, takie jak 'def getFBCookie (self): self.opener.open ('https://www.facebook.com/')' , które Zrobić to samo. I tak, to całkiem zgrabny kod. To zajmuje trochę więcej czasu z góry, ale opłaca się, gdy trzeba go później przeczytać lub użyć ponownie :) –

2

Jeśli masz problemy z wysyłaniem żądań POST do pracy (tak jak miałem to z formularzem logowania), zdecydowanie opłaca się szybko zainstalować rozszerzenie nagłówków Live HTTP do Firefoksa (http://livehttpheaders.mozdev.org) /index.html). To małe rozszerzenie może między innymi pokazywać dokładne dane POST wysyłane podczas ręcznego logowania.

W moim przypadku uderzyłem głową o ścianę przez wiele godzin, ponieważ strona nalegała na dodatkowe pole z "action = login" (doh!).

1

Podczas zapisywania pliku cookie należy użyć ignore_discard i ignore_expires, w kopalni zapisano OK.

self.cj.save(cookie_file, ignore_discard=True, ignore_expires=True) 
Powiązane problemy