python实现12306抢票及自动邮件发送提醒付款功能


Posted in Python onMarch 08, 2018

#写在前面,这个程序我已经弄出来了,但是因为黄牛泛滥以及懒人太多,整个程序的代码就不贴出来了,这里纯粹就是技术交流。

只做技术交流、、、、、

python实现12306抢票及自动邮件发送提醒付款功能python实现12306抢票及自动邮件发送提醒付款功能

嗯,程序结束后,自己还是得手动付款。

废话不多说,下面就直接开始技术主要部分阐述。

先讲理论部分:首先我们需要代码实现一个浏览器功能,那么模块基本上可以确定urllib.parse、urllib.request,这两个包都是和网址有关的模块,那么咱们去登录一个网址,特别是有验证码这些的网址,我们登录进去是不是就行了?答案是对的,但是我们用代码实现的话,这个网址可能每次都有可能被代码去请求,那么服务器怎么知道我们是一个人,而不是多个浏览器不同的用户呢?

此时cookie就非常重要了,在代码中设置好cookie,那么对方服务器自然就知道我们是一个人,比较服务器都是这么区分的。python3中 cookie这个功能是封装在http.cookiejar这个模块之内。好了,代码如下:

# coding=utf-8
# author: Jason
# time:2018/1/16 20:00:00
#version:1.0
import urllib.request as ul
import urllib.parse as uz
import http.cookiejar as cookielib
from json import loads
c=cookielib.LWPCookieJar()#先把cookie对象存储为cookiejar的对象
cookie = ul.HTTPCookieProcessor(c)#把cookiejar对象转换为一个handle
opener = ul.build_opener(cookie)#建立一个模拟浏览器,需要handle作为参数
ul.install_opener(opener)#安装一个全局模拟浏览器,代表无论怎么访问都是一个浏览器操作而不是分开获取验证码等msg

好了,如此一来,我们代码的初步实现已经完成,接下来就是进入网络分析部分

首先可以使用google浏览器或者搜狗浏览器(本人用的搜狗),打开F12,也就是开发者模式,登录12306的登录地址 https://kyfw.12306.cn/otn/login/init

python实现12306抢票及自动邮件发送提醒付款功能

两个红圈中第二个是验证码来源,此时我们只需要记录这个网页(点进去)的详细情况,写入代码当中,python3中urllib.request这个模块打开既可

python实现12306抢票及自动邮件发送提醒付款功能

如此便是验证码来源,那么如何用代码捕捉呢?首先我们可以先乱输入密码,乱点验证码,然后我们直接点击登录

python实现12306抢票及自动邮件发送提醒付款功能

多了一个很奇妙的东西,此时,这里就是验证码验证的网址,那么我们是不是应该记录下来呢?很简单,到Headers里面就全都看得到了

python实现12306抢票及自动邮件发送提醒付款功能

上面那个是服务器验证网址,下面就是我们回复给他的东西,那么那个163,121其实就是我乱点的验证码坐标了。至于为啥是坐标,因为它是用鼠标去点图片,那么他只可能是记录坐标,除非他自己搞了一套人工智能验证图片,但基于他几年前就这么玩了,人工智能根本没有怎么开始,他自然只能是最原始的技术而已。

那么这代表了他是先验证验证码,那么验证密码的在哪?自然是需要验证码这关能过,那我们输一个正确的验证码,再写个错密码,登录

python实现12306抢票及自动邮件发送提醒付款功能

此时可以看到,和验证码一样的方法,我们的回复与验证都在这几个圈了,还记得上面验证码失败的时候回复给我们的code是不是有个数字?这个也很重要,那么可以看看我们的验证成功的验证码返回给我们的是什么东西

python实现12306抢票及自动邮件发送提醒付款功能

这次我们看到了,验证码成功,显示是4,好,那我们不就可以进行条件判断了么?

那么如何打开一个网址然后把我们点的东西一起发过去呢?上代码

