0%

基于GAE使用python通过cookie登陆网页获取信息

前言:因为想用python每天爬一个BT网页,再把里面的图片保存在GAE的数据库上,然后当访问appspot时就以统一的格式输出,之前一直在试图解决appspot被墙的问题,想绑定一个自己的域名,现在的google app的商业套件要收费了,所以这种方法已经失效。我目前发现可行的就是用一个没有被墙的空间在里面做一个反向代理,用.htaccess来重写域名跳转;或者用你自己另外域名的一个子域名app.ABC.com跳转到*.appspot.com,然后在目的域名www.AAA.com的CHAME里填上app.ABC.com,那么你的www.AAA.com不用翻墙就可以访问*.appspot.com

python使用cookie登陆网页有很多个库可以调用,例如httplib,不过这种方法我在本地可以调试通过,但是部署在GAE上却提示307错误,这应该跟GAE的一些设定有关,个人建议使用google.appengine.api里面的urlfetch,有官方文档说明,绝对能用。
第一步,你要知道登陆网页是怎么post数据?是post到哪个网址?是post哪些数据?只要你清楚这些,你才可以去写python的代码,要不你根本不知道错误发生在哪里。建议安装firefox的httpfox来查看目标网站的header,cookie,POST Data和返回的Content。然后用一个post数据的插件,模拟post数据到目标网站,看一下Response是否已经登录,可以登录那就证明你post数据的格式没有问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import re
import urllib
import urllib2
import webapp2
from sgmllib import SGMLParser
from google.appengine.ext import webapp
from google.appengine.api import urlfetch
from google.appengine.ext.webapp.util import run_wsgi_app

class MainPage(webapp2.RequestHandler):
def get(self):
headers = {'Content-Type':'application/x-www-form-urlencoded'}
params = 'referer=index.php&loginfield=username&username=******&password=******&questionid=0&answer=&cookietime=2592000&loginsubmit=%CC%E1+%26%23160%3B+%BD%BB'
login_url = "http://www.ABC.com/logging.php?action=login"
res = urlfetch.fetch(url=login_url, payload=params,method=urlfetch.POST,headers=headers,allow_truncated=True)

self.response.out.write(res.status_code)
self.response.out.write(res.headers)
self.response.out.write(res.content)

app = webapp2.WSGIApplication([('/', MainPage)], debug=True)

注意问题:我之前就不知道params里面还有一个loginsubmit的参数,之前因为没有这个参数死活也登录不上,还有我的params是直接使用RAW的application/x-www-form-urlencoded格式。我是从firefox里面的httpfox里面看到的POST Data就是这些,而且里面包含中文,所以就直接COPY过来,如果没有中文字符,你也可以使用以下这种:

1
params = urllib.urlencode({'username' : '******' , 'password' : '******'})

第二步:在你的浏览器中逐个删除cookie,看一下没有哪一个cookie的时候网页不能登录,通常是包含一大串字符的就是,我登录的网站是cdb_auth这个字符对。接着的步骤就比较简单,从返回的headers里面取出你需要的cookie,然后添加到你发送的headers里面,这样才可以继续访问网站,因为GAE的fetch说明文档写着,自动跳转时不会带cookie的,如果你想带cookie跳转,是要自己手动取出,自己手动完成跳转。那我就用cookie访问以下首页就知道到底有没有成功,代码添加在MainPage里面:

1
2
3
4
5
6
7
8
9
10
data = urllib.urlencode(res.headers)
cookieAuth = re.findall(r"cdb_auth%3D.*?expires",data)
cookieAuth2 = re.sub('cdb_auth%3D', '', cookieAuth[0])
cookieAuth3 = re.sub('%3B\+expires', '', cookieAuth2)

login_index = "http://www.ABC.com/"
headers_cookie = {"Content-Type":"application/x-www-form-urlencoded", "Cookie":"cdb_auth="+cookieAuth3}
response = urlfetch.fetch(url=login_index, method=urlfetch.POST,headers=headers_cookie,allow_truncated=True)

self.response.out.write(response.content)

查看输出,搞定收工