Механизация не работает для автоматизации входа в Gmail в Google Appengine - PullRequest
5 голосов
/ 12 апреля 2011

Я использовал механизировать и развернул приложение на GAE, и оно отлично работает. Но для приложения, которое я создаю, я пытаюсь автоматизировать вход в gmail через механизировать. Он не работает в среде разработки на локальном компьютере, а также после развертывания на appengine.

Мне удалось использовать тот же сценарий для запуска его на моем сервере через mod_python с использованием PSP.

Я нашел здесь много решений, но ни одно из них мне не подходит. Вот фрагмент моего кода:

<snip>
br = mechanize.Browser()
response = br.open("http://www.gmail.com")
loginForm = br.forms().next()
loginForm["Email"] = self.request.get('user')
loginForm["Passwd"] = self.request.get('password')
response = br.open(loginForm.click())
response2 = br.open("http://mail.google.com/mail/h/")
result = response2.read()
<snip>

Когда я смотрю на результат, все, что я получаю, это страницу входа в систему при использовании с appengine. Но с mod_python, размещенным на моем собственном сервере, я получаю страницу с почтовым ящиком пользователя.

1 Ответ

6 голосов
/ 13 апреля 2011

Проблема, скорее всего, связана с тем, как Google повредил модуль urllib2 в GAE.

Внутренне он теперь использует модуль urlfetch (что-то, что написал Google), и они полностью удалили функциональность HTTPCookieProcessor () - это означает, что куки не сохраняются от запроса к запросу, что является критической частью при автоматическом входе на сайты программно ,

Есть способ обойти это, но без использования механизации. Вы должны свернуть свой собственный процессор Cookie - вот базовый подход, который я выбрал (не идеальный, но он выполняет свою работу):

import urllib, urllib2, Cookie
from google.appengine.api import urlfetch
from urlparse import urljoin
import logging

class GAEOpener(object):
    def __init__(self):
        self.cookie = Cookie.SimpleCookie()
        self.last_response = None

    def open(self, url, data = None):
        base_url = url
        if data is None:
            method = urlfetch.GET
        else:
            method = urlfetch.POST
        while url is not None:
            self.last_response = urlfetch.fetch(url = url,
                payload = data,
                method = method,
                headers = self._get_headers(self.cookie),
                allow_truncated = False,
                follow_redirects = False,
                deadline = 10
                )
            data = None # Next request will be a get, so no need to send the data again. 
            method = urlfetch.GET
            self.cookie.load(self.last_response.headers.get('set-cookie', '')) # Load the cookies from the response
            url = urljoin(base_url, self.last_response.headers.get('location'))
            if url == base_url:
                url = None
        return self.last_response

    def _get_headers(self, cookie):
        headers = {
            'Host' : '<ENTER HOST NAME HERE>',
            'User-Agent' : 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729)',
            'Cookie' : self._make_cookie_header(cookie)
             }
        return headers

    def _make_cookie_header(self, cookie):
        cookie_header = ""
        for value in cookie.values():
            cookie_header += "%s=%s; " % (value.key, value.value)
        return cookie_header

    def get_cookie_header(self):
        return self._make_cookie_header(self.cookie)

Вы можете использовать его, как если бы вы использовали urllib2.urlopen, за исключением того, что вы будете использовать метод "open".

...