requests - Formulario de Python POST usando urllib2(también pregunta sobre guardar/usar cookies)
urllib2 readline (3)
Hay bastantes problemas con el código que has publicado. Por lo general, querrá crear un abridor personalizado que pueda manejar redirecciones, https, etc. De lo contrario, tendrá problemas. En cuanto a las cookies, debe llamar a los métodos de carga y guardado en su cookiejar
, y usar una de las subclases, como MozillaCookieJar
o LWPCookieJar
.
Aquí hay una clase que escribí para iniciar sesión en Facebook, cuando jugaba a los juegos de Internet. Acabo de modificarlo para usar un cookiejar basado en archivos, en lugar de uno en memoria.
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)
Después de configurar su nombre de usuario y contraseña, debería ver un archivo, facebook.cookies
, con sus cookies en él. En la práctica, probablemente querrá modificarlo para verificar si tiene una cookie activa y usarla, y luego volver a iniciar sesión si se le niega el acceso.
Estoy intentando escribir una función para publicar los datos del formulario y guardar la información de la cookie devuelta en un archivo para que la próxima vez que se visite la página, la información de la cookie se envíe al servidor (es decir, el comportamiento normal del navegador).
Escribí esto con relativa facilidad en C ++ usando curlib, pero pasé casi un día entero tratando de escribir esto en Python, usando urllib2, y aún no tengo éxito.
Esto es lo que tengo hasta ahora:
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()
Cuando intento iniciar sesión, paso el nombre de usuario y pwd correctos. sin embargo, el inicio de sesión falla y no se guardan datos de cookies.
Mis dos preguntas son:
- ¿Alguien puede ver qué está mal con la función de inicio de sesión () y cómo puedo solucionarlo?
- ¿Cómo puedo modificar la función get_page () para hacer uso de cualquier información de cookies que haya guardado?
Por favor, use ignore_discard
y ignore_expires
mientras guarda una cookie, en mi caso, se guardó OK.
self.cj.save(cookie_file, ignore_discard=True, ignore_expires=True)
Si está teniendo dificultades para hacer que sus solicitudes POST funcionen (como tuve con un formulario de inicio de sesión), definitivamente vale la pena instalar rápidamente la extensión de encabezados HTTP en vivo para Firefox (http://livehttpheaders.mozdev.org/index.html ). Esta pequeña extensión puede, entre otras cosas, mostrarle los datos POST exactos que se envían cuando inicia sesión manualmente.
En mi caso, me había golpeado la cabeza contra la pared durante horas porque el sitio insistía en un campo adicional con "acción = inicio de sesión" (¡doh!).