python实现12306验证和登录
2017-08-07 10:20
866 查看
1.获取验证码
分析:这里可以看出验证码的获取地址,最后一个参数不知道是什么意思,我们直接去掉,然后发现在浏览器中仍然能请求到验证码。
验证码连接:https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand
请求到的验证码如下:由于每次请求验证码地址验证码都会改变,所以看到的和上图验证码不同,请知晓
2.登录按钮点击
登录按钮点击的时候会首先执行验证码的验证操作,只有验证成功后才会执行登录操作,是两个接口2.1 验证码验证接口
通过chrome抓包工具,抓到的验证码验证接口及参数介绍url = "https://kyfw.12306.cn/passport/captcha/captcha-check"
data = {
'login_site':'E', #固定的
'rand':'sjrand', #固定的
'answer':'35,100,240,35' #验证码对应的坐标,两个为一组,跟选择顺序有关,有几个正确的,输入几个
}
2.2 验证码详细介绍
一共有8个验证码,验证码我们编号从做到右从上到下,依次为0,1,2,3,4,5,6,7(程序员思维,见谅),为序号转坐标做准备# --------------------------------------------------
# | | |
# 0 | 1 | 2 | 3
# | | |
# --------------------------------------------------
# | | |
# 4 | 5 | 6 | 7
# | | |
# --------------------------------------------------
大约一个验证码的宽高在70左右,所以每个验证码的坐标中点大约为,注意大约,请勿上纲上线
-------------------------------------------------------
| | |
35,35 | 105,35 | 175,35 | 245,35
| | |
-------------------------------------------------------
| | |
35,105 | 105,105 | 175,105 | 245,105
| | |
-------------------------------------------------------
2.3 验证码的验证结果,json形式的字符串
<HashMap><result_message>验证码校验失败</result_message>
<result_code>5</result_code>
</HashMap>
result_code结果:
4=验证成功
5=验证失败
7=验证码过期
其他结果暂时不清楚,待尝试
3.登录请求
3.1 登录接口及参数
loginUrl = "https://kyfw.12306.cn/passport/web/login"data = {
'username':'xxxxxxxx', #用户名,这个没什么好说的
'password':'oooooooo', #登录密码
'appid':'otn' #不知道是什么,是固定值
}
咦?发现了什么问题?没有跟验证码有关的任何信息,为什么?由于12306是用session信息验证的,所以验证结果信息在session中,具体看后面的代码详细注释
3.2 登录返回结果,依然是json形式的字符串
<HashMap><result_message>登录成功</result_message>
<result_code>0</result_code>
<uamtk>zdVRma2Gm5lZE-CJx5Lbn8rJJrQ_20-ghfTSkgpls2s0</uamtk>
</HashMap>
4. 详细代码及注释
#_*_coding:utf-8_*_ ''' >>> time:2017-08-04 >>> __author__:swh ''' import requests from PIL import Image from json import loads import getpass from requests.packages.urllib3.exceptions import InsecureRequestWarning # 禁用安全请求警告 requests.packages.urllib3.disable_warnings(InsecureRequestWarning) class LoginTic(object): def __init__(self): self.headers = { "User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36" } # 创建一个网络请求session实现登录验证 self.session = requests.session() # 获取验证码图片 def getImg(self): url = "https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand"; response = self.session.get(url=url,headers=self.headers,verify=False) # 把验证码图片保存到本地 with open('img.jpg','wb') as f: f.write(response.content) # 用pillow模块打开并解析验证码,这里是假的,自动解析以后学会了再实现 try: im = Image.open('img.jpg') # 展示验证码图片,会调用系统自带的图片浏览器打开图片,线程阻塞 im.show() # 关闭,只是代码关闭,实际上图片浏览器没有关闭,但是终端已经可以进行交互了(结束阻塞) im.close() except: print u'请输入验证码' #======================================================================= # 根据打开的图片识别验证码后手动输入,输入正确验证码对应的位置,例如:2,5 # --------------------------------------- # | | | # 0 | 1 | 2 | 3 # | | | # --------------------------------------- # | | | # 4 | 5 | 6 | 7 # | | | # --------------------------------------- #======================================================================= captcha_solution = raw_input('请输入验证码位置,以","分割[例如2,5]:') return captcha_solution # 验证结果 def checkYanZheng(self,solution): # 分割用户输入的验证码位置 soList = solution.split(',') # 由于12306官方验证码是验证正确验证码的坐标范围,我们取每个验证码中点的坐标(大约值) yanSol = ['35,35','105,35','175,35','245,35','35,105','105,105','175,105','245,105'] yanList = [] for item in soList: print item yanList.append(yanSol[int(item)]) # 正确验证码的坐标拼接成字符串,作为网络请求时的参数 yanStr = ','.join(yanList) checkUrl = "https://kyfw.12306.cn/passport/captcha/captcha-check" data = { 'login_site':'E', #固定的 'rand':'sjrand', #固定的 'answer':yanStr #验证码对应的坐标,两个为一组,跟选择顺序有关,有几个正确的,输入几个 } # 发送验证 cont = self.session.post(url=checkUrl,data=data,headers=self.headers,verify=False) # 返回json格式的字符串,用json模块解析 dic = loads(cont.content) code = dic['result_code'] # 取出验证结果,4:成功 5:验证失败 7:过期 if str(code) == '4': return True else: return False # 发送登录请求的方法 def loginTo(self): # 用户输入用户名,这里可以直接给定字符串 userName = raw_input('Please input your userName:') # 用户输入密码,这里也可以直接给定 # pwd = raw_input('Please input your password:') # 输入的内容不显示,但是会接收,一般用于密码隐藏 pwd = getpass.getpass('Please input your password:') loginUrl = "https://kyfw.12306.cn/passport/web/login" data = { 'username':userName, 'password':pwd, 'appid':'otn' } result = self.session.post(url=loginUrl,data=data,headers=self.headers,verify=False) dic = loads(result.content) print result.content mes = dic['result_message'] # 结果的编码方式是Unicode编码,所以对比的时候字符串前面加u,或者mes.encode('utf-8') == '登录成功'进行判断,否则报错 if mes == u'登录成功': print '恭喜你,登录成功,可以购票!' else: print '对不起,登录失败,请检查登录信息!' if __name__ == '__main__': # checkYanZheng('0,3') login = LoginTic() yan = login.getImg() chek = False #只有验证成功后才能执行登录操作 while not chek: chek = login.checkYanZheng(yan) if chek: print '验证通过!' else: print '验证失败,请重新验证!' login.loginTo()
说明:我这里写的只是实现12306的整个登录流程,验证码需要手动输入正确验证码的位置,不能自动识别验证码,我在网上看了一个大牛写的fuck12306.py是用于自动解析验证码的,最后更新时间是去年,我还没尝试,如果可以的话,再发博分享。有需要的朋友可以拿去尝试。
相关文章推荐
- python实现12306验证和登录
- 使用Python的Flask框架表单插件Flask-WTF实现Web登录验证
- python学习系列之python装饰器基础(3)---装饰器实现用户登录验证
- python requests实现windows身份验证登录
- 练习:python 操作Mysql 实现登录验证 用户权限管理
- 使用Python的Flask框架表单插件Flask-WTF实现Web登录验证
- python+pyqt实现12306图片验证效果
- Python 实现12306登录功能实例代码
- Python实现简单登录验证
- Python实现简单登录验证
- Python登录注册验证功能实现
- python+pyqt实现12306图片验证效果
- Python+django实现邮箱验证登录
- python自动登录12306并自动点击验证码完成登录的实现源代码
- Servlet实现用户登录页面(通过数据库验证)
- Python完全识别验证码自动登录
- 用python实现二叉搜索树/查找树的简单实现及验证(判断)(三)(栈中根序遍历)
- Python实现学校学生管理系统的自动登录
- (十三)使用handler实现登录验证
- Servlet课程0425(四) Servlet实现简单用户登录验证