PC 登录新浪微博时, 在客户端用js预先对用户名、密码都进行了加密, 而且在POST之前会GET 一组参数,这也将作为POST_DATA 的一部分。 这样, 就不能用通常的那种简单方法来模拟POST 登录( 比如 人人网 )。 由于要用的一部分微博数据用API获取不方便, 所以还是要自己写个小爬虫, 模拟登录是必不可少的。琢磨了一下这个东西,最终登录成功。 1, 在提交POST请求之前, 需要GET 获取两个参数。 地址是:http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.3.18) 得到的数据中有 "servertime" 和 "nonce" 的值, 是随机的,其他值貌似没什么用。 2, 通过httpfox 观察POST 的数据, 参数较复杂,其中 “su" 是加密后的username, "sp"是加密后的password。"servertime" 和 ”nonce" 是上一步得到的。其他参数是不变的。 username 经过了BASE64 计算: username = base64.encodestring( urllib.quote(username) )[:-1]; password 经过了三次SHA1 加密, 且其中加入了 servertime 和 nonce 的值来干扰。 即: 两次SHA1加密后, 将结果加上 servertime 和 nonce 的值, 再SHA1 算一次。 将参数组织好, POST请求。 这之后还没有登录成功。 POST后得到的内容中包含一句 location.replace("http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack&retcode=101&reason=%B5%C7%C2%BC%C3%FB%BB%F2%C3%DC%C2%EB%B4%ED%CE%F3"); 这是登录失败时的结果, 登录成功后结果与之类似, 不过retcode 的值是0 。接下来再请求这个URL,这样就成功登录到微博了。 记得要提前build 缓存。 下面是完整代码(没加注释,凑合看吧): #! /usr/bin/env python #coding=utf8 import urllib import urllib2 import cookielib import base64 import re import json import hashlib cj = cookielib.LWPCookieJar() cookie_support = urllib2.HTTPCookieProcessor(cj) opener = urllib2.build_opener(cookie_support, urllib2.HTTPHandler) urllib2.install_opener(opener) postdata = { 'entry': 'weibo', 'gateway': '1', 'from': '', 'savestate': '7', 'userticket': '1', 'ssosimplelogin': '1', 'vsnf': '1', 'vsnval': '', 'su': '', 'service': 'miniblog', 'servertime': '', 'nonce': '', 'pwencode': 'wsse', 'sp': '', 'encoding': 'UTF-8', 'url': 'http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack', 'returntype': 'META' } def get_servertime(): url = 'http://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=dW5kZWZpbmVk&client=ssologin.js(v1.3.18)&_=1329806375939' data = urllib2.urlopen(url).read() p = re.compile('\((.*)\)') try: json_data = p.search(data).group(1) data = json.loads(json_data) servertime = str(data['servertime']) nonce = data['nonce'] return servertime, nonce except: print 'Get severtime error!' return None def get_pwd(pwd, servertime, nonce): pwd1 = hashlib.sha1(pwd).hexdigest() pwd2 = hashlib.sha1(pwd1).hexdigest() pwd3_ = pwd2 + servertime + nonce pwd3 = hashlib.sha1(pwd3_).hexdigest() return pwd3 def get_user(username): username_ = urllib.quote(username) username = base64.encodestring(username_)[:-1] return username def login(): username = '你的登录邮箱' pwd = '你的密码' url = 'http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.3.18)' try: servertime, nonce = get_servertime() except: return global postdata postdata['servertime'] = servertime postdata['nonce'] = nonce postdata['su'] = get_user(username) postdata['sp'] = get_pwd(pwd, servertime, nonce) postdata = urllib.urlencode(postdata) headers = {'User-Agent':'Mozilla/5.0 (X11; Linux i686; rv:8.0) Gecko/20100101 Firefox/8.0'} req = urllib2.Request( url = url, data = postdata, headers = headers ) result = urllib2.urlopen(req) text = result.read() p = re.compile('location\.replace\(\'(.*?)\'\)') try: login_url = p.search(text).group(1) #print login_url urllib2.urlopen(login_url) print "登录成功!" except: print 'Login error!' login() 请多批评指教, 谢谢! 欢迎交流: 新浪微博 http://weibo.com/rongxs |
|