Форма POST для Python с использованием urllib2 (также вопрос о сохранении / использовании файлов cookie) - PullRequest
17 голосов
/ 02 июня 2010

Я пытаюсь написать функцию для публикации данных формы и сохранения возвращенной информации о файлах cookie в файле, чтобы при следующем посещении страницы информация о файлах cookie отправлялась на сервер (т.е. нормальное поведение браузера).

Я написал это относительно легко на C ++, используя curlib, но потратил почти целый день, пытаясь написать это на Python, используя 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() 

Когда я пытаюсь войти в систему, я передаю правильное имя пользователя и pwd ,. все же вход в систему не удается, и данные cookie не сохраняются.

Мои два вопроса:

  • Кто-нибудь может увидеть, что не так с функцией login (), и как я могу это исправить?
  • как я могу изменить функцию get_page (), чтобы использовать любую информацию о cookie, которую я сохранил?

Ответы [ 3 ]

30 голосов
/ 02 июня 2010

С кодом, который вы опубликовали, довольно много проблем. Как правило, вы захотите создать пользовательский открыватель, который может обрабатывать перенаправления, https и т. Д., Иначе вы столкнетесь с проблемами. Что касается самих файлов cookie, вам необходимо вызвать методы load и save для вашего cookiejar и использовать один из подклассов, например MozillaCookieJar или LWPCookieJar.

.

Вот класс, который я написал для входа в Facebook, когда играл в глупые веб-игры. Я просто изменил его, чтобы использовать cookiejar на основе файлов, а не в памяти.

import cookielib
import os
import urllib
import urllib2

# set these to whatever your fb account is
fb_username = "your@facebook.login"
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, в котором находятся ваши куки. На практике вы, вероятно, захотите изменить его, чтобы проверить, есть ли у вас активный файл cookie, и использовать его, а затем снова войти в систему, если доступ запрещен.

2 голосов
/ 06 декабря 2010

Если вам трудно заставить ваши запросы POST работать (как у меня было с формой входа в систему), определенно стоит быстро установить расширение заголовков Live HTTP для Firefox (http://livehttpheaders.mozdev.org/index.html). Это небольшое расширение может, среди прочего вещи, показать вам точные данные POST, которые отправляются при входе в систему вручную.

В моем случае я часами бился головой о стену, потому что сайт настаивал на дополнительном поле с 'action = login' (doh!).

1 голос
/ 24 августа 2012

Пожалуйста, используйте ignore_discard и ignore_expires при сохранении куки, в моем случае он сохранил ОК.

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