302s и потеря куки с urllib2 - PullRequest
       65

302s и потеря куки с urllib2

3 голосов
/ 05 апреля 2011

Я использую liburl2 с CookieJar / HTTPCookieProcessor в попытке смоделировать вход на страницу для автоматизации загрузки.

Я видел несколько вопросов и ответов по этому вопросу, но ничего, что решало бы мою проблему.Я теряю свой cookie, когда я имитирую логин, который заканчивается перенаправлением 302.Ответ 302 - это то, где cookie устанавливается сервером, но urllib2 HTTPCookieProcessor, похоже, не сохраняет cookie во время перенаправления.Я попытался создать класс HTTPRedirectHandler, чтобы игнорировать перенаправление, но это не помогло.Я попытался ссылаться на CookieJar глобально для обработки файлов cookie из HTTPRedirectHandler, но 1. Это не сработало (потому что я обрабатывал заголовок из перенаправителя, а используемой мной функции CookieJar extract_cookies требовался полный запрос) и2. Это ужасный способ справиться с этим.

Мне, вероятно, нужно какое-то руководство по этому вопросу, так как я довольно зелен с Python.Я думаю, что я в основном лаю здесь правильное дерево, но, возможно, сосредотачиваюсь на неправильной ветви.

cj = cookielib.CookieJar()
cookieprocessor = urllib2.HTTPCookieProcessor(cj)


class MyHTTPRedirectHandler(urllib2.HTTPRedirectHandler):
  def http_error_302(self, req, fp, code, msg, headers):
    global cj
    cookie = headers.get("set-cookie")
    if cookie:
      # Doesn't work, but you get the idea
      cj.extract_cookies(headers, req)

    return urllib2.HTTPRedirectHandler.http_error_302(self, req, fp, code, msg, headers)

  http_error_301 = http_error_303 = http_error_307 = http_error_302

cookieprocessor = urllib2.HTTPCookieProcessor(cj)

# Oh yeah.  I'm using a proxy too, to follow traffic.
proxy = urllib2.ProxyHandler({'http': '127.0.0.1:8888'})
opener = urllib2.build_opener(MyHTTPRedirectHandler, cookieprocessor, proxy)

Добавление: я тоже пытался использовать механизацию, но безуспешно.Вероятно, это новый вопрос, но я задам его здесь, поскольку это та же самая конечная цель:

Этот простой код, использующий Mechanize, при использовании с URL-адресом 302 (http://fxfeeds.mozilla.com/firefox/headlines.xml) - обратите внимание, чтоТо же самое происходит, когда не используется set_handle_robots (False). Я просто хотел убедиться, что это не так:

import urllib2, mechanize

browser = mechanize.Browser()
browser.set_handle_robots(False)
opener = mechanize.build_opener(*(browser.handlers))
r = opener.open("http://fxfeeds.mozilla.com/firefox/headlines.xml")

Вывод:

Traceback (most recent call last):
  File "redirecttester.py", line 6, in <module>
    r = opener.open("http://fxfeeds.mozilla.com/firefox/headlines.xml")
  File "build/bdist.macosx-10.6-universal/egg/mechanize/_opener.py", line 204, in open
  File "build/bdist.macosx-10.6-universal/egg/mechanize/_urllib2_fork.py", line 457, in http_response
  File "build/bdist.macosx-10.6-universal/egg/mechanize/_opener.py", line 221, in error
  File "build/bdist.macosx-10.6-universal/egg/mechanize/_urllib2_fork.py", line 332, in _call_chain
  File "build/bdist.macosx-10.6-universal/egg/mechanize/_urllib2_fork.py", line 571, in http_error_302
  File "build/bdist.macosx-10.6-universal/egg/mechanize/_opener.py", line 188, in open
  File "build/bdist.macosx-10.6-universal/egg/mechanize/_mechanize.py", line 71, in http_request
AttributeError: OpenerDirector instance has no attribute '_add_referer_header'

Есть идеи?

Ответы [ 4 ]

2 голосов
/ 05 апреля 2011

Недавно у меня возникла та же самая проблема, но в целях экономии времени она была решена и я решил использовать mechanize.Он может использоваться как полная замена для urllib2, который ведет себя точно так, как вы ожидаете, что браузер будет вести себя в отношении заголовков, перенаправлений и файлов cookie Referer.

import mechanize
cj = mechanize.CookieJar()
browser = mechanize.Browser()
browser.set_cookiejar(cj)
browser.set_proxies({'http': '127.0.0.1:8888'})

# Use browser's handlers to create a new opener
opener = mechanize.build_opener(*browser.handlers)

Объект Browser может бытьиспользуется как открывашка (с использованием метода .open()).Он поддерживает состояние внутри, но также возвращает объект ответа при каждом вызове.Таким образом, вы получаете большую гибкость.

Кроме того, если вам не нужно проверять cookiejar вручную или передавать его чему-то другому, вы можете пропустить явное создание и назначение этого объекта.а также.

Я полностью осознаю, что это не касается того, что на самом деле происходит и почему urllib2 не может предоставить это решение "из коробки" или, по крайней мере, без особых настроек, но если выу вас мало времени и вы просто хотите, чтобы это сработало, просто используйте механизацию.

1 голос
/ 12 июня 2011

Зависит от того, как осуществляется перенаправление.Если это сделано через HTTP Refresh, то Mechanize имеет HTTPRefreshProcessor, который вы можете использоватьПопробуйте создать открывалку так:

cj = mechanize.CookieJar()
opener = mechanize.build_opener(
    mechanize.HTTPCookieProcessor(cj),
    mechanize.HTTPRefererProcessor,
    mechanize.HTTPEquivProcessor,
    mechanize.HTTPRefreshProcessor)
0 голосов
/ 04 февраля 2016

У меня также была такая же проблема, когда сервер отвечал на запрос POST входа в систему 302 и токеном сеанса в заголовке Set-Cookie. Используя Wireshark, было ясно видно, что urllib следовал за перенаправлением, но не включал токен сеанса в Cookie.

Я буквально просто вырвал urllib и сделал прямую замену с запросами , и это сработало в первый раз без необходимости что-либо менять. Большие реквизиты для этих парней.

0 голосов
/ 11 августа 2011

У меня только что работает вариант нижеприведенного, по крайней мере, когда я пытаюсь прочитать Atom из http://www.fudzilla.com/home?format=feed&type=atom

Я не могу убедиться, что приведенный ниже фрагмент будет работать как ...есть, но может дать вам начало:

import cookielib
cookie_jar = cookielib.LWPCookieJar()
cookie_handler = urllib2.HTTPCookieProcessor(cookie_jar)
handlers = [cookie_handler] #+others, we have proxy + progress handlers
opener = apply(urllib2.build_opener, tuple(handlers + [_FeedURLHandler()])) #see http://code.google.com/p/feedparser/source/browse/trunk/feedparser/feedparser.py#2848 for implementation of _FeedURLHandler
opener.addheaders = [] #may not be needed but see the comments around the link referred to below
try:
    return opener.open(request) #see http://code.google.com/p/feedparser/source/browse/trunk/feedparser/feedparser.py#2954 for implementation of request
finally:
    opener.close()
...