优化代码结构

新增双下单方法
修复一直bug
pull/42/head
wenxianping 2018-08-29 19:19:13 +08:00
parent 009b989a64
commit 6b849c1201
36 changed files with 1686 additions and 2889 deletions

View File

@ -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>

View File

@ -1,11 +0,0 @@
<?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>

View File

@ -1,14 +0,0 @@
<?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>

View File

@ -1,3 +0,0 @@
<component name="ProjectDictionaryState">
<dictionary name="wenxianping" />
</component>

View File

@ -1,10 +1,49 @@
<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>

View File

@ -1,7 +0,0 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="useProjectProfile" value="false" />
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

View File

@ -1,4 +1,7 @@
<?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>

File diff suppressed because it is too large Load Diff

166
README.md
View File

@ -1,60 +1,16 @@
### 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:出发日期格式ex2018-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.图片位置说明验证码图片中每个图片代表一个下标依次类推12345678
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_type1=打码兔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为开启cdn2为普通查询
- 能够一定程度躲避封ip
- 查询余票快人一步
- 提交订单快人一步
- 僵尸票可能会少很多
- 兼容Windows cmd命令乱码问题
- 规范12306接口提交参数
- 修改已知bug
- 最后感谢群里提供测试和代码的小伙伴,能为你们买到一张回家的票真的感到灰常开心
- 2018.2.28更新收12306风控影响代码可能有时候会进入慢排队请自行调整刷新参数
- 修改已知bug
- 优化接口提交参数规范
- [更新日志](Update.md)

118
Update.md Normal file
View File

