web-dev-qa-db-fra.com

Python: confusion urllib / urllib2 / httplib

J'essaie de tester la fonctionnalité d'une application Web en scriptant une séquence de connexion en Python, mais j'ai des problèmes.

Voici ce que je dois faire:

  1. Faites un POST avec quelques paramètres et en-têtes.
  2. Suivez une redirection
  3. Récupérez le corps HTML.

Maintenant, je suis relativement nouveau sur python, mais les deux choses que j'ai testées jusqu'à présent n'ont pas fonctionné. J'ai d'abord utilisé httplib, avec putrequest () (en passant les paramètres dans l'URL) et putheader (). Cela ne semblait pas suivre les redirections.

Ensuite, j'ai essayé urllib et urllib2, en passant les en-têtes et les paramètres sous forme de dict. Cela semble renvoyer la page de connexion, au lieu de la page à laquelle j'essaie de me connecter, je suppose que c'est à cause du manque de cookies ou de quelque chose.

Suis-je en train de manquer quelque chose de simple?

Merci.

52
Ace

Se concentrer sur urllib2 pour cela, ça marche plutôt bien. Ne jouez pas avec httplib, ce n'est pas l'API de niveau supérieur.

Ce que vous remarquez, c'est que urllib2 ne suit pas la redirection.

Vous devez plier dans une instance de HTTPRedirectHandler qui interceptera et suivra les redirections.

En outre, vous souhaiterez peut-être sous-classer le HTTPRedirectHandler par défaut pour capturer les informations que vous vérifierez ensuite dans le cadre de votre test unitaire.

cookie_handler= urllib2.HTTPCookieProcessor( self.cookies )
redirect_handler= HTTPRedirectHandler()
opener = urllib2.build_opener(redirect_handler,cookie_handler)

Vous pouvez ensuite utiliser cet objet opener pour POST et GET, en gérant correctement les redirections et les cookies.

Vous pouvez également ajouter votre propre sous-classe de HTTPHandler pour capturer et enregistrer divers codes d'erreur.

31
S.Lott

Voici mon point de vue sur cette question.

#!/usr/bin/env python

import urllib
import urllib2


class HttpBot:
    """an HttpBot represents one browser session, with cookies."""
    def __init__(self):
        cookie_handler= urllib2.HTTPCookieProcessor()
        redirect_handler= urllib2.HTTPRedirectHandler()
        self._opener = urllib2.build_opener(redirect_handler, cookie_handler)

    def GET(self, url):
        return self._opener.open(url).read()

    def POST(self, url, parameters):
        return self._opener.open(url, urllib.urlencode(parameters)).read()


if __== "__main__":
    bot = HttpBot()
    ignored_html = bot.POST('https://example.com/authenticator', {'passwd':'foo'})
    print bot.GET('https://example.com/interesting/content')
    ignored_html = bot.POST('https://example.com/deauthenticator',{})
15
Jason Pepas

@ S.Lott, merci. Votre suggestion a fonctionné pour moi, avec quelques modifications. Voici comment je l'ai fait.

data = urllib.urlencode(params)
url = Host+page
request = urllib2.Request(url, data, headers)
response = urllib2.urlopen(request)

cookies = CookieJar()
cookies.extract_cookies(response,request)

cookie_handler= urllib2.HTTPCookieProcessor( cookies )
redirect_handler= HTTPRedirectHandler()
opener = urllib2.build_opener(redirect_handler,cookie_handler)

response = opener.open(request)
13
Ace

J'ai dû faire cette chose moi-même récemment. Je n'avais besoin que de cours de la bibliothèque standard. Voici un extrait de mon code:

from urllib import urlencode
from urllib2 import urlopen, Request

# encode my POST parameters for the login page
login_qs = urlencode( [("username",USERNAME), ("password",PASSWORD)] )

# extract my session id by loading a page from the site
set_cookie = urlopen(URL_BASE).headers.getheader("Set-Cookie")
sess_id = set_cookie[set_cookie.index("=")+1:set_cookie.index(";")]

# construct headers dictionary using the session id
headers = {"Cookie": "session_id="+sess_id}

# perform login and make sure it worked
if "Announcements:" not in urlopen(Request(URL_BASE+"login",headers=headers), login_qs).read():
    print "Didn't log in properly"
    exit(1)

# here's the function I used after this for loading pages
def download(page=""):
    return urlopen(Request(URL_BASE+page, headers=headers)).read()

# for example:
print download(URL_BASE + "config")
11
Eli Courtwright

Je donnerais à Mechanize ( http://wwwsearch.sourceforge.net/mechanize/ ) un coup de feu. Il peut très bien gérer vos cookies/en-têtes de manière transparente.

8

Essayez twill - un langage simple qui permet aux utilisateurs de naviguer sur le Web à partir d'une interface de ligne de commande. Avec twill, vous pouvez naviguer sur des sites Web qui utilisent des formulaires, des cookies et la plupart des fonctionnalités Web standard. Plus précisément, sergé est écrit en Python et a un API python , par exemple:

from twill import get_browser
b = get_browser()

b.go("http://www.python.org/")
b.showforms()
6
gimel

Outre le fait qu'il vous manque peut-être un cookie, il peut y avoir des champs dans le formulaire que vous NE POSTEZ PAS au serveur Web. La meilleure façon serait de capturer le réel POST à partir d'un navigateur Web. Vous pouvez utiliser LiveHTTPHeaders ou WireShark pour espionner le trafic et imiter le même comportement dans votre script.

0
chnrxn

Funkload est également un excellent outil de test d'applications Web. Il enveloppe webunit pour gérer l'émulation du navigateur, puis vous offre des fonctionnalités de test de charge et de fonctionnalité en plus.

0
Ned Batchelder