52

我正在尝试通过在 Python 中编写登录序列脚本来测试 Web 应用程序的功能,但我遇到了一些麻烦。

这是我需要做的:

  1. 使用一些参数和标题进行 POST。
  2. 跟随重定向
  3. 检索 HTML 正文。

现在,我对 python 比较陌生,但是到目前为止我测试过的两件事都没有奏效。首先,我使用 httplib、putrequest()(在 URL 中传递参数)和 putheader()。这似乎没有遵循重定向。

然后我尝试了 urllib 和 urllib2,将标头和参数都作为 dicts 传递。这似乎返回了登录页面,而不是我尝试登录的页面,我猜这是因为缺少 cookie 或其他原因。

我错过了一些简单的东西吗?

谢谢。

4

8 回答 8

31

专注urllib2于此,效果很好。不要乱用httplib,它不是顶级 API。

你注意到的是它urllib2不遵循重定向。

您需要折叠一个实例,HTTPRedirectHandler该实例将捕获并遵循重定向。

此外,您可能希望对默认值进行子类化HTTPRedirectHandler以捕获信息,然后将其作为单元测试的一部分进行检查。

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

然后,您可以使用此opener对象进行 POST 和 GET,正确处理重定向和 cookie。

您可能还想添加自己的子类HTTPHandler来捕获和记录各种错误代码。

于 2008-11-19T14:52:47.490 回答
15

这是我对这个问题的看法。

#!/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 __name__ == "__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',{})
于 2011-01-29T09:33:42.020 回答
13

@S.Lott,谢谢。您的建议对我有用,并进行了一些修改。这就是我的做法。

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)
于 2008-11-19T15:17:31.590 回答
11

我最近不得不自己做这件事。我只需要标准库中的类。这是我的代码的摘录:

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")
于 2008-11-19T15:12:08.637 回答
8

我会给 Mechanize(http://wwwsearch.sourceforge.net/mechanize/)一个机会。它可能会透明地处理您的 cookie/标头。

于 2008-11-19T14:19:19.010 回答
6

试试twill - 一种允许用户从命令行界面浏览 Web 的简单语言。使用斜纹,您可以浏览使用表​​单、cookie 和大多数标准 Web 功能的网站。更重要的是,twill是用 python API 编写的Python例如

from twill import get_browser
b = get_browser()

b.go("http://www.python.org/")
b.showforms()
于 2008-11-19T14:15:32.323 回答
0

除了您可能缺少 cookie 的事实之外,表单中可能有一些字段是您没有 POST 到网络服务器的。最好的方法是从 Web 浏览器捕获实际的 POST。您可以使用LiveHTTPHeadersWireShark来窥探流量并在脚本中模仿相同的行为。

于 2008-11-19T14:00:59.157 回答
0

Funkload也是一个很棒的网络应用测试工具。它包装了 webunit 来处理浏览器仿真,然后在上面为您提供功能和负载测试功能。

于 2008-11-19T14:32:49.887 回答