@ -0,0 +1,118 @@
- 2017.5.13跟新
- 增加登陆错误判断(密码错误&ip校验
- 修改queryOrderWaitTime校验orderId字段bug校验msg字段bug校验messagesbug
- 修改checkQueueOrder 校验 data 字段的列表推导式bug
- 增加代理ip方法目前已可以过滤有用ip
- 2018.1.7 号更新
- 增加自动配置
```
#station_date:出发日期格式ex2018-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.图片位置说明验证码图片中每个图片代表一个下标依次类推12345678
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_type1=打码兔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为开启cdn2为普通查询
- 能够一定程度躲避封ip
- 查询余票快人一步
- 提交订单快人一步
- 僵尸票可能会少很多
- 兼容Windows cmd命令乱码问题
- 规范12306接口提交参数
- 修改已知bug
- 最后感谢群里提供测试和代码的小伙伴,能为你们买到一张回家的票真的感到灰常开心
- 2018.2.28更新收12306风控影响代码可能有时候会进入慢排队请自行调整刷新参数
- 修改已知bug
- 优化接口提交参数规范
- 2018.8.29更新,解决慢排队问题,增加双订票接口
- 修改已知bug
- 优化代码结构
- 新增第三方库wrapcache需要重新安装requirements.txt

View 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已经失效, 正在重新登录中"

View File

@ -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"]
return s

View File

@ -1,78 +1,63 @@
---
#station_date:出发日期格式ex2018-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功能是否正常
set:
# 出发日期格式ex2018-01-06
station_dates:
- "2018-09-05"
#邮箱配置 列举163
# 过滤车次格式ex- "G1353" - "G1329"
station_trains:
- "G6504"
# 出发城市,比如深圳北,就填深圳就搜得到
from_station: "深圳"
# 到达城市 比如深圳北,就填深圳就搜得到
to_station: "广州"
# 座位 多个座位ex: - "二等座" - "一等座"
set_type:
- "二等座"
# 余票不足是否自动提交,目前应该没什么卵用
is_more_ticket: True
# 乘车人 多个乘车人ex: - "张三" - "李四"
ticke_peoples:
- ""
# 12306登录账号
12306account:
- uesr: ""
- pwd: ""
select_refresh_interval: 1
# 加入小黑屋时间,此功能为了防止僵尸票导致一直下单不成功错过正常的票
ticket_black_list_time: 5
# 自动打码
is_auto_code: False
# 打码平台, 2 为若快平台(目前只支持若快平台打码,打码兔已经关闭), 若快注册地址http://www.ruokuai.com/client/index?6726
auto_code_type: 2
# 打码平台账号
auto_code_account:
uesr: ""
pwd: ""
# 邮箱配置,如果抢票成功,将通过邮件配置通知给您
# 列举163
# email: "xxx@163.com"
# notice_email_list: "123@qq.com"
# username: "xxxxx"
# password: "xxxxx
# host: "smtp.163.com"
#邮箱配置 列举qq qq设置比较复杂需要在邮箱--账户--开启smtp服务取得授权码==邮箱登录密码
# 列举qq qq设置比较复杂需要在邮箱-->账户-->开启smtp服务取得授权码==邮箱登录密码
# email: "xxx@qq.com"
# notice_email_list: "123@qq.com"
# username: "xxxxx"
# password: "授权码"
# host: "smtp.qq.com"
set:
station_dates:
- "2018-06-21"
- "2018-06-22"
station_trains:
- "G1321"
from_station: "上海"
to_station: "长沙"
set_type:
- "二等座"
- "商务座"
- "一等座"
is_more_ticket: True
ticke_peoples:
- "文贤平"
# - "彭淑杰"
12306count:
# - uesr: ""
# - pwd: "apple1995"
- uesr: "931128603@qq.com"
- pwd: "QWERTY"
select_refresh_interval: 1
ticket_black_list_time: 5
is_aotu_code: False
aotu_code_type: 2
#enable_proxy: False
damatu:
uesr: ""
pwd: "qazWSX1995"
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

View File

@ -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,

View File

@ -1,292 +0,0 @@
# -*- 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()

View File

@ -1,5 +1,6 @@
#!/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.图片位置说明验证码图片中每个图片代表一个下标依次类推12345678
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():

View File

@ -1,23 +1,22 @@
# -*- 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
import wrapcache
from agency.cdn_utils import CDNProxy
from config import urlConf
from config.emailConf import sendEmail
from config.TicketEnmu import ticket
from config.ticketConf import _get_yaml
from init import login
from init.login import GoLogin
from inter.AutoSubmitOrderRequest import autoSubmitOrderRequest
from inter.CheckUser import checkUser
from inter.GetPassengerDTOs import getPassengerDTOs
from inter.LiftTicketInit import liftTicketInit
from inter.Query import query
from inter.SubmitOrderRequest import submitOrderRequest
from myException.PassengerUserException import PassengerUserException
from myException.UserPasswordException import UserPasswordException
from myException.ticketConfigException import ticketConfigException
@ -30,28 +29,23 @@ sys.setdefaultencoding('utf-8')
class select:
"""
快速提交车票通道
"""
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.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.order_type = self.get_ticket_info()
self.is_auto_code = _get_yaml()["is_auto_code"]
self.auto_code_type = _get_yaml()["auto_code_type"]
self.is_cdn = _get_yaml()["is_cdn"]
self.order_request_params = {} # 订单提交时的参数
self.ticketInfoForPassengerForm = {} # 初始化当前页面参数
self.current_seats = {} # 席别信息
self.token = ""
self.set_type = ""
self.user_info = ""
self.secretStr = ""
self.ticket_black_list = dict()
self.ticket_black_list_time = dict()
self.is_check_user = dict()
self.httpClint = HTTPClient()
self.confUrl = urlConf.urls
self.login = GoLogin(self.httpClint, self.confUrl, self.is_aotu_code, self.aotu_code_type)
self.is_download_img = False
self.randCode = ""
self.urls = urlConf.urls
self.login = GoLogin(self, self.is_auto_code, self.auto_code_type)
self.cdn_list = []
self.buy_ticket_time = ""
self.passengerTicketStrList = ""
self.oldPassengerStr = ""
def get_ticket_info(self):
"""
@ -68,58 +62,26 @@ class select:
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
order_type = ticket_info_config["order_type"]
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刷新间隔:{6}s(如果想随机刷新,请自行修改)\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"当前配置:出发站:{0}\n到达站:{1}\n乘车日期:{2}\n坐席:{3}\n是否有票自动提交:{4}\n乘车人:{5}\n" \
u"刷新间隔:随机(1-4S)\n候选购买车次:{7}\n僵尸票关小黑屋时长:{8}\n 下单接口:{9}\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,
order_type,
)
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 get_order_request_params(self):
return self.order_request_params
def get_ticketInfoForPassengerForm(self):
return self.ticketInfoForPassengerForm
def get_current_seats(self):
return self.current_seats
def get_token(self):
return self.token
def get_set_type(self):
return self.set_type
def conversion_int(self, str):
return int(str)
def station_seat(self, index):
"""
获取车票对应坐席
:param seat_type:
:return:
"""
seat = {'商务座': 32,
'一等座': 31,
'二等座': 30,
'特等座': 25,
'软卧': 23,
'硬卧': 28,
'硬座': 29,
'无座': 26,
}
return seat[index]
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, order_type
def station_table(self, from_station, to_station):
"""
@ -138,534 +100,6 @@ class select:
to_station = station_name[to_station.encode("utf8")]
return from_station, to_station
def time(self):
"""
获取日期
:return:
"""
today = datetime.date.today()
# tomorrow = today+datetime.timedelta(1)
return today.strftime('%Y-%m-%d')
def callReadImg(self, code_url):
"""
下载验证码
:param code_url: 验证码url
:return:
"""
self.login.readImg(code_url=code_url)
self.is_aotu_code = True
def callRandCode(self):
"""
识别验证码
:return:
"""
while True:
if self.is_aotu_code:
self.randCode = self.login.getRandCode()
self.is_aotu_code = False
def getRepeatSubmitToken(self):
"""
获取提交车票请求token
:return: token
"""
initdc_url = self.confUrl["initdc_url"]
initdc_result = self.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=(\{.+\})?')
self.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:
self.ticketInfoForPassengerForm = json.loads(re_tfpf[0].replace("'", '"'))
else:
pass
if re_orp:
self.order_request_params = json.loads(re_orp[0].replace("'", '"'))
else:
pass
def GetJS(self):
getJSUrl = self.confUrl["GetJS"]
self.httpClint.send(getJSUrl)
odxmfwgUrl = self.confUrl["odxmfwg"]
self.httpClint.send(odxmfwgUrl)
def getPassengerDTOs(self):
"""
获取乘客信息
:return:
"""
get_passengerDTOs = self.confUrl["get_passengerDTOs"]
get_data = {
'_json_att': None,
'REPEAT_SUBMIT_TOKEN': self.token
}
jsonData = self.httpClint.send(get_passengerDTOs, get_data)
if 'data' in jsonData and jsonData['data'] and 'l' in jsonData['data'] and jsonData['data'][
'normal_passengers']:
normal_passengers = jsonData['data']['normal_passengers']
_normal_passenger = [normal_passengers[i] for i in range(len(normal_passengers))if normal_passengers[i]["passenger_name"] in self.ticke_peoples]
return _normal_passenger if _normal_passenger else [normal_passengers[0]] # 如果配置乘车人没有在账号,则默认返回第一个用户
else:
if 'data' in jsonData and 'exMsg' in jsonData['data'] and jsonData['data']['exMsg']:
print(jsonData['data']['exMsg'])
elif 'messages' in jsonData and jsonData['messages']:
print(jsonData['messages'][0])
else:
print(u"未查找到常用联系人")
raise PassengerUserException(u"未查找到常用联系人,请先添加联系人在试试")
def submitOrderRequestFunc(self, from_station, to_station, station_date=None):
self.confUrl["select_url"]["req_url"] = self.confUrl["select_url"]["req_url"].format(
station_date, from_station, to_station)
station_ticket = self.httpClint.send(self.confUrl["select_url"])
return json.loads(station_ticket)
def submitOrderRequestImplement(self, from_station, to_station,):
"""
提交车次信息
车次对应字典
{32: '商务座 ',
31: '一等座 ',
30: '二等座 ',
25: '特等座 ',
23: '软卧 ',
28: '硬卧 ',
29: '硬座 ',
26: '无座 '
} 参照station_seat()方法
:return:
"""
station_tickets = [self.submitOrderRequestFunc(from_station, to_station, station_date) for station_date in self.station_dates]
for station_ticket in station_tickets:
value = station_ticket['data']
if not value:
print (u'{0}-{1} 车次坐席查询为空...'.format(self.from_station, self.to_station))
else:
if value['result']:
for i in value['result']:
ticket_info = i.split('|')
if ticket_info[11] == "Y" and ticket_info[1].encode("utf8") == "预订": # 筛选未在开始时间内的车次
for j in range(len(self._station_seat)):
is_ticket_pass = ticket_info[self.station_seat(self._station_seat[j].encode("utf8"))]
# print self._station_seat[j]
if is_ticket_pass != '' and is_ticket_pass != '' and ticket_info[3] in self.station_trains and is_ticket_pass != '*': # 过滤有效目标车次
# tiket_values = [k for k in value['map'].values()]
self.secretStr = ticket_info[0]
train_no = ticket_info[3]
print (u'车次: ' + train_no + ' 始发车站: ' + self.from_station + ' 终点站: ' +
self.to_station + ' ' + self._station_seat[j].encode("utf8") + ':' + ticket_info[self.station_seat(self._station_seat[j].encode("utf8"))])
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(u"该车次{} 正在被关小黑屋,跳过此车次".format(train_no))
break
else:
print (u'正在尝试提交订票...')
self.buy_ticket_time = datetime.datetime.now()
# self.submitOrderRequestFunc(from_station, to_station, self.time())
self.submit_station()
self.getPassengerTicketStr(self._station_seat[j].encode("utf8"))
self.getRepeatSubmitToken()
if not self.user_info: # 修改每次都调用用户接口导致用户接口不能用
self.user_info = self.getPassengerDTOs()
codeImgByOrder = self.confUrl["codeImgByOrder"]
self.login.readImg(codeImgByOrder)
if self.checkOrderInfo(train_no, self._station_seat[j].encode("utf8")):
break
else:
pass
else:
pass
# time.sleep(self.expect_refresh_interval)
else:
print u"车次配置信息有误,或者返回数据异常,请检查 {}".format(station_ticket)
def check_user(self):
"""
检查用户是否达到订票条件
:return:
"""
check_user_url = self.confUrl["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 submit_station(self):
"""
提交车次
预定的请求参数注意参数顺序
注意这里为了防止secretStr被urllib.parse过度编码在这里进行一次解码
否则调用HttpTester类的post方法将会将secretStr编码成为无效码,造成提交预定请求失败
:param self:
:param secretStr: 提交车次加密
:return:
"""
submit_station_url = self.confUrl["submit_station_url"]
data = [('secretStr', urllib.unquote(self.secretStr)), # 字符串加密
('train_date', self.station_dates[0]), # 出发时间
('back_train_date', self.time()), # 返程时间
('tour_flag', 'dc'), # 旅途类型
('purpose_codes', 'ADULT'), # 成人票还是学生票
('query_from_station_name', self.from_station), # 起始车站
('query_to_station_name', self.to_station), # 终点车站
]
submitResult = self.httpClint.send(submit_station_url, data)
if 'data' in submitResult and submitResult['data']:
if submitResult['data'] == 'N':
print (u'出票成功')
else:
print (u'出票失败')
elif 'messages' in submitResult and submitResult['messages']:
raise ticketIsExitsException(submitResult['messages'][0])
def getPassengerTicketStr(self, set_type):
"""
获取getPassengerTicketStr 提交对应的代号码
:param str: 坐席
:return:
"""
passengerTicketStr = {
'一等座': 'M',
'特等座': 'P',
'二等座': 'O',
'商务座': 9,
'硬座': 1,
'无座': 1,
'软卧': 4,
'硬卧': 3,
}
self.set_type = str(passengerTicketStr[set_type.replace(' ', '')])
def ticket_type(self):
"""订单票的类型,目前只考虑成人票,此方法暂时搁置,做备案"""
ticket_type = {'adult': "1", 'child': "2", 'student': "3", 'disability': "4"}
return ticket_type
def getPassengerTicketStrListAndOldPassengerStr(self):
"""
获取提交车次人内容格式
passengerTicketStr O,0,1,文贤平,1,43052419950223XXXX,15618715583,N_O,0,1,梁敏,1,43052719920118XXXX,,N
oldPassengerStr 文贤平,1,43052719920118XXXX,1_梁敏,1,43052719920118XXXX,1_
:return:
"""
passengerTicketStrList = []
oldPassengerStr = []
if not self.user_info:
raise PassengerUserException(u"联系人不在列表中,请查证后添加")
if len(self.user_info) is 1:
passengerTicketStrList.append(
'0,' + self.user_info[0]['passenger_type'] + "," + self.user_info[0][
"passenger_name"] + "," +
self.user_info[0]['passenger_id_type_code'] + "," + self.user_info[0]['passenger_id_no'] + "," +
self.user_info[0]['mobile_no'] + ',N')
oldPassengerStr.append(
self.user_info[0]['passenger_name'] + "," + self.user_info[0]['passenger_id_type_code'] + "," +
self.user_info[0]['passenger_id_no'] + "," + self.user_info[0]['passenger_type'] + '_')
else:
for i in range(len(self.user_info)):
passengerTicketStrList.append(
'0,' + self.user_info[i]['passenger_type'] + "," + self.user_info[i][
"passenger_name"] + "," + self.user_info[i]['passenger_id_type_code'] + "," + self.user_info[i][
'passenger_id_no'] + "," + self.user_info[i]['mobile_no'] + ',N_' + self.set_type)
oldPassengerStr.append(
self.user_info[i]['passenger_name'] + "," + self.user_info[i]['passenger_id_type_code'] + "," +
self.user_info[i]['passenger_id_no'] + "," + self.user_info[i]['passenger_type'] + '_')
return passengerTicketStrList, oldPassengerStr
def checkOrderInfo(self, train_no, set_type):
"""
检查支付订单需要提交REPEAT_SUBMIT_TOKEN
passengerTicketStr : 座位编号,0,票类型,乘客名,证件类型,证件号,手机号码,保存常用联系人(Y或N)
oldPassengersStr: 乘客名,证件类型,证件号,乘客类型
:return:
"""
passengerTicketStrList, oldPassengerStr = self.getPassengerTicketStrListAndOldPassengerStr()
checkOrderInfoUrl = self.confUrl["checkOrderInfoUrl"]
data = collections.OrderedDict()
data['cancel_flag'] = 2
data['bed_level_order_num'] = "000000000000000000000000000000"
data['passengerTicketStr'] = self.set_type + "," + ",".join(passengerTicketStrList).rstrip("_{0}".format(self.set_type))
data['oldPassengerStr'] = "".join(oldPassengerStr)
data['tour_flag'] = 'dc'
data['whatsSelect'] = 1
data['REPEAT_SUBMIT_TOKEN'] = self.token
checkOrderInfo = self.httpClint.send(checkOrderInfoUrl, data)
if 'data' in checkOrderInfo:
if "ifShowPassCode" in checkOrderInfo["data"] and checkOrderInfo["data"]["ifShowPassCode"] == "Y":
is_need_code = True
if self.getQueueCount(train_no, set_type, is_need_code):
return True
if "ifShowPassCode" in checkOrderInfo["data"] and checkOrderInfo['data']['submitStatus'] is True:
print (u'车票提交通过,正在尝试排队')
is_need_code = False
if self.getQueueCount(train_no, set_type, is_need_code):
return True
else:
if "errMsg" in checkOrderInfo['data'] and checkOrderInfo['data']["errMsg"]:
print checkOrderInfo['data']["errMsg"]
else:
print checkOrderInfo
elif 'messages' in checkOrderInfo and checkOrderInfo['messages']:
print (checkOrderInfo['messages'][0])
def getQueueCount(self, train_no, set_type, is_need_code):
"""
# 模拟查询当前的列车排队人数的方法
# 返回信息组成的提示字符串
:param token:
:return:
"""
l_time = time.localtime(time.time())
new_train_date = time.strftime("%a %b %d %Y", l_time)
getQueueCountUrl = self.confUrl["getQueueCountUrl"]
data = collections.OrderedDict()
data['train_date'] = str(new_train_date) + " 00:00:00 GMT+0800 (中国标准时间)",
data['train_no'] = self.get_ticketInfoForPassengerForm()['queryLeftTicketRequestDTO']['train_no'],
data['stationTrainCode'] = self.get_ticketInfoForPassengerForm()['queryLeftTicketRequestDTO']['station_train_code'],
data['seatType'] = self.set_type,
data['fromStationTelecode'] = self.get_ticketInfoForPassengerForm()['queryLeftTicketRequestDTO']['from_station'],
data['toStationTelecode'] = self.get_ticketInfoForPassengerForm()['queryLeftTicketRequestDTO']['to_station'],
data['leftTicket'] = self.get_ticketInfoForPassengerForm()['leftTicketStr'],
data['purpose_codes'] = self.get_ticketInfoForPassengerForm()['purpose_codes'],
data['train_location'] = self.get_ticketInfoForPassengerForm()['train_location'],
data['REPEAT_SUBMIT_TOKEN'] = self.get_token(),
getQueueCountResult = self.httpClint.send(getQueueCountUrl, data)
if "status" in getQueueCountResult and getQueueCountResult["status"] is True:
if "countT" in getQueueCountResult["data"]:
ticket = getQueueCountResult["data"]["ticket"]
ticket_split = sum(map(self.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.user_info):
print(u"当前余票数小于乘车人数,放弃订票")
else:
print(u"排队成功, 当前余票还剩余: {0}".format(ticket_split))
if self.checkQueueOrder(is_need_code):
return True
else:
print(u"当前排队人数: {1} 当前余票还剩余:{0} 张,继续排队中".format(ticket_split, countT))
else:
print(u"排队发现未知错误{0},将此列车 {1}加入小黑屋".format(getQueueCountResult, train_no))
self.ticket_black_list[train_no] = datetime.datetime.now()
elif "messages" in getQueueCountResult and getQueueCountResult["messages"]:
print(u"排队异常,错误信息:{0}, 将此列车 {1}加入小黑屋".format(getQueueCountResult["messages"][0], train_no))
self.ticket_black_list[train_no] = datetime.datetime.now()
else:
if "validateMessages" in getQueueCountResult and getQueueCountResult["validateMessages"]:
print(str(getQueueCountResult["validateMessages"]))
self.ticket_black_list[train_no] = datetime.datetime.now()
else:
print(u"未知错误 {0}".format("".join(getQueueCountResult)))
def checkRandCodeAnsyn(self, randCode):
"""
识别验证码
:return: 识别结果
"""
checkRandCodeAnsyn = self.confUrl["checkRandCodeAnsyn"]
randData = {
"randCode": randCode,
"rand": "randp",
"_json_att": None,
"REPEAT_SUBMIT_TOKEN": self.get_token()
}
fresult = self.httpClint.send(checkRandCodeAnsyn, randData) # 校验验证码是否正确
return fresult['data']['msg']
def checkQueueOrder(self, is_node_code=False):
"""
模拟提交订单是确认按钮参数获取方法还是get_ticketInfoForPassengerForm 中获取
:return:
"""
passengerTicketStrList, oldPassengerStr = self.getPassengerTicketStrListAndOldPassengerStr()
checkQueueOrderUrl = self.confUrl["checkQueueOrderUrl"]
data = {
"passengerTicketStr": self.set_type + "," + ",".join(passengerTicketStrList).rstrip("_{0}".format(self.set_type)),
"oldPassengerStr": "".join(oldPassengerStr),
"purpose_codes": self.get_ticketInfoForPassengerForm()["purpose_codes"],
"key_check_isChange": self.get_ticketInfoForPassengerForm()["key_check_isChange"],
"leftTicketStr": self.get_ticketInfoForPassengerForm()["leftTicketStr"],
"train_location": self.get_ticketInfoForPassengerForm()["train_location"],
"seatDetailType": "000", # 开始需要选择座位但是目前12306不支持自动选择作为那这个参数为默认
"roomType": "00", # 好像是根据一个id来判断选中的两种 第一种是00第二种是10但是我在12306的页面没找到该id目前写死是00不知道会出什么错
"dwAll": "N",
"whatsSelect": 1,
"_json_at": "",
"randCode": "",
"choose_seats": "",
"REPEAT_SUBMIT_TOKEN": self.get_token(),
}
try:
if is_node_code:
print(u"正在使用自动识别验证码功能")
for i in range(3):
randCode = self.login.getRandCode()
checkcode = self.checkRandCodeAnsyn(randCode)
if checkcode == 'TRUE':
print(u"验证码通过,正在提交订单")
data['randCode'] = randCode
break
else:
print (u"验证码有误, {0}次尝试重试".format(i+1))
print(u"验证码超过限定次数3次放弃此次订票机会!")
else:
print(u"不需要验证码")
buy_end_time = (datetime.datetime.now() - self.buy_ticket_time).seconds
print(u"总共花费时长{0}S".format(buy_end_time))
time.sleep(8-buy_end_time if buy_end_time<8 else 0)
checkQueueOrderResult = self.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"提交订单成功!")
self.queryOrderWaitTime()
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))
def queryOrderWaitTime(self):
"""
排队获取订单等待信息,每隔3秒请求一次最高请求次数为20次
:return:
"""
num = 1
while True:
_random = int(round(time.time() * 1000))
num += 1
if num > 30:
print(u"超出排队时间,自动放弃,正在重新刷票")
order_id = self.queryMyOrderNoComplete() # 排队失败,自动取消排队订单
if order_id:
self.cancelNoCompleteMyOrder(order_id)
break
try:
data = {"random": _random, "tourFlag": "dc"}
queryOrderWaitTimeUrl = self.confUrl["queryOrderWaitTimeUrl"]
queryOrderWaitTimeResult = self.httpClint.send(queryOrderWaitTimeUrl, data)
except ValueError:
queryOrderWaitTimeResult = {}
if queryOrderWaitTimeResult:
if "status" in queryOrderWaitTimeResult and queryOrderWaitTimeResult["status"]:
if "orderId" in queryOrderWaitTimeResult["data"] and queryOrderWaitTimeResult["data"]["orderId"] is not None:
sendEmail(u"恭喜您订票成功,订单号为:{0}, 请立即打开浏览器登录12306访问未完成订单在30分钟内完成支付".format(queryOrderWaitTimeResult["data"]["orderId"]))
raise ticketIsExitsException(u"恭喜您订票成功,订单号为:{0}, 请立即打开浏览器登录12306访问未完成订单在30分钟内完成支付".format(queryOrderWaitTimeResult["data"]["orderId"]))
elif "msg" in queryOrderWaitTimeResult["data"] and queryOrderWaitTimeResult["data"]["msg"]:
print queryOrderWaitTimeResult["data"]["msg"]
break
elif "waitTime"in queryOrderWaitTimeResult["data"] and queryOrderWaitTimeResult["data"]["waitTime"]:
print(u"排队等待时间预计还剩 {0} ms".format(0-queryOrderWaitTimeResult["data"]["waitTime"]))
else:
print (u"正在等待中")
elif "messages" in queryOrderWaitTimeResult and queryOrderWaitTimeResult["messages"]:
print(u"排队等待失败: " + queryOrderWaitTimeResult["messages"])
else:
print(u"{}次排队中,请耐心等待".format(num+1))
else:
print(u"排队中")
time.sleep(2)
else:
print(ticketNumOutException(u"订单提交失败!,正在重新刷票"))
def queryMyOrderNoComplete(self):
"""
获取订单列表信息
:return:
"""
self.initNoComplete()
queryMyOrderNoCompleteUrl = self.confUrl["queryMyOrderNoCompleteUrl"]
data = {"_json_att": ""}
try:
queryMyOrderNoCompleteResult = self.httpClint.send(queryMyOrderNoCompleteUrl, data)
except ValueError:
queryMyOrderNoCompleteResult = {}
if queryMyOrderNoCompleteResult:
if "data" in queryMyOrderNoCompleteResult and queryMyOrderNoCompleteResult["data"] and "orderDBList" in queryMyOrderNoCompleteResult["data"] and queryMyOrderNoCompleteResult["data"]["orderDBList"]:
orderId = queryMyOrderNoCompleteResult["data"]["orderDBList"][0]["sequence_no"]
return orderId
elif "data" in queryMyOrderNoCompleteResult and "orderCacheDTO" in queryMyOrderNoCompleteResult["data"] and queryMyOrderNoCompleteResult["data"]["orderCacheDTO"]:
if "message" in queryMyOrderNoCompleteResult["data"]["orderCacheDTO"] and queryMyOrderNoCompleteResult["data"]["orderCacheDTO"]["message"]:
print(queryMyOrderNoCompleteResult["data"]["orderCacheDTO"]["message"]["message"])
raise ticketNumOutException(queryMyOrderNoCompleteResult["data"]["orderCacheDTO"]["message"]["message"])
else:
if "message" in queryMyOrderNoCompleteResult and queryMyOrderNoCompleteResult["message"]:
print queryMyOrderNoCompleteResult["message"]
return False
else:
return False
else:
print(u"接口 {} 无响应".format(queryMyOrderNoCompleteUrl))
def initNoComplete(self):
"""
获取订单前需要进入订单列表页获取订单列表页session
:return:
"""
self.httpClint.set_cookies(acw_tc="AQAAAEnFJnekLwwAtGHjZZCr79B6dpXk", current_captcha_type="Z")
initNoCompleteUrl = self.confUrl["initNoCompleteUrl"]
data = {"_json_att": ""}
self.httpClint.send(initNoCompleteUrl, data)
def cancelNoCompleteMyOrder(self, sequence_no):
"""
取消订单
:param sequence_no: 订单编号
:return:
"""
cancelNoCompleteMyOrderUrl = self.confUrl["cancelNoCompleteMyOrder"]
cancelNoCompleteMyOrderData = {
"sequence_no": sequence_no,
"cancel_flag": "cancel_order",
"_json_att": ""
}
cancelNoCompleteMyOrderResult = self.httpClint.send(cancelNoCompleteMyOrderUrl, cancelNoCompleteMyOrderData)
if "data" in cancelNoCompleteMyOrderResult and "existError" in cancelNoCompleteMyOrderResult["data"] and cancelNoCompleteMyOrderResult["data"]["existError"] == "N":
print(u"排队超时,已为您自动取消订单,订单编号: {0}".format(sequence_no))
time.sleep(2)
return True
else:
print(u"排队超时,取消订单失败, 订单号{0}".format(sequence_no))
def set_cdn(self):
"""
设置cdn
:return:
"""
if self.is_cdn == 1:
while True:
if self.cdn_list:
self.httpClint.cdn = self.cdn_list[random.randint(0, len(self.cdn_list)-1)]
break
else:
pass
def call_login(self, auth=False):
"""
登录回调方法
@ -676,67 +110,96 @@ class select:
else:
self.login.go_login()
def cdn_req(self, cdn):
for i in range(len(cdn)-1):
http = HTTPClient()
urls = self.confUrl["loginInit"]
start_time = datetime.datetime.now()
http.cdn = cdn[i].replace("\n", "")
rep = http.send(urls)
if rep and "message" not in rep and (datetime.datetime.now() - start_time).microseconds / 1000 < 200:
self.cdn_list.append(cdn[i].replace("\n", ""))
print(u"所有cdn解析完成...")
def cdn_certification(self):
"""
cdn 认证
:return:
"""
if self.is_cdn == 1:
CDN = CDNProxy()
all_cdn = CDN.all_cdn()
if all_cdn:
print(u"开启cdn查询")
print(u"本次待筛选cdn总数为{}".format(len(all_cdn)))
t = threading.Thread(target=self.cdn_req, args=(all_cdn,))
t.start()
else:
raise ticketConfigException(u"cdn列表为空请先加载cdn")
else:
pass
def main(self):
self.cdn_certification()
self.set_cdn()
l = liftTicketInit(session=self)
l.reqLiftTicketInit()
self.call_login()
checkUser(self).sendCheckUser()
from_station, to_station = self.station_table(self.from_station, self.to_station)
self.check_user()
time.sleep(0.1)
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()
checkUser(self).sendCheckUser()
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点将自动运行")
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(ticket.REST_TIME)
while 1:
time.sleep(1)
if time.strftime('%H:%M:%S', time.localtime(time.time())) > "06:00:00":
print(u"休息时间已过,重新开启检票功能")
if "06:00:00" < time.strftime('%H:%M:%S', time.localtime(time.time())) < "23:00:00":
print(ticket.REST_TIME_PAST)
self.call_login()
break
start_time = datetime.datetime.now()
self.submitOrderRequestImplement(from_station, to_station)
print u"正在第{0}次查询 乘车日期: {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))
self.set_cdn()
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):
train_no = queryResult.get("train_no", "")
train_date = queryResult.get("train_date", "")
stationTrainCode = queryResult.get("stationTrainCode", "")
set_type = queryResult.get("set_type", "")
secretStr = queryResult.get("secretStr", "")
leftTicket = queryResult.get("leftTicket", "")
query_from_station_name = queryResult.get("query_from_station_name", "")
query_to_station_name = queryResult.get("query_to_station_name", "")
if wrapcache.get(train_no):
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", "")
# 提交订单
if self.order_type == 1: # 快读下单
a = autoSubmitOrderRequest(session=self,
secretStr=secretStr,
train_date=train_date,
passengerTicketStr=self.passengerTicketStrList,
oldPassengerStr=self.oldPassengerStr,
train_no=train_no,
stationTrainCode=stationTrainCode,
leftTicket=leftTicket,
set_type=set_type,
query_from_station_name=query_from_station_name,
query_to_station_name=query_to_station_name,
)
a.sendAutoSubmitOrderRequest()
elif self.order_type == 2: # 普通下单
sor = submitOrderRequest(self, secretStr, from_station, to_station, train_no, set_type,
self.passengerTicketStrList, self.oldPassengerStr, train_date,
self.ticke_peoples)
sor.sendSubmitOrderRequest()
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
@ -766,6 +229,4 @@ class select:
if __name__ == '__main__':
login()
# a = select('上海', '北京')
# a.main()
pass

View File

@ -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,
}

73
inter/CheckOrderInfo.py Normal file
View File

@ -0,0 +1,73 @@
# 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])

View File

@ -0,0 +1,27 @@
# 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']

33
inter/CheckUser.py Normal file
View File

@ -0,0 +1,33 @@
# 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)

View File

@ -0,0 +1,96 @@
# 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))

View 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
}

View File

@ -0,0 +1,22 @@
# 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)

View File

@ -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,
}

109
inter/GetQueueCount.py Normal file
View File

@ -0,0 +1,109 @@
# 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)))

View File

@ -1,8 +1,13 @@
# 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}

79
inter/GetRandCode.py Normal file
View File

@ -0,0 +1,79 @@
# 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

View File

@ -0,0 +1,36 @@
# 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
}

View File

@ -1,9 +1,7 @@
# 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}

View File

@ -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

View File

@ -0,0 +1,69 @@
# 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])

202
myUrllib/MySocketUtils.py Normal file
View File

@ -0,0 +1,202 @@
# coding=utf-8
import json
import socket
import re
# s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# s.connect(('183.232.189.31', 80))
# get_str = 'GET {0} HTTP/1.1\r\nConnection: close\r\n' \
# 'Host: %s\r\n' \
# 'User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36' \
# '\r\nAccept: */*\r\n' \
# '\r\n'
# post_str = "POST {0} HTTP/1.1\r\n" \
# "Host: kyfw.12306.cn\r\n" \
# "Connection: close\r\n"\
# "Origin: https://kyfw.12306.cn\r\n" \
# "X-Requested-With: XMLHttpRequest\r\n" \
# "Referer: https://kyfw.12306.cn/otn/leftTicket/init\r\n" \
# "Accept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\n" \
# "Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n" \
# "Accept: application/json, text/javascript, */*; q=0.01\r\n" \
# "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\r\n" \
# "Content-Length: 9\r\n"\
# "Cookie: _passport_session=a459aba69761497eb31de76c27795e999613; _passport_ct=9116b2cb0bf443e1a01d22ac8c1ae449t5007; route=9036359bb8a8a461c164a04f8f50b252; BIGipServerpool_passport=200081930.50215.0000; BIGipServerotn=484704778.64545.0000\r\n\n"\
# "appid=otn\r\n"
# # s.sendall(get_str.format("https://kyfw.12306.cn/otn/login/init"))
# s.sendall(post_str.format("https://kyfw.12306.cn/passport/web/auth/uamtk"))
from config.urlConf import urls
def default_get_data():
"""
get请求默认组装字符串
需要拼接的字符串
-- url 发送请求的全连接
:return:
"""
return 'GET {0} HTTP/1.1\r\nConnection: close\r\n' \
'Host: kyfw.12306.cn\r\n' \
"Referer: {1}\r\n" \
'User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36' \
'\r\nAccept: */*\r\n' \
"Cookie: {2}\r\n\n"\
'\r\n'
# return 'GET {0} HTTP/1.1\r\nConnection: close\r\n' \
# 'Host: kyfw.12306.cn\r\n' \
# 'User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36' \
# '\r\nAccept: */*\r\n' \
# '\r\n'
def default_post_data():
"""
post请求默认组装字符串
需要拼接的字符串
-- url 发送请求的全连接
-- Referer 请求页面来源
-- Content-Length: body 长度
-- Cookie 页面请求的身份认证
-- appid 接口请求报文
:return:
"""
return "POST https://kyfw.12306.cn{0} HTTP/1.1\r\n" \
"Host: kyfw.12306.cn\r\n" \
"Connection: close\r\n"\
"Origin: https://kyfw.12306.cn\r\n" \
"X-Requested-With: XMLHttpRequest\r\n" \
"Referer: {3}\r\n" \
"Accept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\n" \
"Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n" \
"Accept: application/json, text/javascript, */*; q=0.01\r\n" \
"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\r\n" \
"Content-Length: {2}\r\n"\
"Cookie: {4}\r\n\n"\
"{1}\r\n"\
# "\r\n"
class socketUtils:
def __init__(self, host, port=80):
self.host = host
self.port = port
self.s = self.connect_socket(self.host, self.port)
def connect_socket(self, host, port):
"""
连接socket
:param host:
:param port:
:return:
"""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host if isinstance(host, str) else str(host),
port if isinstance(port, int) else int(port)))
return s
def close_s(self):
self.s.close()
# def send(self, urls, Cookie=None, data=None):
# """
# 发送请求
# :param urls:
# :param data:
# :param cookie:
# :return:
# """
# url = urls.get("req_url", "")
# Referer = urls.get("Referer", "")
# if urls.get("req_type", "get") == "post":
# Content_Length = len(data)
# Cookie = "tk=pnidlCoFy2B7wxO_X_pESbrkZFSq3OtVA_xzXwuba2a0; JSESSIONID=C6144324BFCE36AC5082E543E934E8B3; current_captcha_type=Z; _jc_save_fromDate=2018-08-03; _jc_save_fromStation=%u6DF1%u5733%2CSZQ; _jc_save_toDate=2018-08-03; _jc_save_toStation=%u957F%u6C99%2CCSQ; _jc_save_wfdc_flag=dc; ten_key=b5L6aMWfnzBm8CgQe8pcAKQsmVBS2PYH; BIGipServerpool_passport=166527498.50215.0000; BIGipServerotn=165937674.50210.0000; route=c5c62a339e7744272a54643b3be5bf64; RAIL_DEVICEID=fC-yepiUqNjsBiRvtLBXW4JqQmabCfB9QxI3FifJZK9YDRsImhJLSz4sAQ4HiGF7uQAFdFyISg6jA7KAhtpEldJV9ZMNsn6Dzm_psA5CBDwSNfiORf42w-LIRvkeGvdKFtegZwWGlkA2fVuEWKu-1xAYdCXRnsMD; RAIL_EXPIRATION=1533420302032; _jc_save_detail=true"
# if data:
# send_value = default_post_data().format(url,
# data,
# Content_Length,
# Referer,
# Cookie
# )
# print("send_value: " + send_value)
# self.s.sendall(send_value)
# else:
# self.s.sendall(default_get_data().format(url,
# Referer,
# Cookie))
# total_data = ""
# while 1:
# data = self.s.recv(1024)
# total_data += data
# if not data:
# break
# self.close_s()
# print(total_data)
# return self.recv_data(total_data)
def recv_data(self, r_data):
cookie = self.get_cookie(r_data)
status_code = self.get_status_code(r_data)
r_body = self.get_rep_body(r_data)
return {
"cookie": cookie,
"status_code": status_code,
"r_body": r_body
}
@staticmethod
def get_cookie(recv_data):
"""
提取cookie
:param recv_data:
:return:
"""
if not isinstance(recv_data, str):
recv_data = str(recv_data)
cookies_re = re.compile(r"Set-Cookie: (\S+);")
cookies = re.findall(cookies_re, recv_data)
return "; ".join(cookies)
@staticmethod
def get_status_code(recv_data):
"""
获取状态码
:return:
"""
if not isinstance(recv_data, str):
recv_data = str(recv_data)
http_code_re = re.compile(r"HTTP/1.1 (\S+) ")
status_code = re.search(http_code_re, recv_data).group(1)
return status_code
@staticmethod
def get_rep_body(recv_data):
"""
获取返回值
:param recv_data:
:return:
"""
if not isinstance(recv_data, str):
recv_data = str(recv_data)
if recv_data.find("{") != -1 and recv_data.find("}") != -1:
data = json.loads(recv_data.split("\n")[-1])
return data
else:
print(recv_data)
if __name__ == "__main__":
so = socketUtils('183.232.189.31', 80)
train_date = "2018-08-03"
from_station = "SZQ"
to_station = "CSQ"
urls["select_url"]["req_url"] = "https://kyfw.12306.cn" + urls["select_url"]["req_url"].format(train_date, from_station, to_station)
result = so.send(urls=urls["select_url"])
print(result)
so = socketUtils('183.232.189.31', 80)
data = "secretStr=Vgo534nDZiCH8NCvyEPcGepzJoRCjvYr34gKFv5CW1K1XtM6mtKHoiFPjUYvaVKoe06SMhUUpT%2FK%0AxIEIsBD4zHgJPpVyKiTPx80y6OCWhNgcKjib2LLMXMJfgTgh0RKPISjkDjVFmO9p905O%2FegDeKjp%0A1fhIeqCuYraHjNhI0PjQY39BAY4AHLzW0iGgDq8b%2FtpyOY8Td2XfIWNZJCWzgyPkNXOk0HUguB2G%0AKh2T8nlko6zb5ra%2B%2BA%3D%3D&train_date=2018-08-03&back_train_date=2018-08-03&tour_flag=dc&purpose_codes=ADULT&query_from_station_name=深圳&query_to_station_name=长沙&undefined"
result1 = so.send(urls=urls["submit_station_url"], data=data)
print(result1)
# so = socketUtils('183.232.189.31', 80)
# result = so.send(url="https://kyfw.12306.cn/passport/web/login", s_data="")
# print(result)

View File

@ -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)

View File

@ -3,4 +3,5 @@ bs4==0.0.1
PyYAML==3.12
six==1.10.0
requests==2.18.4
Pillow==5.0.0
Pillow==5.0.0
wrapcache==1.0.8

14
run.py
View File

@ -1,12 +1,16 @@
# -*- 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()
run()
# testEmail()