python实现12306验证和登录

举报
悦来客栈的老板 发表于 2020/12/29 01:25:04 2020/12/29
【摘要】 原文地址:http://blog.csdn.net/sinat_36772813/article/details/76804799 1.获取验证码 分析:这里可以看出验证码的获取地址,最后一个参数不知道是什么意思,我们直接去掉,然后发现在浏览器中仍然能请求到验证码。 验证码连接:https://kyfw.12306.cn/passport/captc...

原文地址:http://blog.csdn.net/sinat_36772813/article/details/76804799


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. 详细代码及注释


   
  1. #_coding:utf-8_
  2. import requests
  3. from PIL import Image
  4. from json import loads
  5. import getpass
  6. from requests.packages.urllib3.exceptions import InsecureRequestWarning
  7. # 禁用安全请求警告
  8. requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
  9. class LoginTic(object):
  10. def __init__(self):
  11. self.headers = {
  12. "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"
  13. }
  14. # 创建一个网络请求session实现登录验证
  15. self.session = requests.session()
  16. # 获取验证码图片
  17. def getImg(self):
  18. url = "https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand";
  19. response = self.session.get(url=url,headers=self.headers,verify=False)
  20. # 把验证码图片保存到本地
  21. with open('img.jpg','wb') as f:
  22. f.write(response.content)
  23. # 用pillow模块打开并解析验证码,这里是假的,自动解析以后学会了再实现
  24. try:
  25. im = Image.open('img.jpg')
  26. # 展示验证码图片,会调用系统自带的图片浏览器打开图片,线程阻塞
  27. im.show()
  28. # 关闭,只是代码关闭,实际上图片浏览器没有关闭,但是终端已经可以进行交互了(结束阻塞)
  29. im.close()
  30. except:
  31. print ('请输入验证码')
  32. #=======================================================================
  33. # 根据打开的图片识别验证码后手动输入,输入正确验证码对应的位置,例如:2,5
  34. # ---------------------------------------
  35. # | | |
  36. # 0 | 1 | 2 | 3
  37. # | | |
  38. # ---------------------------------------
  39. # | | |
  40. # 4 | 5 | 6 | 7
  41. # | | |
  42. # ---------------------------------------
  43. #=======================================================================
  44. captcha_solution = input('请输入验证码位置,以","分割[例如2,5]:')
  45. return captcha_solution
  46. # 验证结果
  47. def checkYanZheng(self,solution):
  48. # 分割用户输入的验证码位置
  49. soList = solution.split(',')
  50. # 由于12306官方验证码是验证正确验证码的坐标范围,我们取每个验证码中点的坐标(大约值)
  51. yanSol = ['35,35','105,35','175,35','245,35','35,105','105,105','175,105','245,105']
  52. yanList = []
  53. for item in soList:
  54. print (item)
  55. yanList.append(yanSol[int(item)])
  56. # 正确验证码的坐标拼接成字符串,作为网络请求时的参数
  57. yanStr = ','.join(yanList)
  58. checkUrl = "https://kyfw.12306.cn/passport/captcha/captcha-check"
  59. data = {
  60. 'login_site':'E', #固定的
  61. 'rand':'sjrand', #固定的
  62. 'answer':yanStr #验证码对应的坐标,两个为一组,跟选择顺序有关,有几个正确的,输入几个
  63. }
  64. # 发送验证
  65. cont = self.session.post(url=checkUrl,data=data,headers=self.headers,verify=False)
  66. # 返回json格式的字符串,用json模块解析
  67. print (cont.content)
  68. dic = loads(cont.content.decode())
  69. code = dic['result_code']
  70. # 取出验证结果,4:成功 5:验证失败 7:过期
  71. if str(code) == '4':
  72. return True
  73. else:
  74. return False
  75. # 发送登录请求的方法
  76. def loginTo(self):
  77. # 用户输入用户名,这里可以直接给定字符串
  78. userName = input('Please input your userName:')
  79. # 用户输入密码,这里也可以直接给定
  80. # pwd = raw_input('Please input your password:')
  81. # 输入的内容不显示,但是会接收,一般用于密码隐藏
  82. pwd = getpass.getpass('Please input your password:')
  83. loginUrl = "https://kyfw.12306.cn/passport/web/login"
  84. data = {
  85. 'username':userName,
  86. 'password':pwd,
  87. 'appid':'otn'
  88. }
  89. result = self.session.post(url=loginUrl,data=data,headers=self.headers,verify=False)
  90. dic = loads(result.content.decode())
  91. print (result.content)
  92. mes = dic['result_message']
  93. # 结果的编码方式是Unicode编码,所以对比的时候字符串前面加u,或者mes.encode('utf-8') == '登录成功'进行判断,否则报错
  94. if mes == '登录成功':
  95. print ('恭喜你,登录成功,可以购票!')
  96. else:
  97. print ('对不起,登录失败,请检查登录信息!')
  98. if __name__ == '__main__':
  99. # checkYanZheng('0,3')
  100. login = LoginTic()
  101. yan = login.getImg()
  102. chek = False
  103. #只有验证成功后才能执行登录操作
  104. while not chek:
  105. chek = login.checkYanZheng(yan)
  106. if chek:
  107. print ('验证通过!')
  108. else:
  109. print ('验证失败,请重新验证!')
  110. login.loginTo()





说明:我这里写的只是实现12306的整个登录流程,验证码需要手动输入正确验证码的位置,不能自动识别验证码,我在网上看了一个大牛写的fuck12306.py是用于自动解析验证码的,最后更新时间是去年,我还没尝试,如果可以的话,再发博分享。有需要的朋友可以拿去尝试。

文章来源: blog.csdn.net,作者:悦来客栈的老板,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/qq523176585/article/details/78688284

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。