headers={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36'}#先写个头,表示我这是浏览器用户登录而不是代码登录,如果不写,代码默认用的签名之类的是编程语言的标识,这样对方服务器很容易就发现你是个脚本了
def get_code():#获取验证码的步骤
  req = ul.Request('https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand&0.6758635422370105')
  req.headers = headers
  code_file = opener.open(req).read()#此时为浏览器的open而不再是ul.urlopen,下同
  with open(r'C:\Users\Administrator\Desktop\12306自动抢票\code.png','wb')as f:
    f.write(code_file)

把验证码直接下载后方电脑上,后面要坐标只需要打开这个图既可输入,坐标的输入方式我用字典表示给大家看{1:(45,45)}{2:(120,45)}{3:(180,45)}{4:(255,45)}{5:(45,120)}{6:(120,120)}{7:(180,120)}{8:(255,120)}

根据这个验证码的排序,我相信读者应该知道顺序怎么来的吧,比较坐标就能懂了。

继续

def main_():
  get_code()
  code = input('输入验证码:')
  req = ul.Request('https://kyfw.12306.cn/passport/captcha/captcha-check')
  req.headers = headers

  data = {
    'answer':code,
    'login_site':'E',
    'rand':'sjrand'
  }
  data = uz.urlencode(data).encode()#把字典转换为URL query string,此时是str,要把它变为byts。

  html = opener.open(req,data= data).read().decode()#读取出来是byts格式,转换为‘utf-8(默认)
  print(html)
  result = loads(html)
  if result['result_code']=='4':
    print('验证码通过')
    rep = ul.Request('https://kyfw.12306.cn/passport/web/login')
    rep.headers = headers
    data = {'username':'这里就是你用户名',
        'password':'这里就是你的密码',
        'appid':'otn'
    }
    data = uz.urlencode(data).encode() #看到了吗,这就是你给服务器回复的东西

    html1 = opener.open(rep,data = data ).read().decode()
    result1 = loads(html1)
    if result1['result_code'] == 0:
      print('账户密码验证通过')
    else:
      print(result1['result_message'])

  else:
    print('验证码校验失败,重来')


if __name__ == '__main__':
  main_()

此时,咱们就过了验证码密码这一关,后面是不是又要查票?那么同样的方法,我们就可以以此类推到最后一步,这里就不一一贴代码了

ps:查代码这几步的信息可是很重要喔,我们要把它记录好,并且这里面的信息包含了各种作为信息以及他们的顺序,多测试几次基本都能搞出来,这里就是提醒一点

python实现12306抢票及自动邮件发送提醒付款功能

找找规律,然后用split的方法完全就可以切割出来,然后一个循环,就可以得到第几个元素是我们要的,那么后面就可以标志判断返回值如果是无,就没票可以继续查询,直到有票就可以下一步;

那么有票的话,后面一样也是以此类推的方式,代码我就不重现了,很简单,我就把后面出现需要请求的网址都发出来供大家观摩

查询车票信息

url = 'https://kyfw.12306.cn/otn/leftTicket/queryZ?leftTicketDTO.train_date=%s&leftTicketDTO.from_station=%s&leftTicketDTO.to_station=%s&purpose_codes=ADULT'%(train_data,from_station,to_station)
req = ul.Request('https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest')#确定订单信息
req = ul.Request("https://kyfw.12306.cn/otn/confirmPassenger/initDc")#验证订单
req = ul.Request('https://kyfw.12306.cn/otn/confirmPassenger/getPassengerDTOs')#准备跨到下单中的过度
req = ul.Request('https://kyfw.12306.cn/otn/confirmPassenger/checkOrderInfo')#检查订单信息
req = ul.Request('https://kyfw.12306.cn/otn/confirmPassenger/getQueueCount')#信息提交给服务器,准备进入下单步骤
req = ul.Request('https://kyfw.12306.cn/otn/confirmPassenger/confirmSingleForQueue')#正式进入下单步骤
req = ul.Request('https://kyfw.12306.cn/otn/confirmPassenger/queryOrderWaitTime?random=%s&tourFlag=dc&_json_att=&REPEAT_SUBMIT_TOKEN=%s'%(numb,time.time()))#下单确认中,此时这个网址一般是进行两次访问,不知为何,我还是做了两次访问,numb是前面查询车票点击预定回复我们的信息中的一条,有点难找喔,我曾经找了三天。。。当然是因为自己不仔细而已
zreq = ul.Request("https://kyfw.12306.cn/otn/confirmPassenger/resultOrderForDcQueue")#最后的结果回执,如果一切都顺利,那么票就已经订了。我一般是打印他返回的内容
'''
      zreq = ul.Request("https://kyfw.12306.cn/otn/confirmPassenger/resultOrderForDcQueue")
      zreq.headers = headers
      data ={"REPEAT_SUBMIT_TOKEN":"%s"%numb,
          "_json_att": "",
          "orderSequence_no":orderId
          }
      data = uz.urlencode(data).encode()
      html = opener.open(zreq,data=data).read().decode()
      result = loads(html)
      print('代码全部过完,回去登录下是否搞定')
      print(result)
      print(result['data']['submitStatus'])
      if result['data']['submitStatus'] == True:
        print('购票成功')
        return True
      else:
        print('购票失败,重试其他列车')
        continue
'''
最终的回执代码详细 信息,读者可以自己尝试多次,得到自己的回复代码确认是否购票成功,因为result['data']['submitStatus']==True只不过是确认订单状态而已,这个被我改动过,你可以多次尝试

最后的最后,火车票预订成功只有30分钟支付时间,所以我为了防止订好票但是我人不在,特意写了qq邮件通知

qq邮件通知:

def email():#这是我订票后给自己发邮件的函数
  import smtplib
  from email.mime.text import MIMEText
  import time
  text = '已经为%s抢到票,速度登录12306付款,用户名:%s,密码:%s'%(NAME,username,password)
  msg = MIMEText(text, 'plain', 'utf-8')
  msg_From = '2059****16@qq.com'
  msg_To = '5043****75@qq.com'#是的,我有两个qq,一个发一个收
  smtpSever = 'smtp.qq.com' # qq邮箱的smtp Sever地址
  smtpPort = '465' # 开放的端口
  sqm = 'q********eghe' # 在登录smtp时需要login中的密码应当使用授权码而非账户密码
  msg['from'] = msg_From
  msg['to'] = msg_To
  msg['subject'] = 'Python自动邮件-%s' % time.ctime()
  smtp = smtplib
  smtp = smtplib.SMTP_SSL()
  '''
  smtplib的connect(连接到邮件服务器)、login(登陆验证)、sendmail(发送邮件)
  '''
  smtp.connect(smtpSever, smtpPort)
  smtp.login(msg_From, sqm)
  smtp.sendmail(msg_From, msg_To, str(msg))
  # s = smtplib.SMTP("localhost")
  # s.send_message(msg)
  smtp.quit()
  print('邮件已发送~你可以安心去玩了')
def emailforcode():#此函数是防止查询有票但12306账号掉线人不在无法订票的提醒
  import smtplib
  from email.mime.text import MIMEText
  import time
  text = '%s账号下线,速度登录验证12306' % NAME
  msg = MIMEText(text, 'plain', 'utf-8')
  msg_From = '205****516@qq.com'
  msg_To = '50****75@qq.com'
  smtpSever = 'smtp.qq.com' # qq邮箱的smtp Sever地址
  smtpPort = '465' # 开放的端口
  sqm = 'qowa*******ghe' # 在登录smtp时需要login中的密码应当使用授权码而非账户密码
  msg['from'] = msg_From
  msg['to'] = msg_To
  msg['subject'] = 'Python自动邮件-%s' % time.ctime()
  smtp = smtplib
  smtp = smtplib.SMTP_SSL()
  '''
  smtplib的connect(连接到邮件服务器)、login(登陆验证)、sendmail(发送邮件)
  '''
  smtp.connect(smtpSever, smtpPort)
  smtp.login(msg_From, sqm)
  smtp.sendmail(msg_From, msg_To, str(msg))
  # s = smtplib.SMTP("localhost")
  # s.send_message(msg)
  smtp.quit()
  print('邮件已发送~')

如此就大功告成了。

不能发完整的代码(本身目的就是为了技术交流而已,防止懒人盗码乱搞),但是我相信各位开发中的朋友们只要有逻辑,有开头,只要自己肯动手,都可以自己钻研出来,举一反三。毕竟我就是这样搞出来的,我从来都相信,只要肯学,都会学会,只要肯做,都可以做成。

总结

以上所述是小编给大家介绍的python实现12306抢票及自动邮件发送提醒付款功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Python 相关文章推荐
粗略分析Python中的内存泄漏
Apr 23 Python
Android应用开发中Action bar编写的入门教程
Feb 26 Python
利用Python抓取行政区划码的方法
Nov 28 Python
如何用itertools解决无序排列组合的问题
May 18 Python
Python使用文件锁实现进程间同步功能【基于fcntl模块】
Oct 16 Python
用Python登录好友QQ空间点赞的示例代码
Nov 04 Python
python实现数据写入excel表格
Mar 25 Python
解决python3捕获cx_oracle抛出的异常错误问题
Oct 18 Python
OpenCV图像颜色反转算法详解
May 13 Python
python Django编写接口并用Jmeter测试的方法
Jul 31 Python
Python使用matplotlib 画矩形的三种方式分析
Oct 31 Python
5 分钟读懂Python 中的 Hook 钩子函数
Dec 09 Python
TensorFlow模型保存/载入的两种方法
Mar 08 #Python
python2.7 json 转换日期的处理的示例
Mar 07 #Python
教你用Python创建微信聊天机器人
Mar 31 #Python
为什么入门大数据选择Python而不是Java?
Mar 07 #Python
详解Python中如何写控制台进度条的整理
Mar 07 #Python
python爬虫爬取网页表格数据
Mar 07 #Python
python使用mysql的两种使用方式
Mar 07 #Python
You might like
从零开始 教你如何搭建Discuz!4.1论坛
2006/07/07 PHP
php中将时间差转换为字符串提示的实现代码
2011/08/08 PHP
支付宝服务窗API接口开发php版本
2016/07/20 PHP
php session_decode函数用法讲解
2019/05/26 PHP
jscript之Open an Excel Spreadsheet
2007/06/13 Javascript
弹出层之1:JQuery.Boxy (一) 使用介绍
2011/10/06 Javascript
js内存泄露的几种情况详细探讨
2013/05/31 Javascript
jQuery实现复选框全选/取消全选/反选及获得选择的值
2014/06/12 Javascript
jquery实现简单的无缝滚动
2015/04/15 Javascript
深入浅出 jQuery中的事件机制
2016/08/23 Javascript
详解微信小程序之scroll-view的flex布局问题
2019/01/16 Javascript
vue计算属性computed的使用方法示例
2019/03/13 Javascript
JS使用H5实现图片预览功能
2019/09/30 Javascript
JS实现滑动插件
2020/01/15 Javascript
彻底搞懂并解决vue-cli4中图片显示的问题实现
2020/08/31 Javascript
[43:24]2018DOTA2亚洲邀请赛3月29日 小组赛A组 LGD VS Liquid
2018/03/30 DOTA
Python 自动安装 Rising 杀毒软件
2009/04/24 Python
对python打乱数据集中X,y标签对的方法详解
2018/12/14 Python
浅谈Python接口对json串的处理方法
2018/12/19 Python
Python3.4学习笔记之类型判断,异常处理,终止程序操作小结
2019/03/01 Python
python提取log文件内容并画出图表
2019/07/08 Python
pycharm工具连接mysql数据库失败问题
2020/04/01 Python
python使用bs4爬取boss直聘静态页面
2020/10/10 Python
Python Sqlalchemy如何实现select for update
2020/10/12 Python
html5拖拽应用记录及注意点
2020/05/27 HTML / CSS
美国最受欢迎的度假租赁网站:VRBO
2016/08/02 全球购物
英国领先的电视购物零售商:Ideal World
2019/03/18 全球购物
养成教育经验材料
2014/05/26 职场文书
运动会加油口号
2014/06/07 职场文书
爱护公物标语
2014/06/24 职场文书
倡议书的写法
2014/08/30 职场文书
纪念九一八事变演讲稿:忘记意味着背叛
2014/09/14 职场文书
简易离婚协议书(范本)
2014/10/25 职场文书
社会实践活动总结
2015/02/05 职场文书
Vue实现动态查询规则生成组件
2021/05/27 Vue.js
Python 键盘事件详解
2021/11/11 Python