提交 6b849c12 编写于 作者: W wenxianping

优化代码结构

新增双下单方法
修复一直bug
上级 009b989a
......@@ -2,10 +2,11 @@
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Python 2.7.10 (/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7)" jdkType="Python SDK" />
<orderEntry type="jdk" jdkName="Python 2.7 (qt12306)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="TestRunnerService">
<option name="PROJECT_TEST_RUNNER" value="Unittests" />
<option name="projectConfiguration" value="Nosetests" />
<option name="PROJECT_TEST_RUNNER" value="Nosetests" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Python 2.7.10 (/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="TestRunnerService">
<option name="PROJECT_TEST_RUNNER" value="Unittests" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectCodeStyleSettingsManager">
<option name="PER_PROJECT_SETTINGS">
<value>
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
<MarkdownNavigatorCodeStyleSettings>
<option name="RIGHT_MARGIN" value="72" />
</MarkdownNavigatorCodeStyleSettings>
</value>
</option>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</component>
</project>
\ No newline at end of file
<component name="ProjectDictionaryState">
<dictionary name="wenxianping" />
</component>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="InconsistentLineSeparators" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="LongLine" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ProblematicWhitespace" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="SSBasedInspection" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="TodoComment" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredPackages">
<value>
<list size="11">
<item index="0" class="java.lang.String" itemvalue="nose" />
<item index="1" class="java.lang.String" itemvalue="locust" />
<item index="2" class="java.lang.String" itemvalue="selenium" />
<item index="3" class="java.lang.String" itemvalue="locustio" />
<item index="4" class="java.lang.String" itemvalue="pymssql" />
<item index="5" class="java.lang.String" itemvalue="python-hessian" />
<item index="6" class="java.lang.String" itemvalue="suds" />
<item index="7" class="java.lang.String" itemvalue="DBUtils" />
<item index="8" class="java.lang.String" itemvalue="MySQL-python" />
<item index="9" class="java.lang.String" itemvalue="redis" />
<item index="10" class="java.lang.String" itemvalue="redis_py_cluster" />
</list>
</value>
</option>
</inspection_tool>
<inspection_tool class="PyPep8Inspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="ignoredErrors">
<list>
<option value="E501" />
</list>
</option>
</inspection_tool>
<inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="ignoredErrors">
<list>
<option value="N801" />
<option value="N803" />
<option value="N806" />
<option value="N802" />
</list>
</option>
</inspection_tool>
<inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredIdentifiers">
<list>
<option value="list.__setitem__" />
<option value="dict.json" />
</list>
</option>
</inspection_tool>
</profile>
</component>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<settings>
<option name="useProjectProfile" value="false" />
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 2.7.10 (/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7)" project-jdk-type="Python SDK" />
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 2.7 (qt12306)" project-jdk-type="Python SDK" />
</project>
\ No newline at end of file
此差异已折叠。
### 12306
#### 12306 购票小助手
- python版本支持
- 2.7
- 2.7.10 - 2.7.15
- 依赖库
- 依赖打码兔 需要去打码兔注册(用户)账号,打码兔账号地址:http://www.dama2.com, 一般充值1元就够用了,充值打码兔之后,首次运行是需要到官网黑白名单授权
- 依赖若快 若快注册地址:http://www.ruokuai.com/client/index?6726 推荐用若快,打码兔在12306验证码更新之后识别率不是很高
- 依赖若快 若快注册地址:http://www.ruokuai.com/client/index?6726 推荐用若快,打码兔平台已经关闭
- 项目依赖包 requirements.txt
- 安装方法 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
- 项目使用说明
- 需要配置邮箱,可以配置可以不配置,配置邮箱的格式在yaml里面可以看到ex
- 提交订单验证码哪里依赖打码兔,所以如果是订票遇到验证码的时候,没有打码兔是过不了的,不推荐手动,手动太慢
- 配置yaml文件的时候,需注意空格和遵循yaml语法格式,项目的yaml配置ex:
- ticket_config.yaml 配置说明
```
#station_date:出发日期改为多日期查询,格式ex:
- "2018-02-03"
- "2018-02-04"
- "2018-02-05"
#station_trains:过滤车次,格式ex:
# - "G1353"
# - "G1329"
# - "G1355"
# - "G1303"
# - "G1357"
# - "G1305"
# - "G1359"
# - "G1361"
# - "G1373"
# - "G1363"
#from_station: 始发站
#to_station: 到达站
#set_type: 坐席(商务座,二等座,特等座,软卧,硬卧,硬座,无座)
#is_more_ticket:余票不足是否自动提交
#select_refresh_interval:抢票刷新间隔时间,1为一秒,0.1为100毫秒,以此类推 如果捡漏推荐为1秒,刷票设置0.01
#expect_refresh_interval:售票未开始,等待刷新间隔时间,1为一秒,0.1为100毫秒,以此类推
#ticket_black_list:加入小黑屋的等待时间,默认3 min 小黑屋的功能是上次买票失败,证明此票已无机会,下次刷新看到此票跳过
#enable_proxy:是否开启代理模式,代理速度比较慢,如果是抢票阶段,不建议开启
#ticke_peoples: 乘客 ex: "张三"
#damatu:打码兔账号,用于自动登录和订单自动打码
#is_aotu_code是否自动打码,如果选择Ture,则调用打码兔打码,默认不使用打码兔
#is_email: 是否需要邮件通知 ex: True or False 切记,邮箱加完一定到config目录下测试emailConf功能是否正常
#邮箱配置 列举163
# email: "xxx@163.com"
# notice_email_list: "123@qq.com"
# username: "xxxxx"
# password: "xxxxx
# host: "smtp.163.com"
#邮箱配置 列举qq ,qq设置比较复杂,需要在邮箱--账户--开启smtp服务,取得授权码==邮箱登录密码
# email: "xxx@qq.com"
# notice_email_list: "123@qq.com"
# username: "xxxxx"
# password: "授权码"
# host: "smtp.qq.com"
```
- 配置yaml文件的时候,需注意空格和遵循yaml语法格式
- 项目开始
- 修改config/ticket_config.yaml文件,按照提示更改自己想要的信息
......@@ -94,118 +50,6 @@
恭喜您订票成功,订单号为:EB52743573, 请立即打开浏览器登录12306,访问‘未完成订单’,在30分钟内完成支付!
```
- 2017.5.13跟新
- 增加登陆错误判断(密码错误&ip校验)
- 修改queryOrderWaitTime,校验orderId字段bug,校验msg字段bug,校验messagesbug
- 修改checkQueueOrder 校验 data 字段的列表推导式bug
- 增加代理ip方法,目前已可以过滤有用ip
- 2018.1.7 号更新
- 增加自动配置
```
#station_date:出发日期,格式ex:2018-01-06
#from_station: 始发站
#to_station: 到达站
#set_type: 坐席(商务座,二等座,特等座,软卧,硬卧,硬座,无座)
#is_more_ticket:余票不足是否自动提交
#select_refresh_interval:刷新间隔时间,1为一秒,0.1为100毫秒,以此类推
#ticke_peoples: 乘客
#damatu:打码图账号,用于自动登录
```
- 优化订票流程
- 支持自动刷票,自动订票
- 2018.1.8 更新
- 增加小黑屋功能
- 修复bug若干
- 增加多账号同时订票功能
- 增加按照选定车次筛选购买车次
- 2018.1.9 更新
- 增加手动打码,只是登录接口,完全不用担心提交票的效率问题,要挂linux系统的话,还是去注册个打码兔吧
```
思路
1.调用PIL显示图片
2.图片位置说明,验证码图片中每个图片代表一个下标,依次类推,1,2,3,4,5,6,7,8
3.控制台输入对应下标,按照英文逗号分开,即可手动完成打码,
```
- 修改无座和硬座的座位号提交是个字符串的问题
- 增加校验下单需要验证码功能
- 增强下单成功判断接口校验
- 2018.1.10 更新
- 优化查票流程
- 修改二等座的余票数返回为字符串的问题
- 优化订单查询bug
- 2018.1.12更新
- 优化抢票页面逻辑
-增强代码稳定性
- 2018.1.13更新
- 修改下单验证码功能
- 优化大量调用user接口导致联系人不能用,理论加快订票速度
- 增加邮箱功能
```
#is_email: 是否需要邮件通知 ex: True or False 切记,邮箱加完一定要到config目录下测试emailConf功能是否正常
#email: 发送的邮箱地址 ex: 1@qq.com
#notice_email_list: 被通知人邮箱 ex: 2@qq.com
#username: 邮箱账号
#password: 邮箱密码
#host: 邮箱地址
```
- 2018.1.14更新
- 优化订票流程
- 优化挂机功能
- 修改之前程序到11点自动跳出功能,现在修改为到早上7点自动开启刷票
- 需要开启打码兔代码功能,is_aotu_code 设置为True
- 增加异常判断
- 2018.1.15更新
- 增加捡漏自动检测是否登录功能,建议捡漏不要刷新太快,2S最好,否则会封IP
- 优化提交订单有很大记录无限排队的情况,感谢群里的小伙伴提供的思路
- 修改休眠时间为早上6点
- 2018.1.20更新,好久没跟新了,群里的小伙伴说登录不行了,今晚抽空改了一版登录,妥妥的
- 更新新版登录功能,经测试,更稳定有高效
- 优化手动打码功能
- 更新请求第三方库
- 优化若干代码,小伙伴尽情的放肆起来
- 2018.1.21跟新
- 修复若干bug
- 合并dev
- 恢复之前因为12306改版引起的订票功能
- 增加派对失败自动取消订单功能
- 优化接口请求规范
- 增加多日期查询,请严格按照yaml格式添加 即可
- 注意:如果多日期查询的话,可能查询时间会比较长
- 增加如果排队时间超过一分钟,自动取消订单
- 2018.1.23更新
- 增加若快平台打码,yaml新增字段aotu_code_type,1=打码兔,2=若快 若快注册地址:http://www.ruokuai.com/client/index?6726
- 修改is_aotu_code字段为全部是否自动打码字段,也就是说字段为rue,则全部自动打码,为False全部手动打码,包括提交订单,注意centOs不可设置手动打码
- 修复bug
- 优化抢票功能
- 2018.1.25更新
- 删除 expect_refresh_interval 无用字段,优化代码
- 2018.1.29更新
- 增加cdn轮训功能,优势, is_cdn=1为开启cdn,2为普通查询
- 能够一定程度躲避封ip
- 查询余票快人一步
- 提交订单快人一步
- 僵尸票可能会少很多
- 兼容Windows cmd命令乱码问题
- 规范12306接口提交参数
- 修改已知bug
- 最后感谢群里提供测试和代码的小伙伴,能为你们买到一张回家的票真的感到灰常开心
- 2018.2.28更新,收12306风控影响,代码可能有时候会进入慢排队,请自行调整刷新参数
- 修改已知bug
- 优化接口提交参数规范
- [更新日志](Update.md)
- 2017.5.13跟新
- 增加登陆错误判断(密码错误&ip校验)
- 修改queryOrderWaitTime,校验orderId字段bug,校验msg字段bug,校验messagesbug
- 修改checkQueueOrder 校验 data 字段的列表推导式bug
- 增加代理ip方法,目前已可以过滤有用ip
- 2018.1.7 号更新
- 增加自动配置
```
#station_date:出发日期,格式ex:2018-01-06
#from_station: 始发站
#to_station: 到达站
#set_type: 坐席(商务座,二等座,特等座,软卧,硬卧,硬座,无座)
#is_more_ticket:余票不足是否自动提交
#select_refresh_interval:刷新间隔时间,1为一秒,0.1为100毫秒,以此类推
#ticke_peoples: 乘客
#damatu:打码图账号,用于自动登录
```
- 优化订票流程
- 支持自动刷票,自动订票
- 2018.1.8 更新
- 增加小黑屋功能
- 修复bug若干
- 增加多账号同时订票功能
- 增加按照选定车次筛选购买车次
- 2018.1.9 更新
- 增加手动打码,只是登录接口,完全不用担心提交票的效率问题,要挂linux系统的话,还是去注册个打码兔吧
```
思路
1.调用PIL显示图片
2.图片位置说明,验证码图片中每个图片代表一个下标,依次类推,1,2,3,4,5,6,7,8
3.控制台输入对应下标,按照英文逗号分开,即可手动完成打码,
```
- 修改无座和硬座的座位号提交是个字符串的问题
- 增加校验下单需要验证码功能
- 增强下单成功判断接口校验
- 2018.1.10 更新
- 优化查票流程
- 修改二等座的余票数返回为字符串的问题
- 优化订单查询bug
- 2018.1.12更新
- 优化抢票页面逻辑
-增强代码稳定性
- 2018.1.13更新
- 修改下单验证码功能
- 优化大量调用user接口导致联系人不能用,理论加快订票速度
- 增加邮箱功能
```
#is_email: 是否需要邮件通知 ex: True or False 切记,邮箱加完一定要到config目录下测试emailConf功能是否正常
#email: 发送的邮箱地址 ex: 1@qq.com
#notice_email_list: 被通知人邮箱 ex: 2@qq.com
#username: 邮箱账号
#password: 邮箱密码
#host: 邮箱地址
```
- 2018.1.14更新
- 优化订票流程
- 优化挂机功能
- 修改之前程序到11点自动跳出功能,现在修改为到早上7点自动开启刷票
- 需要开启打码兔代码功能,is_auto_code 设置为True
- 增加异常判断
- 2018.1.15更新
- 增加捡漏自动检测是否登录功能,建议捡漏不要刷新太快,2S最好,否则会封IP
- 优化提交订单有很大记录无限排队的情况,感谢群里的小伙伴提供的思路
- 修改休眠时间为早上6点
- 2018.1.20更新,好久没跟新了,群里的小伙伴说登录不行了,今晚抽空改了一版登录,妥妥的
- 更新新版登录功能,经测试,更稳定有高效
- 优化手动打码功能
- 更新请求第三方库
- 优化若干代码,小伙伴尽情的放肆起来
- 2018.1.21跟新
- 修复若干bug
- 合并dev
- 恢复之前因为12306改版引起的订票功能
- 增加派对失败自动取消订单功能
- 优化接口请求规范
- 增加多日期查询,请严格按照yaml格式添加 即可
- 注意:如果多日期查询的话,可能查询时间会比较长
- 增加如果排队时间超过一分钟,自动取消订单
- 2018.1.23更新
- 增加若快平台打码,yaml新增字段auto_code_type,1=打码兔,2=若快 若快注册地址:http://www.ruokuai.com/client/index?6726
- 修改is_auto_code字段为全部是否自动打码字段,也就是说字段为rue,则全部自动打码,为False全部手动打码,包括提交订单,注意centOs不可设置手动打码
- 修复bug
- 优化抢票功能
- 2018.1.25更新
- 删除 expect_refresh_interval 无用字段,优化代码
- 2018.1.29更新
- 增加cdn轮训功能,优势, is_cdn=1为开启cdn,2为普通查询
- 能够一定程度躲避封ip
- 查询余票快人一步
- 提交订单快人一步
- 僵尸票可能会少很多
- 兼容Windows cmd命令乱码问题
- 规范12306接口提交参数
- 修改已知bug
- 最后感谢群里提供测试和代码的小伙伴,能为你们买到一张回家的票真的感到灰常开心
- 2018.2.28更新,收12306风控影响,代码可能有时候会进入慢排队,请自行调整刷新参数
- 修改已知bug
- 优化接口提交参数规范
- 2018.8.29更新,解决慢排队问题,增加双订票接口
- 修改已知bug
- 优化代码结构
- 新增第三方库wrapcache,需要重新安装requirements.txt
\ No newline at end of file
......@@ -33,3 +33,8 @@ class ticket(object):
CANCEL_ORDER_SUCCESS = u"排队超时,已为您自动取消订单,订单编号: {0}"
CANCEL_ORDER_FAIL = u"排队超时,取消订单失败, 订单号{0}"
REST_TIME = u"12306休息时间,本程序自动停止,明天早上6点将自动运行"
REST_TIME_PAST = u"休息时间已过,重新开启检票功能"
LOGIN_SESSION_FAIL = u"用户检查失败:{0},可能未登录,可能session已经失效, 正在重新登录中"
......@@ -13,19 +13,4 @@ def _get_yaml():
f = open(path)
s = yaml.load(f)
f.close()
return s
# def get_set_info():
# return _get_yaml()["set"]
#
#
# def get_ticke_peoples():
# return _get_yaml()["ticke_peoples"]
#
#
# def get_damatu():
# return _get_yaml()["damatu"]
#
#
# print _get_yaml()["set"]["12306count"]
\ No newline at end of file
return s
\ No newline at end of file
---
#station_date:出发日期,格式ex:2018-01-06
#station_trains:过滤车次,格式ex:
# - "G1353"
# - "G1329"
# - "G1355"
# - "G1303"
# - "G1357"
# - "G1305"
# - "G1359"
# - "G1361"
# - "G1373"
# - "G1363"
#from_station: 始发站
#to_station: 到达站
#set_type: 坐席(商务座,二等座,特等座,软卧,硬卧,硬座,无座)
#is_more_ticket:余票不足是否自动提交
#select_refresh_interval:抢票刷新间隔时间,1为一秒,0.1为100毫秒,以此类推 如果捡漏推荐为1秒,刷票设置0.01
#expect_refresh_interval:售票未开始,等待刷新间隔时间,1为一秒,0.1为100毫秒,以此类推
#ticket_black_list:加入小黑屋的等待时间,默认3 min
#enable_proxy:是否开启代理模式,代理速度比较慢,如果是抢票阶段,不建议开启
#ticke_peoples: 乘客
#damatu:打码兔账号,用于自动登录
#is_aotu_code是否自动打码,如果选择Ture,则调用打码兔打码,默认不使用打码兔
#aotu_code_type 1为打码兔,2为若快
#is_email: 是否需要邮件通知 ex: True or False 切记,邮箱加完一定到config目录下测试emailConf功能是否正常
#邮箱配置 列举163
# email: "xxx@163.com"
# notice_email_list: "123@qq.com"
# username: "xxxxx"
# password: "xxxxx
# host: "smtp.163.com"
#邮箱配置 列举qq ,qq设置比较复杂,需要在邮箱--账户--开启smtp服务,取得授权码==邮箱登录密码
# email: "xxx@qq.com"
# notice_email_list: "123@qq.com"
# username: "xxxxx"
# password: "授权码"
# host: "smtp.qq.com"
set:
# 出发日期,格式ex:2018-01-06
station_dates:
- "2018-06-21"
- "2018-06-22"
- "2018-09-05"
# 过滤车次,格式ex:- "G1353" - "G1329"
station_trains:
- "G1321"
- "G6504"
from_station: "上海"
to_station: "长沙"
# 出发城市,比如深圳北,就填深圳就搜得到
from_station: "深圳"
# 到达城市 比如深圳北,就填深圳就搜得到
to_station: "广州"
# 座位 多个座位ex: - "二等座" - "一等座"
set_type:
- "二等座"
- "商务座"
- "一等座"
# 余票不足是否自动提交,目前应该没什么卵用
is_more_ticket: True
# 乘车人 多个乘车人ex: - "张三" - "李四"
ticke_peoples:
- "文贤平"
# - "彭淑杰"
12306count:
# - uesr: ""
# - pwd: "apple1995"
- uesr: "931128603@qq.com"
- pwd: "QWERTY"
- ""
# 12306登录账号
12306account:
- uesr: ""
- pwd: ""
select_refresh_interval: 1
# 加入小黑屋时间,此功能为了防止僵尸票导致一直下单不成功错过正常的票
ticket_black_list_time: 5
is_aotu_code: False
aotu_code_type: 2
#enable_proxy: False
damatu:
# 自动打码
is_auto_code: False
# 打码平台, 2 为若快平台(目前只支持若快平台打码,打码兔已经关闭), 若快注册地址:http://www.ruokuai.com/client/index?6726
auto_code_type: 2
# 打码平台账号
auto_code_account:
uesr: ""
pwd: "qazWSX1995"
pwd: ""
# 邮箱配置,如果抢票成功,将通过邮件配置通知给您
# 列举163
# email: "xxx@163.com"
# notice_email_list: "123@qq.com"
# username: "xxxxx"
# password: "xxxxx
# host: "smtp.163.com"
# 列举qq ,qq设置比较复杂,需要在邮箱-->账户-->开启smtp服务,取得授权码==邮箱登录密码
# email: "xxx@qq.com"
# notice_email_list: "123@qq.com"
# username: "xxxxx"
# password: "授权码"
# host: "smtp.qq.com"
email_conf:
is_email: True
email: "@qq.com "
......@@ -81,8 +66,11 @@ email_conf:
password: ""
host: "smtp.qq.com"
# 是否开启cdn查询,可以更快的检测飘飘 1为开启,2为关闭
is_cdn: 2
# 下单接口分为两种,1 为快速下单,2 是普通下单
order_type: 1
......@@ -71,7 +71,7 @@ urls = {
"req_type": "get",
"Referer": "https://kyfw.12306.cn/otn/index/init",
"Host": "kyfw.12306.cn",
"re_try": 10,
"re_try": 1,
"re_time": 0.1,
"s_time": 0.1,
"is_logger": False,
......@@ -157,7 +157,7 @@ urls = {
},
"select_url": { # 查询余票
"req_url": "/otn/leftTicket/query?leftTicketDTO.train_date={0}&leftTicketDTO.from_station={1}&leftTicketDTO.to_station={2}&purpose_codes=ADULT",
"req_type": "post",
"req_type": "get",
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
"Host": "kyfw.12306.cn",
"re_try": 10,
......
# -*- coding=utf-8 -*-
import datetime
import json
import random
import re
import socket
import sys
import threading
import time
import urllib
from collections import OrderedDict
import collections
from agency.cdn_utils import CDNProxy
from config import urlConf
from config.TicketEnmu import ticket
from config.emailConf import sendEmail
from config.ticketConf import _get_yaml
from init import login
from init.login import GoLogin
from inter.AutoSubmitOrderRequest import autoSubmitOrderRequest
from inter.ConfirmSingleForQueueAsys import confirmSingleForQueueAsys
from inter.GetPassengerDTOs import getPassengerDTOs
from inter.GetQueueCountAsync import getQueueCountAsync
from inter.LiftTicketInit import liftTicketInit
from inter.Query import query
from inter.QueryOrderWaitTime import queryOrderWaitTime
from myException.PassengerUserException import PassengerUserException
from myException.UserPasswordException import UserPasswordException
from myException.ticketConfigException import ticketConfigException
from myException.ticketIsExitsException import ticketIsExitsException
from myException.ticketNumOutException import ticketNumOutException
from myUrllib.httpUtils import HTTPClient
reload(sys)
sys.setdefaultencoding('utf-8')
class selectFast:
"""
快速提交车票通道
"""
def __init__(self):
self.from_station, self.to_station, self.station_dates, self._station_seat, self.is_more_ticket, self.ticke_peoples, self.select_refresh_interval, self.station_trains, self.ticket_black_list_time = self.get_ticket_info()
self.is_aotu_code = _get_yaml()["is_aotu_code"]
self.aotu_code_type = _get_yaml()["aotu_code_type"]
self.is_cdn = _get_yaml()["is_cdn"]
self.httpClint = HTTPClient()
self.urls = urlConf.urls
self.login = GoLogin(self.httpClint, self.urls, self.is_aotu_code, self.aotu_code_type)
self.is_download_img = False
self.cdn_list = []
self.is_check_user = dict()
self.ticket_black_list = dict()
self.passengerTicketStrList = ""
self.oldPassengerStr = ""
def get_ticket_info(self):
"""
获取配置信息
:return:
"""
ticket_info_config = _get_yaml()
from_station = ticket_info_config["set"]["from_station"].encode("utf8")
to_station = ticket_info_config["set"]["to_station"].encode("utf8")
station_dates = ticket_info_config["set"]["station_dates"]
set_type = ticket_info_config["set"]["set_type"]
is_more_ticket = ticket_info_config["set"]["is_more_ticket"]
ticke_peoples = ticket_info_config["set"]["ticke_peoples"]
select_refresh_interval = ticket_info_config["select_refresh_interval"]
station_trains = ticket_info_config["set"]["station_trains"]
ticket_black_list_time = ticket_info_config["ticket_black_list_time"]
print u"*" * 20
print u"12306刷票小助手,最后更新于2018.2.28,请勿作为商业用途,交流群号:286271084"
print u"如果有好的margin,请联系作者,表示非常感激\n"
print u"当前配置:出发站:{0}\n到达站:{1}\n乘车日期:{2}\n坐席:{3}\n是否有票自动提交:{4}\n乘车人:{5}\n刷新间隔:随机(1-4S)\n候选购买车次:{7}\n僵尸票关小黑屋时长:{8}\n".format \
(
from_station,
to_station,
station_dates,
",".join(set_type),
is_more_ticket,
",".join(ticke_peoples),
select_refresh_interval,
",".join(station_trains),
ticket_black_list_time,
)
print u"*" * 20
return from_station, to_station, station_dates, set_type, is_more_ticket, ticke_peoples, select_refresh_interval, station_trains, ticket_black_list_time
def station_table(self, from_station, to_station):
"""
读取车站信息
:param station:
:return:
"""
result = open('station_name.txt')
info = result.read().split('=')[1].strip("'").split('@')
del info[0]
station_name = {}
for i in range(0, len(info)):
n_info = info[i].split('|')
station_name[n_info[1]] = n_info[2]
from_station = station_name[from_station.encode("utf8")]
to_station = station_name[to_station.encode("utf8")]
return from_station, to_station
def call_login(self, auth=False):
"""
登录回调方法
:return:
"""
if auth:
return self.login.auth()
else:
self.login.go_login()
def check_user(self):
"""
检查用户是否达到订票条件
:return:
"""
check_user_url = self.urls["check_user_url"]
data = {"_json_att": ""}
check_user = self.httpClint.send(check_user_url, data)
check_user_flag = check_user['data']['flag']
if check_user_flag is True:
self.is_check_user["user_time"] = datetime.datetime.now()
else:
if check_user['messages']:
print (u'用户检查失败:%s,可能未登录,可能session已经失效' % check_user['messages'][0])
print (u'正在尝试重新登录')
self.call_login()
self.is_check_user["user_time"] = datetime.datetime.now()
else:
print (u'用户检查失败: %s,可能未登录,可能session已经失效' % check_user)
print (u'正在尝试重新登录')
self.call_login()
self.is_check_user["user_time"] = datetime.datetime.now()
def main(self):
l = liftTicketInit(session=self)
l.reqLiftTicketInit()
self.call_login()
self.check_user()
from_station, to_station = self.station_table(self.from_station, self.to_station)
passengerTicketStrList, oldPassengerStr, set_type = "", "", ""
num = 1
while 1:
try:
num += 1
if "user_time" in self.is_check_user and (
datetime.datetime.now() - self.is_check_user["user_time"]).seconds / 60 > 5:
# 5分钟检查一次用户是否登录
self.check_user()
time.sleep(self.select_refresh_interval)
if time.strftime('%H:%M:%S', time.localtime(time.time())) > "23:00:00" or time.strftime('%H:%M:%S',
time.localtime(
time.time())) < "06:00:00":
print(u"12306休息时间,本程序自动停止,明天早上6点将自动运行")
while 1:
time.sleep(1)
if "06:00:00" < time.strftime('%H:%M:%S', time.localtime(time.time())) < "23:00:00":
print(u"休息时间已过,重新开启检票功能")
self.call_login()
break
start_time = datetime.datetime.now()
q = query(session=self,
from_station=from_station,
to_station=to_station,
from_station_h=self.from_station,
to_station_h=self.to_station,
_station_seat=self._station_seat,
station_trains=self.station_trains,
station_dates=self.station_dates,)
queryResult = q.sendQuery()
# 查询接口
if queryResult.get("status", False):
secretStr = queryResult.get("secretStr", "")
train_no = queryResult.get("train_no", "")
stationTrainCode = queryResult.get("stationTrainCode", "")
train_date = queryResult.get("train_date", "")
query_from_station_name = queryResult.get("query_from_station_name", "")
query_to_station_name = queryResult.get("query_to_station_name", "")
set_type = queryResult.get("set_type", "")
leftTicket = queryResult.get("leftTicket", "")
if self.ticket_black_list.has_key(train_no) and (
datetime.datetime.now() - self.ticket_black_list[train_no]).seconds / 60 < int(
self.ticket_black_list_time):
print(ticket.QUEUE_WARNING_MSG.format(train_no))
else:
# 获取联系人
if not self.passengerTicketStrList and not self.oldPassengerStr:
s = getPassengerDTOs(session=self, ticket_peoples=self.ticke_peoples, set_type=set_type)
getPassengerDTOsResult = s.getPassengerTicketStrListAndOldPassengerStr()
if getPassengerDTOsResult.get("status", False):
self.passengerTicketStrList = getPassengerDTOsResult.get("passengerTicketStrList", "")
self.oldPassengerStr = getPassengerDTOsResult.get("oldPassengerStr", "")
set_type = getPassengerDTOsResult.get("set_type", "")
# 提交订单
a = autoSubmitOrderRequest(session=self,
secretStr=secretStr,
train_date=train_date,
query_from_station_name=self.from_station,
query_to_station_name=self.to_station,
passengerTicketStr=self.passengerTicketStrList,
oldPassengerStr=self.oldPassengerStr
)
submitResult = a.sendAutoSubmitOrderRequest()
if submitResult.get("status", False):
result = submitResult.get("result", "")
# 订单排队
time.sleep(submitResult.get("ifShowPassCodeTime", 1))
g = getQueueCountAsync(session=self,
train_no=train_no,
stationTrainCode=stationTrainCode,
fromStationTelecode=query_from_station_name,
toStationTelecode=query_to_station_name,
leftTicket=leftTicket,
set_type=set_type,
users=len(self.ticke_peoples),
)
getQueueCountAsyncResult = g.sendGetQueueCountAsync()
time.sleep(submitResult.get("ifShowPassCodeTime", 1))
if getQueueCountAsyncResult.get("is_black", False):
black_train_no = getQueueCountAsyncResult.get("train_no", "")
self.ticket_black_list[black_train_no] = datetime.datetime.now()
if getQueueCountAsyncResult.get("status", False):
# 请求订单快读接口
c = confirmSingleForQueueAsys(session=self,
passengerTicketStr=self.passengerTicketStrList,
oldPassengerStr=self.oldPassengerStr,
result=result, )
confirmSingleForQueueAsysResult = c.sendConfirmSingleForQueueAsys()
# 排队
if confirmSingleForQueueAsysResult.get("status", False):
qwt = queryOrderWaitTime(session=self)
qwt.sendQueryOrderWaitTime()
else:
self.httpClint.del_cookies()
else:
s_time = random.randint(0, 4)
time.sleep(s_time)
print u"正在第{0}次查询 随机停留时长:{6} 乘车日期: {1} 车次:{2} 查询无票 cdn轮询IP:{4}当前cdn总数:{5} 总耗时:{3}ms".format(num,
",".join(
self.station_dates),
",".join(
self.station_trains),
(
datetime.datetime.now() - start_time).microseconds / 1000,
self.httpClint.cdn,
len(
self.cdn_list),
s_time)
except PassengerUserException as e:
print e.message
break
except ticketConfigException as e:
print e.message
break
except ticketIsExitsException as e:
print e.message
break
except ticketNumOutException as e:
print e.message
break
except UserPasswordException as e:
print e.message
break
except ValueError as e:
if e.message == "No JSON object could be decoded":
print(u"12306接口无响应,正在重试")
else:
print(e.message)
except KeyError as e:
print(e.message)
# except TypeError as e:
# print(u"12306接口无响应,正在重试 {0}".format(e.message))
except socket.error as e:
print(e.message)
if __name__ == '__main__':
s = selectFast()
s.main()
# a = select('上海', '北京')
# a.main()
#!/bin/env python
# -*- coding=utf-8 -*-
import copy
import random
import json
import re
......@@ -10,118 +11,25 @@ from config.ticketConf import _get_yaml
from PIL import Image
from damatuCode.damatuWeb import DamatuApi
from damatuCode.ruokuai import RClient
from inter.GetPassCodeNewOrderAndLogin import getPassCodeNewOrderAndLogin
from inter.GetRandCode import getRandCode
from myException.UserPasswordException import UserPasswordException
from myException.balanceException import balanceException
from myUrllib import myurllib2
class GoLogin:
def __init__(self, httpClint, urlConf, is_aotu_code, aotu_code_type):
self.httpClint = httpClint
def __init__(self, session, is_auto_code, auto_code_type):
self.session = session
self.randCode = ""
self.urlConf = urlConf
self.is_aotu_code = is_aotu_code
self.aotu_code_type = aotu_code_type
def cookietp(self):
print(u"正在获取cookie")
url = self.urlConf["loginInit"]
self.httpClint.send(url)
def getRandCode(self):
"""
识别验证码
:return: 坐标
"""
try:
if self.is_aotu_code:
if self.aotu_code_type == 1:
return DamatuApi(_get_yaml()["damatu"]["uesr"], _get_yaml()["damatu"]["pwd"], "./tkcode").main()
elif self.aotu_code_type == 2:
rc = RClient(_get_yaml()["damatu"]["uesr"], _get_yaml()["damatu"]["pwd"])
im = open('./tkcode', 'rb').read()
Result = rc.rk_create(im, 6113)
if "Result" in Result:
return self.codexy(Ofset=",".join(list(Result["Result"])), is_raw_input=False)
else:
if "Error" in Result and Result["Error"]:
print Result["Error"]
return ""
else:
img = Image.open('./tkcode')
img.show()
return self.codexy()
except:
pass
def readImg(self, code_url):
"""
增加手动打码,只是登录接口,完全不用担心提交订单效率
思路
1.调用PIL显示图片
2.图片位置说明,验证码图片中每个图片代表一个下标,依次类推,1,2,3,4,5,6,7,8
3.控制台输入对应下标,按照英文逗号分开,即可手动完成打码,
:return:
"""
print (u"下载验证码...")
codeimgUrl = code_url
img_path = './tkcode'
result = self.httpClint.send(codeimgUrl)
try:
print(u"下载验证码成功")
open(img_path, 'wb').write(result)
except OSError as e:
print (e)
def codexy(self, Ofset=None, is_raw_input=True):
"""
获取验证码
:return: str
"""
if is_raw_input:
Ofset = raw_input(u"请输入验证码: ")
select = Ofset.split(',')
post = []
offsetsX = 0 # 选择的答案的left值,通过浏览器点击8个小图的中点得到的,这样基本没问题
offsetsY = 0 # 选择的答案的top值
for ofset in select:
if ofset == '1':
offsetsY = 46
offsetsX = 42
elif ofset == '2':
offsetsY = 46
offsetsX = 105
elif ofset == '3':
offsetsY = 45
offsetsX = 184
elif ofset == '4':
offsetsY = 48
offsetsX = 256
elif ofset == '5':
offsetsY = 36
offsetsX = 117
elif ofset == '6':
offsetsY = 112
offsetsX = 115
elif ofset == '7':
offsetsY = 114
offsetsX = 181
elif ofset == '8':
offsetsY = 111
offsetsX = 252
else:
pass
post.append(offsetsX)
post.append(offsetsY)
randCode = str(post).replace(']', '').replace('[', '').replace("'", '').replace(' ', '')
print(u"验证码识别坐标为{0}".format(randCode))
return randCode
self.is_auto_code = is_auto_code
self.auto_code_type = auto_code_type
def auth(self):
"""认证"""
authUrl = self.urlConf["auth"]
authUrl = self.session.urls["auth"]
authData = {"appid": "otn"}
tk = self.httpClint.send(authUrl, authData)
tk = self.session.httpClint.send(authUrl, authData)
return tk
def codeCheck(self):
......@@ -129,13 +37,13 @@ class GoLogin:
验证码校验
:return:
"""
codeCheck = self.urlConf["codeCheck"]
codeCheck = self.session.urls["codeCheck"]
codeCheckData = {
"answer": self.randCode,
"rand": "sjrand",
"login_site": "E"
}
fresult = self.httpClint.send(codeCheck, codeCheckData)
fresult = self.session.httpClint.send(codeCheck, codeCheckData)
if "result_code" in fresult and fresult["result_code"] == "4":
print (u"验证码通过,开始登录..")
return True
......@@ -143,7 +51,7 @@ class GoLogin:
if "result_message" in fresult:
print(fresult["result_message"])
sleep(1)
self.httpClint.del_cookies()
self.session.httpClint.del_cookies()
def baseLogin(self, user, passwd):
"""
......@@ -152,13 +60,13 @@ class GoLogin:
:param passwd:
:return: 权限校验码
"""
logurl = self.urlConf["login"]
logurl = self.session.urls["login"]
logData = {
"username": user,
"password": passwd,
"appid": "otn"
}
tresult = self.httpClint.send(logurl, logData)
tresult = self.session.httpClint.send(logurl, logData)
if 'result_code' in tresult and tresult["result_code"] == 0:
print (u"登录成功")
tk = self.auth()
......@@ -185,9 +93,9 @@ class GoLogin:
if not uamtk:
return u"权限校验码不能为空"
else:
uamauthclientUrl = self.urlConf["uamauthclient"]
uamauthclientUrl = self.session.urls["uamauthclient"]
data = {"tk": uamtk}
uamauthclientResult = self.httpClint.send(uamauthclientUrl, data)
uamauthclientResult = self.session.httpClint.send(uamauthclientUrl, data)
if uamauthclientResult:
if "result_code" in uamauthclientResult and uamauthclientResult["result_code"] == 0:
print(u"欢迎 {} 登录".format(uamauthclientResult["username"]))
......@@ -195,9 +103,9 @@ class GoLogin:
else:
return False
else:
self.httpClint.send(uamauthclientUrl, data)
url = self.urlConf["getUserInfo"]
self.httpClint.send(url)
self.session.httpClint.send(uamauthclientUrl, data)
url = self.session.urls["getUserInfo"]
self.session.httpClint.send(url)
def go_login(self):
"""
......@@ -206,27 +114,17 @@ class GoLogin:
:param passwd: 密码
:return:
"""
if self.is_aotu_code and self.aotu_code_type == 1:
balance = DamatuApi(_get_yaml()["damatu"]["uesr"], _get_yaml()["damatu"]["pwd"]).getBalance()
if self.is_auto_code and self.auto_code_type == 1:
balance = DamatuApi(_get_yaml()["auto_code_account"]["uesr"], _get_yaml()["auto_code_account"]["pwd"]).getBalance()
if int(balance) < 40:
raise balanceException(u'余额不足,当前余额为: {}'.format(balance))
user, passwd = _get_yaml()["set"]["12306count"][0]["uesr"], _get_yaml()["set"]["12306count"][1]["pwd"]
user, passwd = _get_yaml()["set"]["12306acount"][0]["uesr"], _get_yaml()["set"]["12306account"][1]["pwd"]
if not user or not passwd:
raise UserPasswordException(u"温馨提示: 用户名或者密码为空,请仔细检查")
login_num = 0
while True:
self.cookietp()
# self.httpClint.set_cookies(_jc_save_showIns="true",
# _jc_save_wfdc_flag="dc",
# _jc_save_toDate="2018-06-06",
# _jc_save_fromDate=_get_yaml()["set"]["station_dates"][0],
# RAIL_EXPIRATION="1528337042724",
# RAIL_DEVICEID="O6DFHLmFChFrZUI7QyY9xcqj94eZG9JH_kD3zSZt53tkCUq0uqdvlo1fm_CmNxr_QAnMOU79JmHI8jbtj2vaNUnOZKCqcsMNbhCaoDIB3vxgsyzMMGOZF-CknXKEFaCLPGyDNXEknPDs7xgSbanwKqsiSRT41xti",
#
# )
self.urlConf["getCodeImg"]["req_url"] = self.urlConf["getCodeImg"]["req_url"].format(random.random())
self.readImg(self.urlConf["getCodeImg"])
self.randCode = self.getRandCode()
getPassCodeNewOrderAndLogin(session=self.session, imgType="login")
self.randCode = getRandCode(self.is_auto_code, self.auto_code_type)
login_num += 1
self.auth()
if self.codeCheck():
......
此差异已折叠。
......@@ -3,6 +3,10 @@ import urllib
from collections import OrderedDict
from config.TicketEnmu import ticket
from config.ticketConf import _get_yaml
from inter.CheckRandCodeAnsyn import checkRandCodeAnsyn
from inter.GetQueueCountAsync import getQueueCountAsync
from inter.GetRandCode import getRandCode
class autoSubmitOrderRequest:
......@@ -15,7 +19,11 @@ class autoSubmitOrderRequest:
query_from_station_name,
query_to_station_name,
passengerTicketStr,
oldPassengerStr):
oldPassengerStr,
train_no,
stationTrainCode,
leftTicket,
set_type,):
self.secretStr = urllib.unquote(secretStr)
self.train_date = train_date
self.query_from_station_name = query_from_station_name
......@@ -23,6 +31,10 @@ class autoSubmitOrderRequest:
self.passengerTicketStr = passengerTicketStr
self.oldPassengerStr = oldPassengerStr
self.session = session
self.train_no = train_no
self.stationTrainCode = stationTrainCode
self.leftTicket = leftTicket
self.set_type = set_type
def data_par(self):
"""
......@@ -46,8 +58,8 @@ class autoSubmitOrderRequest:
data["train_date"] = self.train_date
data["tour_flag"] = "dc"
data["purpose_codes"] = "ADULT"
data["query_from_station_name"] = self.query_from_station_name
data["query_to_station_name"] = self.query_to_station_name
data["query_from_station_name"] = self.session.from_station
data["query_to_station_name"] = self.session.to_station
data["cancel_flag"] = 2
data["bed_level_order_num"] = "000000000000000000000000000000"
data["passengerTicketStr"] = self.passengerTicketStr
......@@ -69,40 +81,42 @@ class autoSubmitOrderRequest:
if requestResultData:
result = requestResultData.get("result", "")
ifShowPassCode = requestResultData.get("ifShowPassCode", "N")
ifShowPassCodeTime = int(requestResultData.get("ifShowPassCodeTime", "1000")) / float(1000)
print(ticket.AUTO_SUBMIT_ORDER_REQUEST_C)
g = getQueueCountAsync(session=self.session,
train_no=self.train_no,
stationTrainCode=self.stationTrainCode,
fromStationTelecode=self.query_from_station_name,
toStationTelecode=self.query_to_station_name,
leftTicket=self.leftTicket,
set_type=self.set_type,
users=len(self.session.ticke_peoples),
station_dates=self.train_date,
passengerTicketStr=self.passengerTicketStr,
oldPassengerStr=self.oldPassengerStr,
result=result,
ifShowPassCodeTime=ifShowPassCodeTime,
)
g.sendGetQueueCountAsync()
if ifShowPassCode == "Y": # 如果需要验证码
print(ticket.AUTO_SUBMIT_NEED_CODE)
return {
"result": result,
"ifShowPassCode": ifShowPassCode,
"code": ticket.SUCCESS_CODE,
"ifShowPassCodeTime": requestResultData.get("requestResultData", 2000) / float(1000),
"status": True,
}
else:
print(ticket.AUTO_SUBMIT_NOT_NEED_CODE)
return {
"result": result,
"ifShowPassCode": ifShowPassCode,
"code": ticket.SUCCESS_CODE,
"ifShowPassCodeTime": requestResultData.get("requestResultData", 2000) / float(1000),
"status": True,
}
print(u"需要验证码")
print(u"正在使用自动识别验证码功能")
for i in range(3):
randCode = getRandCode(is_auto_code=True, auto_code_type=_get_yaml()["auto_code_type"])
checkcode = checkRandCodeAnsyn(self.session, randCode, "")
if checkcode == 'TRUE':
print(u"验证码通过,正在提交订单")
data['randCode'] = randCode
break
else:
print (u"验证码有误, {0}次尝试重试".format(i + 1))
print(u"验证码超过限定次数3次,放弃此次订票机会!")
g.sendGetQueueCountAsync()
else:
print(ticket.AUTO_SUBMIT_ORDER_REQUEST_F)
if autoSubmitOrderRequestResult.get("messages", ""):
print(autoSubmitOrderRequestResult.get("messages", ""))
return {
"code": ticket.FAIL_CODE,
"status": False,
}
elif autoSubmitOrderRequestResult.get("validateMessages", ""):
print(autoSubmitOrderRequestResult.get("validateMessages", ""))
return {
"code": ticket.FAIL_CODE,
"status": False,
}
# coding=utf-8
from collections import OrderedDict
from inter.GetQueueCount import getQueueCount
from inter.GetRepeatSubmitToken import getRepeatSubmitToken
class checkOrderInfo:
def __init__(self, session, train_no, set_type, passengerTicketStrList, oldPassengerStr, station_dates, ticket_peoples):
self.train_no = train_no
self.set_type = set_type
self.passengerTicketStrList = passengerTicketStrList
self.oldPassengerStr = oldPassengerStr
self.station_dates = station_dates
self.ticket_peoples = ticket_peoples
self.RepeatSubmitToken = getRepeatSubmitToken(session)
self.getTicketInfoForPassengerForm = self.RepeatSubmitToken.sendGetRepeatSubmitToken()
self.ticketInfoForPassengerForm = self.getTicketInfoForPassengerForm.get("ticketInfoForPassengerForm", "")
self.token = self.getTicketInfoForPassengerForm.get("token", "")
self.session = self.getTicketInfoForPassengerForm.get("session", "")
def data_par(self):
"""
参数结构
:return:
"""
data = OrderedDict()
data['passengerTicketStr'] = self.passengerTicketStrList.rstrip("_{0}".format(self.set_type))
data['oldPassengerStr'] = self.oldPassengerStr
data['REPEAT_SUBMIT_TOKEN'] = self.token
data['randCode'] = ""
data['cancel_flag'] = 2
data['bed_level_order_num'] = "000000000000000000000000000000"
data['tour_flag'] = 'dc'
data['_json_att'] = ""
return data
def sendCheckOrderInfo(self):
"""
检查支付订单,需要提交REPEAT_SUBMIT_TOKEN
passengerTicketStr : 座位编号,0,票类型,乘客名,证件类型,证件号,手机号码,保存常用联系人(Y或N)
oldPassengersStr: 乘客名,证件类型,证件号,乘客类型
:return:
"""
CheckOrderInfoUrls = self.session.urls["checkOrderInfoUrl"]
data = self.data_par()
checkOrderInfoRep = self.session.httpClint.send(CheckOrderInfoUrls, data)
if 'data' in checkOrderInfoRep:
print (u'车票提交通过,正在尝试排队')
ifShowPassCodeTime = int(checkOrderInfoRep["data"]["ifShowPassCodeTime"]) / float(1000)
if "ifShowPassCode" in checkOrderInfoRep["data"] and checkOrderInfoRep["data"]["ifShowPassCode"] == "Y":
is_need_code = True
elif "ifShowPassCode" in checkOrderInfoRep["data"] and checkOrderInfoRep['data']['submitStatus'] is True:
is_need_code = False
else:
is_need_code = False
QueueCount = getQueueCount(self.session,
is_need_code,
ifShowPassCodeTime,
self.set_type,
self.station_dates,
self.train_no,
self.ticket_peoples,
self.ticketInfoForPassengerForm,
self.token,
self.oldPassengerStr,
self.passengerTicketStrList,
)
QueueCount.sendGetQueueCount()
elif "errMsg" in checkOrderInfoRep['data'] and checkOrderInfoRep['data']["errMsg"]:
print checkOrderInfoRep['data']["errMsg"]
elif 'messages' in checkOrderInfoRep and checkOrderInfoRep['messages']:
print (checkOrderInfoRep['messages'][0])
\ No newline at end of file
# coding=utf-8
class checkRandCodeAnsyn:
def __init__(self, session, randCode, token):
self.session = session
self.randCode = randCode
self.token = token
def data_par(self):
"""
:return:
"""
data = {
"randCode": self.randCode,
"rand": "randp",
"_json_att": "",
"REPEAT_SUBMIT_TOKEN": self.token
}
return data
def sendCheckRandCodeAnsyn(self):
"""
下单验证码识别
:return:
"""
checkRandCodeAnsynUrl = self.session.urls["checkRandCodeAnsyn"]
fresult = self.session.httpClint.send(checkRandCodeAnsynUrl, self.data_par()) # 校验验证码是否正确
return fresult['data']['msg']
\ No newline at end of file
# coding=utf-8
import datetime
import wrapcache
from config.TicketEnmu import ticket
class checkUser:
def __init__(self, session):
self.session = session
def sendCheckUser(self):
"""
检查用户登录, 检查间隔为五分钟
:return:
"""
if wrapcache.get("user_time") is None:
check_user_url = self.session.urls["check_user_url"]
data = {"_json_att": ""}
check_user = self.session.httpClint.send(check_user_url, data)
if check_user.get("data", False):
check_user_flag = check_user["data"]["flag"]
if check_user_flag is True:
wrapcache.set("user_time", datetime.datetime.now(), timeout=60 * 5)
else:
if check_user['messages']:
print (ticket.LOGIN_SESSION_FAIL.format(check_user['messages']))
self.session.call_login()
wrapcache.set("user_time", datetime.datetime.now(), timeout=60 * 5)
else:
print (ticket.LOGIN_SESSION_FAIL.format(check_user['messages']))
self.session.call_login()
wrapcache.set("user_time", datetime.datetime.now(), timeout=60 * 5)
\ No newline at end of file
# coding=utf-8
import datetime
import time
from config.ticketConf import _get_yaml
from inter.CheckRandCodeAnsyn import checkRandCodeAnsyn
from inter.GetPassengerDTOs import getPassengerDTOs
from inter.GetRandCode import getRandCode
from inter.QueryOrderWaitTime import queryOrderWaitTime
class confirmSingleForQueue:
def __init__(self, session, ifShowPassCodeTime, is_node_code, token, set_type, ticket_peoples, ticketInfoForPassengerForm,
oldPassengerStr, passengerTicketStrList):
self.session = session
self.ifShowPassCodeTime = ifShowPassCodeTime
self.is_node_code = is_node_code
self.token = token
self.set_type = set_type
self.ticket_peoples = ticket_peoples
self.ticketInfoForPassengerForm = ticketInfoForPassengerForm
self.passengerTicketStrList = passengerTicketStrList
self.oldPassengerStr = oldPassengerStr
def data_par(self):
"""
模拟提交订单是确认按钮,参数获取方法还是get_ticketInfoForPassengerForm 中获取
:return:
"""
if not self.passengerTicketStrList and not self.oldPassengerStr:
s = getPassengerDTOs(session=self.session, ticket_peoples=self.ticket_peoples, set_type=self.set_type)
getPassengerDTOsResult = s.getPassengerTicketStrListAndOldPassengerStr()
if getPassengerDTOsResult.get("status", False):
self.passengerTicketStrList = getPassengerDTOsResult.get("passengerTicketStrList", "")
self.oldPassengerStr = getPassengerDTOsResult.get("oldPassengerStr", "")
data = {
"passengerTicketStr": self.passengerTicketStrList.rstrip("_{0}".format(self.set_type)),
"oldPassengerStr": "".join(self.oldPassengerStr),
"purpose_codes": self.ticketInfoForPassengerForm["purpose_codes"],
"key_check_isChange": self.ticketInfoForPassengerForm["key_check_isChange"],
"leftTicketStr": self.ticketInfoForPassengerForm["leftTicketStr"],
"train_location": self.ticketInfoForPassengerForm["train_location"],
"seatDetailType": "", # 开始需要选择座位,但是目前12306不支持自动选择作为,那这个参数为默认
"roomType": "00", # 好像是根据一个id来判断选中的,两种 第一种是00,第二种是10,但是我在12306的页面没找到该id,目前写死是00,不知道会出什么错
"dwAll": "N",
"whatsSelect": 1,
"_json_at": "",
"randCode": "",
"choose_seats": "",
"REPEAT_SUBMIT_TOKEN": self.token,
}
return data
def sendConfirmSingleForQueue(self):
"""
# 模拟查询当前的列车排队人数的方法
# 返回信息组成的提示字符串
:return:
"""
data = self.data_par()
checkQueueOrderUrl = self.session.urls["checkQueueOrderUrl"]
try:
if self.is_node_code:
print(u"正在使用自动识别验证码功能")
for i in range(3):
randCode = getRandCode(is_auto_code=True, auto_code_type=_get_yaml()["auto_code_type"])
checkcode = checkRandCodeAnsyn(self.session, randCode, self.token)
if checkcode == 'TRUE':
print(u"验证码通过,正在提交订单")
data['randCode'] = randCode
break
else:
print (u"验证码有误, {0}次尝试重试".format(i + 1))
print(u"验证码超过限定次数3次,放弃此次订票机会!")
else:
print(u"不需要验证码")
time.sleep(self.ifShowPassCodeTime)
checkQueueOrderResult = self.session.httpClint.send(checkQueueOrderUrl, data)
if "status" in checkQueueOrderResult and checkQueueOrderResult["status"]:
c_data = checkQueueOrderResult["data"] if "data" in checkQueueOrderResult else {}
if 'submitStatus' in c_data and c_data['submitStatus'] is True:
print(u"提交订单成功!")
qow = queryOrderWaitTime(self.session)
qow.sendQueryOrderWaitTime()
else:
if 'errMsg' in c_data and c_data['errMsg']:
print(u"提交订单失败,{0}".format(c_data['errMsg']))
else:
print(c_data)
print(u'订票失败!很抱歉,请重试提交预订功能!')
elif "messages" in checkQueueOrderResult and checkQueueOrderResult["messages"]:
print(u"提交订单失败,错误信息: " + checkQueueOrderResult["messages"])
else:
print(u"提交订单中,请耐心等待:" + checkQueueOrderResult["message"])
except ValueError:
print(u"接口 {} 无响应".format(checkQueueOrderUrl))
\ No newline at end of file
......@@ -3,6 +3,8 @@ import json
import urllib
from collections import OrderedDict
from inter.QueryOrderWaitTime import queryOrderWaitTime
class confirmSingleForQueueAsys:
"""
......@@ -64,15 +66,7 @@ class confirmSingleForQueueAsys:
if confirmSingleForQueueAsysResult.get("status", False) and confirmSingleForQueueAsysResult.get("data", False):
queueData = confirmSingleForQueueAsysResult.get("data", {})
if queueData.get("submitStatus", False):
return {
"status": True
}
qwt = queryOrderWaitTime(session=self.session)
qwt.sendQueryOrderWaitTime()
else:
print(queueData.get("errMsg", ""))
return {
"status": False
}
else:
return {
"status": False
}
\ No newline at end of file
# coding=utf-8
def getPassCodeNewOrderAndLogin(session, imgType):
"""
下载验证码
:param session:
:param imgType: 下载验证码类型,login=登录验证码,其余为订单验证码
:return:
"""
if imgType == "login":
codeImgUrl = session.urls["getCodeImg"]
else:
codeImgUrl = session.urls["codeImgByOrder"]
print (u"下载验证码...")
img_path = './tkcode'
result = session.httpClint.send(codeImgUrl)
try:
print(u"下载验证码成功")
open(img_path, 'wb').write(result)
except OSError as e:
print (e)
......@@ -56,7 +56,7 @@ class getPassengerDTOs:
"""
获取提交车次人内容格式
passengerTicketStr O,0,1,文贤平,1,43052419950223XXXX,15618715583,N_O,0,1,梁敏,1,43052719920118XXXX,,N
oldPassengerStr 文贤平,1,43052719920118XXXX,1_梁敏,1,43052719920118XXXX,1_
oldPassengerStr 文贤平,1,43052719920118XXXX,1_梁敏,1,43052719920118XXXX,1
:return:
"""
passengerTicketStrList = []
......@@ -89,4 +89,5 @@ class getPassengerDTOs:
"code": ticket.SUCCESS_CODE,
"set_type": set_type,
"status": True,
"user_info": user_info,
}
# coding=utf-8
import datetime
import time
from collections import OrderedDict
import wrapcache
from config.ticketConf import _get_yaml
from inter.ConfirmSingleForQueue import confirmSingleForQueue
def conversion_int(str):
return int(str)
class getQueueCount:
def __init__(self, session, is_need_code, ifShowPassCodeTime, set_type, station_dates, train_no, ticket_peoples,
ticketInfoForPassengerForm, token, oldPassengerStr, passengerTicketStrList):
self.station_dates = station_dates
self.session = session
self.is_need_code = is_need_code
self.ifShowPassCodeTime = ifShowPassCodeTime
self.set_type = set_type
self.train_no = train_no
self.ticket_peoples = ticket_peoples
self.ticket_black_list = {}
self.ticketInfoForPassengerForm = ticketInfoForPassengerForm
self.token = token
self.oldPassengerStr = oldPassengerStr
self.passengerTicketStrList = passengerTicketStrList
def data_par(self):
"""
参数结构
自动提交代码接口-autoSubmitOrderRequest
- 字段说明
- secretStr 车票代码
- train_date 乘车日期
- tour_flag 乘车类型
- purpose_codes 学生还是成人
- query_from_station_name 起始车站
- query_to_station_name 结束车站
- cancel_flag 默认2,我也不知道干嘛的
- bed_level_order_num 000000000000000000000000000000
- passengerTicketStr 乘客乘车代码
- oldPassengerStr 乘客编号代码
:return:
"""
new_train_date = filter(None, str(time.asctime(time.strptime(self.station_dates, "%Y-%m-%d"))).split(" "))
data = OrderedDict()
data['train_date'] = "{0} {1} 0{2} {3} 00:00:00 GMT+0800 (中国标准时间)".format(
new_train_date[0],
new_train_date[1],
new_train_date[2],
new_train_date[4],
),
data['train_no'] = self.ticketInfoForPassengerForm['queryLeftTicketRequestDTO']['train_no'],
data['stationTrainCode'] = self.ticketInfoForPassengerForm['queryLeftTicketRequestDTO'][
'station_train_code'],
data['seatType'] = self.set_type,
data['fromStationTelecode'] = self.ticketInfoForPassengerForm['queryLeftTicketRequestDTO'][
'from_station'],
data['toStationTelecode'] = self.ticketInfoForPassengerForm['queryLeftTicketRequestDTO']['to_station'],
data['leftTicket'] = self.ticketInfoForPassengerForm['leftTicketStr'],
data['purpose_codes'] = self.ticketInfoForPassengerForm['purpose_codes'],
data['train_location'] = self.ticketInfoForPassengerForm['train_location'],
data['REPEAT_SUBMIT_TOKEN'] = self.token,
return data
def sendGetQueueCount(self):
"""
# 模拟查询当前的列车排队人数的方法
# 返回信息组成的提示字符串
:return:
"""
getQueueCountResult = self.session.httpClint.send(self.session.urls["getQueueCountUrl"], self.data_par())
if "status" in getQueueCountResult and getQueueCountResult["status"] is True:
if "countT" in getQueueCountResult["data"]:
ticket = getQueueCountResult["data"]["ticket"]
ticket_split = sum(map(conversion_int, ticket.split(","))) if ticket.find(",") != -1 else ticket
countT = getQueueCountResult["data"]["countT"]
if int(countT) is 0:
if int(ticket_split) < len(self.ticket_peoples):
print(u"当前余票数小于乘车人数,放弃订票")
else:
print(u"排队成功, 当前余票还剩余: {0} 张".format(ticket_split))
csf = confirmSingleForQueue(self.session, self.ifShowPassCodeTime, self.is_need_code, self.token,
self.set_type, self.ticket_peoples, self.ticketInfoForPassengerForm,
self.oldPassengerStr, self.passengerTicketStrList)
csf.sendConfirmSingleForQueue()
else:
print(u"当前排队人数: {1} 当前余票还剩余:{0} 张,继续排队中".format(ticket_split, countT))
else:
print(u"排队发现未知错误{0},将此列车 {1}加入小黑屋".format(getQueueCountResult, self.train_no))
wrapcache.set(key=self.train_no, value=datetime.datetime.now(),
timeout=int(_get_yaml()["ticket_black_list_time"]) * 60)
elif "messages" in getQueueCountResult and getQueueCountResult["messages"]:
print(u"排队异常,错误信息:{0}, 将此列车 {1}加入小黑屋".format(getQueueCountResult["messages"][0], self.train_no))
wrapcache.set(key=self.train_no, value=datetime.datetime.now(), timeout=int(_get_yaml()["ticket_black_list_time"]) * 60)
else:
if "validateMessages" in getQueueCountResult and getQueueCountResult["validateMessages"]:
print(str(getQueueCountResult["validateMessages"]))
wrapcache.set(key=self.train_no, value=datetime.datetime.now(),
timeout=int(_get_yaml()["ticket_black_list_time"]) * 60)
else:
print(u"未知错误 {0}".format("".join(getQueueCountResult)))
# coding=utf-8
import datetime
import time
from collections import OrderedDict
import wrapcache
from config.TicketEnmu import ticket
from config.ticketConf import _get_yaml
from inter.ConfirmSingleForQueueAsys import confirmSingleForQueueAsys
class getQueueCountAsync:
......@@ -17,7 +22,12 @@ class getQueueCountAsync:
toStationTelecode,
leftTicket,
set_type,
users,):
users,
station_dates,
passengerTicketStr,
oldPassengerStr,
result,
ifShowPassCodeTime):
self.train_no = train_no
self.session = session
self.stationTrainCode = stationTrainCode
......@@ -26,6 +36,11 @@ class getQueueCountAsync:
self.set_type = set_type
self.leftTicket = leftTicket
self.users = users
self.station_dates = station_dates
self.passengerTicketStr = passengerTicketStr
self.oldPassengerStr = oldPassengerStr
self.result = result
self.ifShowPassCodeTime=ifShowPassCodeTime
def data_par(self):
"""
......@@ -41,11 +56,15 @@ class getQueueCountAsync:
- _json_att 没啥卵用,还是带上吧
:return:
"""
l_time = time.localtime(time.time())
new_train_date = time.strftime("%b %d %Y %H:%M:%S", l_time)
new_train_date = filter(None, str(time.asctime(time.strptime(self.station_dates, "%Y-%m-%d"))).split(" "))
data = OrderedDict()
# data["train_date"] = "Fri " + str(new_train_date) + " GMT+0800 (CST)"
data["train_date"] = "Fri Jun 21 2018 18:23:54 GMT+0800 (CST)"
data['train_date'] = "{0} {1} {2} {3} 00:00:00 GMT+0800 (中国标准时间)".format(
new_train_date[0],
new_train_date[1],
new_train_date[2],
new_train_date[4],
time.strftime("%H:%M:%S", time.localtime(time.time()))
),
data["train_no"] = self.train_no
data["stationTrainCode"] = self.stationTrainCode
data["seatType"] = self.set_type
......@@ -76,27 +95,27 @@ class getQueueCountAsync:
countT = getQueueCountAsyncResult["data"]["countT"]
if int(countT) is 0:
if int(ticket_split) < self.users:
print(ticket.QUEUE_TICKET_SHORT)
return {"status": False, "is_black": False}
print(u"当前余票数小于乘车人数,放弃订票")
else:
print(ticket.QUEUE_TICKET_SUCCESS.format(ticket_split))
return {"status": True, "is_black": False}
else:
return {"status": False, "is_black": True}
print(u"排队成功, 当前余票还剩余: {0} 张".format(ticket_split))
c = confirmSingleForQueueAsys(session=self.session,
passengerTicketStr=self.passengerTicketStr,
oldPassengerStr=self.oldPassengerStr,
result=self.result,)
print(u"验证码提交安全期,等待{}MS".format(self.ifShowPassCodeTime))
time.sleep(self.ifShowPassCodeTime)
c.sendConfirmSingleForQueueAsys()
else:
print(ticket.QUEUE_JOIN_BLACK.format(getQueueCountAsyncResult, self.train_no))
return {"status": False, "is_black": True, "train_no": self.train_no}
print(u"排队发现未知错误{0},将此列车 {1}加入小黑屋".format(getQueueCountAsyncResult, self.train_no))
wrapcache.set(key=self.train_no, value=datetime.datetime.now(),
timeout=int(_get_yaml()["ticket_black_list_time"]) * 60)
elif "messages" in getQueueCountAsyncResult and getQueueCountAsyncResult["messages"]:
print(ticket.QUEUE_WARNING_MSG.format(getQueueCountAsyncResult["messages"][0], self.train_no))
return {"status": False, "is_black": True, "train_no": self.train_no}
print(u"排队异常,错误信息:{0}, 将此列车 {1}加入小黑屋".format(getQueueCountAsyncResult["messages"][0], self.train_no))
wrapcache.set(key=self.train_no, value=datetime.datetime.now(),
timeout=int(_get_yaml()["ticket_black_list_time"]) * 60)
else:
if "validateMessages" in getQueueCountAsyncResult and getQueueCountAsyncResult["validateMessages"]:
print(str(getQueueCountAsyncResult["validateMessages"]))
return {"status": False, "is_black": False}
else:
return {"status": False, "is_black": False}
else:
return {"status": False, "is_black": False}
# coding=utf-8
from PIL import Image
from config.ticketConf import _get_yaml
from damatuCode.ruokuai import RClient
def getRandCode(is_auto_code, auto_code_type):
"""
识别验证码
:return: 坐标
"""
try:
if is_auto_code:
if auto_code_type == 1:
print(u"打码兔已关闭, 如需使用自动识别,请使用如果平台 auto_code_type == 2")
return
if auto_code_type == 2:
rc = RClient(_get_yaml()["auto_code_account"]["uesr"], _get_yaml()["auto_code_account"]["pwd"])
im = open('./tkcode', 'rb').read()
Result = rc.rk_create(im, 6113)
if "Result" in Result:
return codexy(Ofset=",".join(list(Result["Result"])), is_raw_input=False)
else:
if "Error" in Result and Result["Error"]:
print Result["Error"]
return ""
else:
img = Image.open('./tkcode')
img.show()
return codexy()
except:
pass
def codexy(Ofset=None, is_raw_input=True):
"""
获取验证码
:return: str
"""
if is_raw_input:
Ofset = raw_input(u"请输入验证码: ")
Ofset = Ofset.replace(",", ",")
select = Ofset.split(',')
post = []
offsetsX = 0 # 选择的答案的left值,通过浏览器点击8个小图的中点得到的,这样基本没问题
offsetsY = 0 # 选择的答案的top值
for ofset in select:
if ofset == '1':
offsetsY = 46
offsetsX = 42
elif ofset == '2':
offsetsY = 46
offsetsX = 105
elif ofset == '3':
offsetsY = 45
offsetsX = 184
elif ofset == '4':
offsetsY = 48
offsetsX = 256
elif ofset == '5':
offsetsY = 36
offsetsX = 117
elif ofset == '6':
offsetsY = 112
offsetsX = 115
elif ofset == '7':
offsetsY = 114
offsetsX = 181
elif ofset == '8':
offsetsY = 111
offsetsX = 252
else:
pass
post.append(offsetsX)
post.append(offsetsY)
randCode = str(post).replace(']', '').replace('[', '').replace("'", '').replace(' ', '')
print(u"验证码识别坐标为{0}".format(randCode))
return randCode
# coding=utf-8
import json
import re
class getRepeatSubmitToken:
def __init__(self, session):
self.session = session
def sendGetRepeatSubmitToken(self):
"""
获取提交车票请求token
:return: token
"""
initdc_url = self.session.urls["initdc_url"]
initdc_result = self.session.httpClint.send(initdc_url, )
token_name = re.compile(r"var globalRepeatSubmitToken = '(\S+)'")
ticketInfoForPassengerForm_name = re.compile(r'var ticketInfoForPassengerForm=(\{.+\})?')
order_request_params_name = re.compile(r'var orderRequestDTO=(\{.+\})?')
token = re.search(token_name, initdc_result).group(1)
re_tfpf = re.findall(ticketInfoForPassengerForm_name, initdc_result)
re_orp = re.findall(order_request_params_name, initdc_result)
if re_tfpf:
ticketInfoForPassengerForm = json.loads(re_tfpf[0].replace("'", '"'))
else:
ticketInfoForPassengerForm = ""
if re_orp:
order_request_params = json.loads(re_orp[0].replace("'", '"'))
else:
order_request_params = ""
return {
"token": token,
"ticketInfoForPassengerForm": ticketInfoForPassengerForm,
"order_request_params": order_request_params,
"session": self.session
}
\ No newline at end of file
# coding=utf-8
import copy
import datetime
import random
import time
import wrapcache
from config.TicketEnmu import ticket
......@@ -45,11 +43,9 @@ class query:
查询
:return:
"""
for station_date in self.station_dates:
select_url = copy.copy(self.session.urls["select_url"])
select_url["req_url"] = select_url["req_url"].format(
station_date, self.from_station, self.to_station)
select_url["req_url"] = select_url["req_url"].format(station_date, self.from_station, self.to_station)
station_ticket = self.session.httpClint.send(select_url)
value = station_ticket.get("data", "")
if not value:
......@@ -62,52 +58,42 @@ class query:
if ticket_info[11] == "Y" and ticket_info[1].encode("utf8") == "预订": # 筛选未在开始时间内的车次
for j in xrange(len(self._station_seat)):
is_ticket_pass = ticket_info[self.station_seat(self._station_seat[j].encode("utf8"))]
if is_ticket_pass != '' and is_ticket_pass != '无' and ticket_info[
3] in self.station_trains and is_ticket_pass != '*': # 过滤有效目标车次
if is_ticket_pass != '' and is_ticket_pass != '无' and ticket_info[3] in self.station_trains and is_ticket_pass != '*': # 过滤有效目标车次
secretStr = ticket_info[0]
train_no = ticket_info[2]
query_from_station_name = ticket_info[6]
query_to_station_name = ticket_info[7]
train_location = ticket_info[15]
stationTrainCode = ticket_info[3]
train_date = station_date
leftTicket = ticket_info[12]
set_type = self._station_seat[j]
print (u'车次: {0} 始发车站: {1} 终点站: {2} {3}: {4}'.format(train_no,
self.from_station_h,
self.to_station_h,
self._station_seat[j].encode(
"utf8"),
ticket_info[self.station_seat(
self._station_seat[
j].encode("utf8"))]
))
if "train_no" in self.ticket_black_list and (
datetime.datetime.now() - self.ticket_black_list[
train_no]).seconds / 60 < int(ticket.TICKET_BLACK_LIST_TIME):
self.from_station_h,
self.to_station_h,
self._station_seat[j].encode(
"utf8"),
ticket_info[self.station_seat(
self._station_seat[
j].encode("utf8"))]
))
if wrapcache.get(train_no):
print(ticket.QUERY_IN_BLACK_LIST.format(train_no))
break
else:
print (ticket.QUERY_C)
# self.buy_ticket_time = datetime.datetime.now()
return {
"secretStr": secretStr,
"train_no": train_no,
"stationTrainCode": stationTrainCode,
"train_date": train_date,
"train_date": station_date,
"query_from_station_name": query_from_station_name,
"query_to_station_name": query_to_station_name,
# "buy_ticket_time": self.buy_ticket_time,
"set_type": set_type,
"leftTicket": leftTicket,
"train_location": train_location,
"code": ticket.SUCCESS_CODE,
"status": True,
}
else:
pass
else:
pass
else:
print u"车次配置信息有误,或者返回数据异常,请检查 {}".format(station_ticket)
return {"code": ticket.FAIL_CODE, "status": False}
......
......@@ -89,7 +89,7 @@ class queryOrderWaitTime:
else:
return False
else:
print(u"接口 {} 无响应".format(queryMyOrderNoCompleteUrl))
return False
def initNoComplete(self):
"""
......@@ -121,3 +121,4 @@ class queryOrderWaitTime:
return True
else:
print(ticket.CANCEL_ORDER_FAIL.format(sequence_no))
return False
# coding=utf-8
import datetime
import urllib
from inter.CheckOrderInfo import checkOrderInfo
from myException.ticketIsExitsException import ticketIsExitsException
def time():
"""
获取日期
:return:
"""
today = datetime.date.today()
return today.strftime('%Y-%m-%d')
class submitOrderRequest:
def __init__(self, session, secretStr, from_station, to_station, train_no, set_type,
passengerTicketStrList, oldPassengerStr, train_date, ticke_peoples):
self.session = session
self.secretStr = secretStr
self.from_station = from_station
self.to_station = to_station
self.to_station = to_station
self.train_no = train_no
self.set_type = set_type
self.passengerTicketStrList = passengerTicketStrList
self.oldPassengerStr = oldPassengerStr
self.train_date = train_date
self.ticke_peoples = ticke_peoples
def data_apr(self):
"""
:return:
"""
data = [('secretStr', urllib.unquote(self.secretStr)), # 字符串加密
('train_date', self.train_date), # 出发时间
('back_train_date', time()), # 返程时间
('tour_flag', 'dc'), # 旅途类型
('purpose_codes', 'ADULT'), # 成人票还是学生票
('query_from_station_name', self.from_station), # 起始车站
('query_to_station_name', self.to_station), # 终点车站
]
return data
def sendSubmitOrderRequest(self):
"""
提交车次
预定的请求参数,注意参数顺序
注意这里为了防止secretStr被urllib.parse过度编码,在这里进行一次解码
否则调用HttpTester类的post方法将会将secretStr编码成为无效码,造成提交预定请求失败
:param self:
:param secretStr: 提交车次加密
:return:
"""
submit_station_url = self.session.urls["submit_station_url"]
submitResult = self.session.httpClint.send(submit_station_url, self.data_apr())
if 'data' in submitResult and submitResult['data']:
if submitResult['data'] == 'N':
print (u'出票成功')
coi = checkOrderInfo(self.session, self.train_no, self.set_type, self.passengerTicketStrList,
self.oldPassengerStr,
self.train_date, self.ticke_peoples)
coi.sendCheckOrderInfo()
else:
print (u'出票失败')
elif 'messages' in submitResult and submitResult['messages']:
raise ticketIsExitsException(submitResult['messages'][0])
此差异已折叠。
......@@ -12,49 +12,14 @@ from config import logger
def _set_header_default():
header_dict = OrderedDict()
header_dict["Host"] = "kyfw.12306.cn"
header_dict["Connection"] = "keep-alive"
header_dict["Accept"] = "application/json, text/javascript, */*; q=0.01"
header_dict["Origin"] = "https://kyfw.12306.cn"
header_dict["X-Requested-With"] = "XMLHttpRequest"
header_dict["Accept"] = "application/json, text/plain, */*"
header_dict["Accept-Encoding"] = "gzip, deflate"
header_dict[
"User-Agent"] = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36"
"User-Agent"] = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) 12306-electron/1.0.1 Chrome/59.0.3071.115 Electron/1.8.4 Safari/537.36"
header_dict["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8"
header_dict["Referer"] = "https://kyfw.12306.cn/otn/leftTicket/init"
header_dict["Accept-Encoding"] = "gzip, deflate, br"
header_dict["Accept-Language"] = "zh-CN,zh;q=0.9,en;q=0.8"
return header_dict
def _set_header_j():
"""设置header"""
return {
"Content-Type": "application/json; charset=UTF-8",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/604.3.5 (KHTML, like Gecko) Version/11.0.1 Safari/604.3.5",
"Accept": "application/json, text/javascript, */*; q=0.01",
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
"Origin": "https://kyfw.12306.cn",
"Connection": "keep-alive",
}
def _set_header_x():
"""设置header"""
return {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"X-Requested-With": "XMLHttpRequest",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/604.3.5 (KHTML, like Gecko) Version/11.0.1 Safari/604.3.5",
"Accept": "application/json, text/javascript, */*; q=0.01",
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
"Origin": "https://kyfw.12306.cn",
"Connection": "keep-alive",
}
class HTTPClient(object):
def __init__(self):
......@@ -67,7 +32,7 @@ class HTTPClient(object):
def initS(self):
self._s = requests.Session()
self._s.headers.update(_set_header_j())
self._s.headers.update(_set_header_default())
return self
def set_cookies(self, **kwargs):
......@@ -79,6 +44,13 @@ class HTTPClient(object):
for k, v in kwargs.items():
self._s.cookies.set(k, v)
def get_cookies(self):
"""
获取cookies
:return:
"""
return self._s.cookies.values()
def del_cookies(self):
"""
删除所有的key
......@@ -97,12 +69,9 @@ class HTTPClient(object):
self._s.headers.update(headers)
return self
def resetHeaders(self, header_type):
def resetHeaders(self):
self._s.headers.clear()
if header_type == 1:
self._s.headers.update(_set_header_x())
else:
self._s.headers.update(_set_header_j())
self._s.headers.update(_set_header_default())
def getHeadersHost(self):
return self._s.headers["Host"]
......@@ -126,14 +95,6 @@ class HTTPClient(object):
def cdn(self, cdn):
self._cdn = cdn
# def send_socket(self, urls, data=None, **kwargs):
# data = """
# POST {0} HTTP/1.1
# {0}
# """.format(urls["req_url"], self._set_header())
# fack = socket.create_connection(urls["Host"], 443)
# fack.send()
def send(self, urls, data=None, **kwargs):
"""send request to url.If response 200,return response, else return None."""
allow_redirects = False
......@@ -141,31 +102,22 @@ class HTTPClient(object):
req_url = urls.get("req_url", "")
re_try = urls.get("re_try", 0)
s_time = urls.get("s_time", 0)
contentType = urls.get("Content-Type", 0)
error_data = {"code": 99999, "message": u"重试次数达到上限"}
if data:
method = "post"
self.setHeaders({"Content-Length": "{0}".format(len(data))})
else:
method = "get"
self.resetHeaders(contentType)
self.resetHeaders()
self.setHeadersReferer(urls["Referer"])
if is_logger:
logger.log(
u"url: {0}\n入参: {1}\n请求方式: {2}\n".format(req_url, data, method, ))
self.setHeadersHost(urls["Host"])
# self.setHeadersHost(urls["Host"])
if self.cdn:
url_host = self.cdn
else:
url_host = urls["Host"]
if contentType == 1:
# 普通from表单
self.resetHeaders(contentType)
if method == "post":
pass
data = urllib.urlencode(data)
elif contentType == 0:
self.resetHeaders(contentType)
for i in range(re_try):
try:
# sleep(urls["s_time"]) if "s_time" in urls else sleep(0.001)
......
......@@ -3,4 +3,5 @@ bs4==0.0.1
PyYAML==3.12
six==1.10.0
requests==2.18.4
Pillow==5.0.0
\ No newline at end of file
Pillow==5.0.0
wrapcache==1.0.8
\ No newline at end of file
# -*- coding=utf-8 -*-
from init import login, select_ticket_info, SelectTicketInfoFast
from config.emailConf import sendEmail
from init import select_ticket_info
def run():
# login.main()
SelectTicketInfoFast.selectFast().main()
# select_ticket_info.select().main()
select_ticket_info.select().main()
def testEmail():
sendEmail(u"订票小助手测试一下")
if __name__ == '__main__':
run()
\ No newline at end of file
run()
# testEmail()
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册