Python: путаница urllib / urllib2 / httplib - PullRequest
52 голосов
/ 19 ноября 2008

Я пытаюсь проверить работоспособность веб-приложения, написав последовательность входа в Python, но у меня возникли некоторые проблемы.

Вот что мне нужно сделать:

  1. Сделайте POST с несколькими параметрами и заголовками.
  2. Следуйте за редиректом
  3. Получить тело HTML.

Теперь я относительно новичок в python, но две вещи, которые я тестировал до сих пор, не сработали. Сначала я использовал httplib, с putrequest () (передавая параметры внутри URL) и putheader (). Это не похоже на перенаправления.

Затем я попробовал urllib и urllib2, передавая оба заголовка и параметры как dicts. Похоже, это возвращает страницу входа, а не страницу, на которую я пытаюсь войти, я думаю, это из-за отсутствия файлов cookie или чего-то еще.

Мне не хватает чего-то простого?

Спасибо.

Ответы [ 8 ]

31 голосов
/ 19 ноября 2008

Сфокусируйтесь на 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, чтобы также регистрировать и регистрировать различные коды ошибок.

15 голосов
/ 29 января 2011

Вот мое мнение по этому вопросу.

#!/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',{})
13 голосов
/ 19 ноября 2008

@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)
11 голосов
/ 19 ноября 2008

Я должен был сделать это точно сам недавно. Мне нужны были только классы из стандартной библиотеки. Вот выдержка из моего кода:

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")
8 голосов
/ 19 ноября 2008

Я бы дал Mechanize (http://wwwsearch.sourceforge.net/mechanize/) шанс). Он вполне может прозрачно обрабатывать ваши cookie / заголовки.

6 голосов
/ 19 ноября 2008

Попробуйте twill - простой язык, который позволяет пользователям просматривать веб-страницы из интерфейса командной строки. С помощью twill вы можете перемещаться по веб-сайтам, которые используют формы, файлы cookie и большинство стандартных веб-функций. Более того, twill написано в Python и имеет Python API , например:

from twill import get_browser
b = get_browser()

b.go("http://www.python.org/")
b.showforms()
0 голосов
/ 19 ноября 2008

Funkload также является отличным инструментом для тестирования веб-приложений. Он оборачивает веб-модуль для эмуляции браузера, а затем предоставляет как функциональные, так и нагрузочные функции тестирования.

0 голосов
/ 19 ноября 2008

Помимо того факта, что вы можете пропустить cookie, могут быть некоторые поля в форме, которую вы не размещаете на веб-сервере. Наилучшим способом было бы получить фактический POST из веб-браузера. Вы можете использовать LiveHTTPHeaders или WireShark для отслеживания трафика и имитации того же поведения в вашем скрипте.

...