链家使用的是单点登录(CAS)。模拟登录的时候主要分析表单提交的Url、cookie、表单内容,说白了就是带着cookie post账号密码,使session合法化的一个过程,只不过链家的登录过程稍微复杂一点。
要想实现模拟登录,就要先观察正常登录的流程: 打开chrome的开发者工具,选择network,打开登录页:
可以看到header里面生成了一个键名为JSESSIONID的cookie,没有这个cookie是无法登录的,所以发送表单内容之前一定要先获取这个cookie,然后带着这个cookie去post数据。 然后输入账号密码进行登录,可以看到下面的一个数据的发送过程:
先看第一个:
我们post一个表单数据过去,带着cookie,服务器验证用户合法性之后302到另外一个地址,可以看到header头里面cookie是带着JSESSIONID的,然后看Form Data,username、password是账号密码不用说,lt、execution、_eventId都是表单中的隐藏域的value:
所以,在第一次打开登录页面的时候就要获取这些信息,一并post,post之后302到一个地址:
可以看到在返回的headers里面又设置了一些cookie,其中最重要的也是代表合法用户的cookie就是lianjia_uuid,这个lianjia_uuid就相当于一个合法的令牌,带着这个cookie去访问任意一个链家页面,都是登录状态的。 我把代码简单的示范一下:
# encoding:utf-8 import urllib import urllib2 import json import cookielib import time import re #获取Cookiejar对象(存在本机的cookie消息) cookie = cookielib.CookieJar() #自定义opener,并将opener跟CookieJar对象绑定 opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie)) #安装opener,此后调用urlopen()时都会使用安装过的opener对象 urllib2.install_opener(opener) home_url = 'http://bj.lianjia.com/' auth_url = 'https://passport.lianjia.com/cas/login?service=http%3A%2F%2Fbj.lianjia.com%2F' chengjiao_url = 'http://bj.lianjia.com/chengjiao/' headers = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate, sdch', 'Accept-Language': 'zh-CN,zh;q=0.8', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'Content-Type': 'application/x-www-form-urlencoded', 'Host': 'passport.lianjia.com', 'Pragma': 'no-cache', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36' } # 获取lianjia_uuid req = urllib2.Request('http://bj.lianjia.com/') opener.open(req) # 初始化表单 req = urllib2.Request(auth_url, headers=headers) result = opener.open(req) # print(cookie) # 获取cookie和lt值 pattern = re.compile(r'JSESSIONID=(.*)') jsessionid = pattern.findall(result.info().getheader('Set-Cookie').split(';')[0])[0] html_content = result.read() pattern = re.compile(r'value=\"(LT-.*)\"') lt = pattern.findall(html_content)[0] pattern = re.compile(r'name="execution" value="(.*)"') execution = pattern.findall(html_content)[0] # print(cookie) # opener.open(lj_uuid_url) # print(cookie) # opener.open(api_url) # print(cookie) # data data = { 'username': 'YOUR USERNAME', 'password': 'YOUR PASSWORD', # 'service': 'http://bj.lianjia.com/', # 'isajax': 'true', # 'remember': 1, 'execution': execution, '_eventId': 'submit', 'lt': lt, 'verifyCode': '', 'redirect': '', } # urllib进行编码 post_data=urllib.urlencode(data) # header headers = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.8', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', # 'Content-Length': '152', 'Content-Type': 'application/x-www-form-urlencoded', 'Host': 'passport.lianjia.com', 'Origin': 'https://passport.lianjia.com', 'Pragma': 'no-cache', 'Referer': 'https://passport.lianjia.com/cas/login?service=http%3A%2F%2Fbj.lianjia.com%2F', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36', 'Upgrade-Insecure-Requests': '1', 'X-Requested-With': 'XMLHttpRequest', } headers2 = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate, sdch', 'Accept-Language': 'zh-CN,zh;q=0.8', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'Content-Type': 'application/x-www-form-urlencoded', 'Host': 'bj.lianjia.com', 'Pragma': 'no-cache', 'Referer': 'https://passport.lianjia.com/cas/xd/api?name=passport-lianjia-com', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36' } req = urllib2.Request(auth_url, post_data, headers) try: result = opener.open(req) except urllib2.HTTPError, e: print e.getcode() print e.reason print e.geturl() print "-------------------------" print e.info() print(e.geturl()) req = urllib2.Request(e.geturl()) result = opener.open(req) req = urllib2.Request(chengjiao_url) result = opener.open(req).read() print(result)PS:后来发现链家登陆需要先访问其他页面获取lianjia_uuid(cookie)