我使用了机械化并在GAE上部署了一个应用程序,它运行正常。但是,对于我正在制作的应用程序,我正在尝试通过mechanize自动登录到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,我得到了用户收件箱的页面。
答案 0 :(得分:6)
问题很可能是由于谷歌如何破坏了GAE上的urllib2模块。
在内部,它现在使用urlfetch模块(谷歌写的东西)并且他们已经完全删除了HTTPCookieProcessor()功能 - 这意味着,cookie不会从请求到请求持久化,这是以编程方式自动登录网站时的关键部分。
有一种解决方法,但不使用机械化。你必须推出自己的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一样使用它,除了您使用的方法只是“打开”。