mirror of https://github.com/testerSunshine/12306
test version
commit
1411824016
|
@ -1,11 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="79a86edc-721f-4aad-920d-b595d0348b7f" name="Default" comment="">
|
||||
<change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/.idea/markdown-navigator.xml" />
|
||||
<change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/.idea/markdown-navigator/profiles_settings.xml" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/.idea/codeStyleSettings.xml" afterPath="$PROJECT_DIR$/.idea/codeStyleSettings.xml" />
|
||||
<list default="true" id="79a86edc-721f-4aad-920d-b595d0348b7f" name="Default" comment="test version">
|
||||
<change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/config/emailConf.py" />
|
||||
<change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/config/urlConf.py" />
|
||||
<change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/myException/UserPasswordException.py" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/tkcode" afterPath="$PROJECT_DIR$/tkcode" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/README.md" afterPath="$PROJECT_DIR$/README.md" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/config/ticketConf.py" afterPath="$PROJECT_DIR$/config/ticketConf.py" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/config/ticket_config.yaml" afterPath="$PROJECT_DIR$/config/ticket_config.yaml" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/init/login.py" afterPath="$PROJECT_DIR$/init/login.py" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/init/select_ticket_info.py" afterPath="$PROJECT_DIR$/init/select_ticket_info.py" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/myUrllib/httpUtils.py" afterPath="$PROJECT_DIR$/myUrllib/httpUtils.py" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/myUrllib/myurllib2.py" afterPath="$PROJECT_DIR$/myUrllib/myurllib2.py" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/run.py" afterPath="$PROJECT_DIR$/run.py" />
|
||||
</list>
|
||||
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
|
||||
<option name="TRACKING_ENABLED" value="true" />
|
||||
|
@ -43,7 +51,7 @@
|
|||
<entry file="file://$PROJECT_DIR$/init/login.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="2030">
|
||||
<caret line="145" column="38" lean-forward="false" selection-start-line="141" selection-start-column="7" selection-end-line="145" selection-end-column="38" />
|
||||
<caret line="145" column="28" lean-forward="false" selection-start-line="141" selection-start-column="7" selection-end-line="145" selection-end-column="28" />
|
||||
<folding>
|
||||
<element signature="e#41#54#0" expanded="true" />
|
||||
</folding>
|
||||
|
@ -77,7 +85,7 @@
|
|||
<entry file="file://$PROJECT_DIR$/config/ticketConf.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="168">
|
||||
<caret line="12" column="18" lean-forward="true" selection-start-line="12" selection-start-column="18" selection-end-line="12" selection-end-column="18" />
|
||||
<caret line="12" column="7" lean-forward="true" selection-start-line="12" selection-start-column="7" selection-end-line="12" selection-end-column="7" />
|
||||
<folding>
|
||||
<element signature="e#46#55#0" expanded="true" />
|
||||
</folding>
|
||||
|
@ -85,11 +93,11 @@
|
|||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="select_ticket_info.py" pinned="false" current-in-tab="true">
|
||||
<file leaf-file-name="select_ticket_info.py" pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/init/select_ticket_info.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="527">
|
||||
<caret line="240" column="41" lean-forward="false" selection-start-line="240" selection-start-column="41" selection-end-line="240" selection-end-column="41" />
|
||||
<state relative-caret-position="-456">
|
||||
<caret line="204" column="16" lean-forward="true" selection-start-line="204" selection-start-column="16" selection-end-line="204" selection-end-column="16" />
|
||||
<folding>
|
||||
<element signature="e#23#34#0" expanded="true" />
|
||||
</folding>
|
||||
|
@ -97,10 +105,10 @@
|
|||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="ticket_config.yaml" pinned="false" current-in-tab="false">
|
||||
<file leaf-file-name="ticket_config.yaml" pinned="false" current-in-tab="true">
|
||||
<entry file="file://$PROJECT_DIR$/config/ticket_config.yaml">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="400">
|
||||
<state relative-caret-position="44">
|
||||
<caret line="56" column="9" lean-forward="false" selection-start-line="56" selection-start-column="9" selection-end-line="56" selection-end-column="9" />
|
||||
<folding />
|
||||
</state>
|
||||
|
@ -250,6 +258,8 @@
|
|||
<foldersAlwaysOnTop value="true" />
|
||||
</navigator>
|
||||
<panes>
|
||||
<pane id="Scope" />
|
||||
<pane id="Scratches" />
|
||||
<pane id="ProjectPane">
|
||||
<subPane>
|
||||
<expand>
|
||||
|
@ -281,8 +291,6 @@
|
|||
<select />
|
||||
</subPane>
|
||||
</pane>
|
||||
<pane id="Scratches" />
|
||||
<pane id="Scope" />
|
||||
</panes>
|
||||
</component>
|
||||
<component name="PropertiesComponent">
|
||||
|
@ -844,15 +852,15 @@
|
|||
<frame x="0" y="0" width="1440" height="900" extended-state="0" />
|
||||
<editor active="true" />
|
||||
<layout>
|
||||
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.17238913" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
|
||||
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.17453505" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
|
||||
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="10" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.5465538" sideWeight="0.50429183" order="14" side_tool="true" content_ui="tabs" />
|
||||
<window_info id="Database" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.54413545" sideWeight="0.49570817" order="4" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32889965" sideWeight="0.5" order="15" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Python Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.48004836" sideWeight="0.5" order="16" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Python Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.48004836" sideWeight="0.5" order="16" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.24964234" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32889965" sideWeight="0.5" order="17" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.32889965" sideWeight="0.5" order="17" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.7315599" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.3297568" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
|
||||
<window_info id="Data View" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.3297568" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
||||
|
@ -1086,7 +1094,7 @@
|
|||
<entry file="file://$PROJECT_DIR$/config/ticketConf.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="168">
|
||||
<caret line="12" column="18" lean-forward="true" selection-start-line="12" selection-start-column="18" selection-end-line="12" selection-end-column="18" />
|
||||
<caret line="12" column="7" lean-forward="true" selection-start-line="12" selection-start-column="7" selection-end-line="12" selection-end-column="7" />
|
||||
<folding>
|
||||
<element signature="e#46#55#0" expanded="true" />
|
||||
</folding>
|
||||
|
@ -1096,7 +1104,7 @@
|
|||
<entry file="file://$PROJECT_DIR$/init/login.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="2030">
|
||||
<caret line="145" column="38" lean-forward="false" selection-start-line="141" selection-start-column="7" selection-end-line="145" selection-end-column="38" />
|
||||
<caret line="145" column="28" lean-forward="false" selection-start-line="141" selection-start-column="7" selection-end-line="145" selection-end-column="28" />
|
||||
<folding>
|
||||
<element signature="e#41#54#0" expanded="true" />
|
||||
</folding>
|
||||
|
@ -1121,23 +1129,23 @@
|
|||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/config/ticket_config.yaml">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="400">
|
||||
<caret line="56" column="9" lean-forward="false" selection-start-line="56" selection-start-column="9" selection-end-line="56" selection-end-column="9" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/init/select_ticket_info.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="527">
|
||||
<caret line="240" column="41" lean-forward="false" selection-start-line="240" selection-start-column="41" selection-end-line="240" selection-end-column="41" />
|
||||
<state relative-caret-position="-456">
|
||||
<caret line="204" column="16" lean-forward="true" selection-start-line="204" selection-start-column="16" selection-end-line="204" selection-end-column="16" />
|
||||
<folding>
|
||||
<element signature="e#23#34#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/config/ticket_config.yaml">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="44">
|
||||
<caret line="56" column="9" lean-forward="false" selection-start-line="56" selection-start-column="9" selection-end-line="56" selection-end-column="9" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</component>
|
||||
</project>
|
102
README.md
102
README.md
|
@ -3,10 +3,55 @@
|
|||
- python版本支持
|
||||
- 2.7
|
||||
- 依赖库
|
||||
- 依赖打码兔 需要去打码兔注册账号,打码兔账号地址:http://www.dama2.com,一般充值1元就够用了
|
||||
- 依赖打码兔 需要去打码兔注册(用户)账号,打码兔账号地址:http://www.dama2.com,一般充值1元就够用了,充值打码兔之后,首次运行是需要到官网黑白名单授权
|
||||
- 项目依赖包 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-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: 乘客 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"
|
||||
```
|
||||
|
||||
- 项目开始
|
||||
- 修改config/ticket_config.yaml文件,按照提示更改自己想要的信息
|
||||
- 运行根目录run.py,即可开始
|
||||
|
@ -26,6 +71,25 @@
|
|||
- 本软件只供学习交流使用,务作为商业用途,交流群:286271084
|
||||
- 能为你抢到一张回家的票,是我最大的心愿
|
||||
|
||||
- 成功log,如果是购票失败的,请带上失败的log给我,我尽力帮你挑,也可加群一起交流,程序只是加速买票的过程,并不一定能买到票
|
||||
```
|
||||
正在第355次查询 乘车日期: 2018-02-12 车次G4741,G2365,G1371,G1377,G1329 查询无票 代理设置 无 总耗时429ms
|
||||
车次: G4741 始发车站: 上海 终点站: 邵阳 二等座:有
|
||||
正在尝试提交订票...
|
||||
尝试提交订单...
|
||||
出票成功
|
||||
排队成功, 当前余票还剩余: 359 张
|
||||
正在使用自动识别验证码功能
|
||||
验证码通过,正在提交订单
|
||||
提交订单成功!
|
||||
排队等待时间预计还剩 -12 ms
|
||||
排队等待时间预计还剩 -6 ms
|
||||
排队等待时间预计还剩 -7 ms
|
||||
排队等待时间预计还剩 -4 ms
|
||||
排队等待时间预计还剩 -4 ms
|
||||
恭喜您订票成功,订单号为:EB52743573, 请立即打开浏览器登录12306,访问‘未完成订单’,在30分钟内完成支付!
|
||||
```
|
||||
|
||||
- 2017.5.13跟新
|
||||
- 增加登陆错误判断(密码错误&ip校验)
|
||||
- 修改queryOrderWaitTime,校验orderId字段bug,校验msg字段bug,校验messagesbug
|
||||
|
@ -71,3 +135,39 @@
|
|||
- 优化查票流程
|
||||
- 修改二等座的余票数返回为字符串的问题
|
||||
- 优化订单查询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更新,好久没跟新了,群里的小伙伴说登录不行了,今晚抽空改了一版登录,妥妥的
|
||||
- 更新新版登录功能,经测试,更稳定有高效
|
||||
- 优化手动打码功能
|
||||
- 更新请求第三方库
|
||||
- 优化若干代码,小伙伴尽情的放肆起来
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
# -*- coding: utf8 -*-
|
||||
__author__ = 'MR.wen'
|
||||
from email.header import Header
|
||||
from email.mime.text import MIMEText
|
||||
from config.ticketConf import _get_yaml
|
||||
import smtplib
|
||||
|
||||
|
||||
def sendEmail(msg):
|
||||
"""
|
||||
邮件通知
|
||||
:param str: email content
|
||||
:return:
|
||||
"""
|
||||
email_conf = _get_yaml()
|
||||
is_email = email_conf["email_conf"]["is_email"]
|
||||
if is_email:
|
||||
sender = email_conf["email_conf"]["email"]
|
||||
receiver = email_conf["email_conf"]["notice_email_list"]
|
||||
subject = '恭喜,您已订票成功'
|
||||
username = email_conf["email_conf"]["username"]
|
||||
password = email_conf["email_conf"]["password"]
|
||||
host = email_conf["email_conf"]["host"]
|
||||
s = "{0}".format(msg)
|
||||
|
||||
msg = MIMEText(s, 'text', 'utf-8') # 中文需参数‘utf-8’,单字节字符不需要
|
||||
msg['Subject'] = Header(subject, 'utf-8')
|
||||
msg['From'] = sender
|
||||
msg['To'] = receiver
|
||||
|
||||
smtp = smtplib.SMTP_SSL()
|
||||
smtp.connect(host)
|
||||
smtp.login(username, password)
|
||||
smtp.sendmail(sender, receiver.split(","), msg.as_string())
|
||||
smtp.quit()
|
||||
print("邮件已通知, 请查收")
|
||||
else:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sendEmail(1)
|
|
@ -6,7 +6,6 @@ import yaml
|
|||
import PyQt5
|
||||
|
||||
|
||||
|
||||
def _get_yaml():
|
||||
"""
|
||||
解析yaml
|
||||
|
|
|
@ -22,40 +22,67 @@
|
|||
#ticke_peoples: 乘客
|
||||
#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"
|
||||
|
||||
|
||||
set:
|
||||
station_date: "2018-02-07"
|
||||
station_date: "2018-02-12"
|
||||
station_trains:
|
||||
- "G4933"
|
||||
- "G2365"
|
||||
- "G1371"
|
||||
- "G1377"
|
||||
- "G1329"
|
||||
# - "K4300"
|
||||
# - "K5226"
|
||||
# - "K7772"
|
||||
# - "G1329"
|
||||
# - "G1359"
|
||||
# - "G1361"
|
||||
# - "G1373"
|
||||
# - "G1363"
|
||||
from_station: "上海"
|
||||
# - "G4933"
|
||||
from_station: "昆山"
|
||||
to_station: "长沙"
|
||||
set_type:
|
||||
- "二等座"
|
||||
is_more_ticket: True
|
||||
ticke_peoples:
|
||||
- "文贤平"
|
||||
# - "梁敏"
|
||||
- "宋倩倩"
|
||||
# - "彭淑杰"
|
||||
12306count:
|
||||
# - uesr: ""
|
||||
# - pwd: "649823049lilymin"
|
||||
- uesr: "931128603@qq.com"
|
||||
- pwd: "QWERTY"
|
||||
# - pwd: "apple1995"
|
||||
- uesr: ""
|
||||
- pwd: "songyu1995"
|
||||
|
||||
select_refresh_interval: 0.1
|
||||
expect_refresh_interval: 0.1
|
||||
expect_refresh_interval: 0.3
|
||||
ticket_black_list_time: 3
|
||||
is_aotu_code: True
|
||||
is_aotu_code: False
|
||||
#enable_proxy: False
|
||||
|
||||
damatu:
|
||||
uesr: ""
|
||||
pwd: "wen1995"
|
||||
|
||||
email_conf:
|
||||
is_email: False
|
||||
email: "@qq.com "
|
||||
notice_email_list: "@qq.com"
|
||||
username: ""
|
||||
password: "xwopwxbkupbqbfgb"
|
||||
host: "smtp.qq.com"
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
import random
|
||||
|
||||
urls = {
|
||||
"auth": {
|
||||
"req_url": "https://kyfw.12306.cn/passport/web/auth/uamtk",
|
||||
"req_type": "post"
|
||||
},
|
||||
"login": {
|
||||
"req_url": "https://kyfw.12306.cn/passport/web/login",
|
||||
"req_type": "post"
|
||||
},
|
||||
"getCodeImg": {
|
||||
"req_url": "https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand&{0}".format(random.random()),
|
||||
"req_type": "get"
|
||||
},
|
||||
"codeCheck": {
|
||||
"req_url": "https://kyfw.12306.cn/passport/captcha/captcha-check",
|
||||
"req_type": "post"
|
||||
},
|
||||
"loginInit": {
|
||||
"req_url": "https://kyfw.12306.cn/otn/login/init",
|
||||
"req_type": "get"
|
||||
},
|
||||
"getUserInfo": {
|
||||
"req_url": "https://kyfw.12306.cn/otn/index/initMy12306",
|
||||
"req_type": "get"
|
||||
},
|
||||
"userLogin": {
|
||||
"req_url": "https://kyfw.12306.cn/otn/login/userLogin",
|
||||
"req_type": "get"
|
||||
},
|
||||
"uamauthclient": {
|
||||
"req_url": "https://kyfw.12306.cn/otn/uamauthclient",
|
||||
"req_type": "post"
|
||||
},
|
||||
"initdc_url": {
|
||||
"req_url": "https://kyfw.12306.cn/otn/confirmPassenger/initDc",
|
||||
"req_type": "get"
|
||||
},
|
||||
"get_passengerDTOs": {
|
||||
"req_url": "https://kyfw.12306.cn/otn/confirmPassenger/getPassengerDTOs",
|
||||
"req_type": "post"
|
||||
},
|
||||
"select_url": {
|
||||
"req_url": "https://kyfw.12306.cn/otn/leftTicket/queryZ?leftTicketDTO.train_date={0}&leftTicketDTO.from_station={1}&leftTicketDTO.to_station={2}&purpose_codes=ADULT",
|
||||
"req_type": "post"
|
||||
},
|
||||
"check_user_url": {
|
||||
"req_url": "https://kyfw.12306.cn/otn/login/checkUser",
|
||||
"req_type": "post"
|
||||
},
|
||||
"submit_station_url": {
|
||||
"req_url": "https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest",
|
||||
"req_type": "post"
|
||||
},
|
||||
"checkOrderInfoUrl": {
|
||||
"req_url": "https://kyfw.12306.cn/otn/confirmPassenger/checkOrderInfo",
|
||||
"req_type": "post"
|
||||
},
|
||||
"getQueueCountUrl": {
|
||||
"req_url": "https://kyfw.12306.cn/otn/confirmPassenger/getQueueCount",
|
||||
"req_type": "post"
|
||||
},
|
||||
"checkQueueOrderUrl": {
|
||||
"req_url": "https://kyfw.12306.cn/otn/confirmPassenger/confirmSingleForQueue",
|
||||
"req_type": "post"
|
||||
},
|
||||
"checkRandCodeAnsyn": {
|
||||
"req_url": "https://kyfw.12306.cn/otn/passcodeNew/checkRandCodeAnsyn",
|
||||
"req_type": "post"
|
||||
},
|
||||
"codeImgByOrder": {
|
||||
"req_url": "https://kyfw.12306.cn/otn/passcodeNew/getPassCodeNew?module=passenger&rand=randp&%s" % random.random(),
|
||||
"req_type": "post"
|
||||
},
|
||||
"queryOrderWaitTimeUrl": {
|
||||
"req_url": "https://kyfw.12306.cn/otn/confirmPassenger/queryOrderWaitTime",
|
||||
"req_type": "post"
|
||||
},
|
||||
"queryMyOrderNoCompleteUrl": {
|
||||
"req_url": "https://kyfw.12306.cn/otn/queryOrder/queryMyOrderNoComplete",
|
||||
"req_type": "post"
|
||||
},
|
||||
"initNoCompleteUrl": {
|
||||
"req_url": "https://kyfw.12306.cn/otn/queryOrder/initNoComplete",
|
||||
"req_type": "post"
|
||||
}
|
||||
|
||||
}
|
363
init/login.py
363
init/login.py
|
@ -3,202 +3,205 @@
|
|||
import random
|
||||
import json
|
||||
import re
|
||||
import socket
|
||||
from time import sleep
|
||||
|
||||
from config.ticketConf import _get_yaml
|
||||
from PIL import Image
|
||||
from damatuCode.damatuWeb import DamatuApi
|
||||
from myException.UserPasswordException import UserPasswordException
|
||||
from myUrllib import myurllib2
|
||||
|
||||
codeimg = 'https://kyfw.12306.cn/otn/passcodeNew/getPassCodeNew?module=login&rand=sjrand&%s' % random.random()
|
||||
|
||||
class GoLogin:
|
||||
def __init__(self, httpClint, urlConf):
|
||||
self.httpClint = httpClint
|
||||
self.randCode = ""
|
||||
self.urlConf = urlConf
|
||||
|
||||
def cookietp():
|
||||
stoidinput("获取Cookie")
|
||||
Url = "https://kyfw.12306.cn/otn/login/init"
|
||||
myurllib2.get(Url)
|
||||
# for index, c in enumerate(myurllib2.cookiejar):
|
||||
# stoidinput(c)
|
||||
def cookietp(self):
|
||||
print("正在获取cookie")
|
||||
url = self.urlConf["loginInit"]["req_url"]
|
||||
self.httpClint.send(url)
|
||||
# Url = "https://kyfw.12306.cn/otn/login/init"
|
||||
# myurllib2.get(Url)
|
||||
# for index, c in enumerate(myurllib2.cookiejar):
|
||||
# stoidinput(c)
|
||||
|
||||
|
||||
def readImg():
|
||||
"""
|
||||
增加手动打码,只是登录接口,完全不用担心提交订单效率
|
||||
思路
|
||||
1.调用PIL显示图片
|
||||
2.图片位置说明,验证码图片中每个图片代表一个下标,依次类推,1,2,3,4,5,6,7,8
|
||||
3.控制台输入对应下标,按照英文逗号分开,即可手动完成打码,
|
||||
:return:
|
||||
"""
|
||||
|
||||
global randCode
|
||||
stoidinput("下载验证码...")
|
||||
img_path = './tkcode'
|
||||
result = myurllib2.get(codeimg)
|
||||
try:
|
||||
open(img_path, 'wb').write(result)
|
||||
if _get_yaml()["is_aotu_code"]:
|
||||
randCode = DamatuApi(_get_yaml()["damatu"]["uesr"], _get_yaml()["damatu"]["pwd"], img_path).main()
|
||||
else:
|
||||
img = Image.open('./tkcode')
|
||||
img.show()
|
||||
codexy()
|
||||
except OSError as e:
|
||||
print (e)
|
||||
pass
|
||||
|
||||
|
||||
def stoidinput(text):
|
||||
"""
|
||||
正常信息输出
|
||||
:param text:
|
||||
:return:
|
||||
"""
|
||||
print "\033[34m[*]\033[0m %s " % text
|
||||
|
||||
|
||||
def errorinput(text):
|
||||
"""
|
||||
错误信息输出
|
||||
:param text:
|
||||
:return:
|
||||
"""
|
||||
print "\033[32m[!]\033[0m %s " % text
|
||||
return False
|
||||
|
||||
|
||||
def codexy():
|
||||
"""
|
||||
获取验证码
|
||||
:return: str
|
||||
"""
|
||||
|
||||
Ofset = raw_input("[*] 请输入验证码: ")
|
||||
select = Ofset.split(',')
|
||||
global randCode
|
||||
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:
|
||||
def readImg(self):
|
||||
"""
|
||||
增加手动打码,只是登录接口,完全不用担心提交订单效率
|
||||
思路
|
||||
1.调用PIL显示图片
|
||||
2.图片位置说明,验证码图片中每个图片代表一个下标,依次类推,1,2,3,4,5,6,7,8
|
||||
3.控制台输入对应下标,按照英文逗号分开,即可手动完成打码,
|
||||
:return:
|
||||
"""
|
||||
print ("下载验证码...")
|
||||
codeimgUrl = self.urlConf["getCodeImg"]["req_url"]
|
||||
img_path = './tkcode'
|
||||
result = self.httpClint.send(codeimgUrl)
|
||||
try:
|
||||
open(img_path, 'wb').write(result)
|
||||
if _get_yaml()["is_aotu_code"]:
|
||||
self.randCode = DamatuApi(_get_yaml()["damatu"]["uesr"], _get_yaml()["damatu"]["pwd"], img_path).main()
|
||||
else:
|
||||
img = Image.open('./tkcode')
|
||||
img.show()
|
||||
self.codexy()
|
||||
except OSError as e:
|
||||
print (e)
|
||||
pass
|
||||
post.append(offsetsX)
|
||||
post.append(offsetsY)
|
||||
randCode = str(post).replace(']', '').replace('[', '').replace("'", '').replace(' ', '')
|
||||
|
||||
def codexy(self):
|
||||
"""
|
||||
获取验证码
|
||||
:return: str
|
||||
"""
|
||||
|
||||
def login(user, passwd):
|
||||
"""
|
||||
登陆
|
||||
:param user: 账户名
|
||||
:param passwd: 密码
|
||||
:return:
|
||||
"""
|
||||
login_num = 0
|
||||
while True:
|
||||
cookietp()
|
||||
readImg()
|
||||
login_num += 1
|
||||
randurl = 'https://kyfw.12306.cn/otn/passcodeNew/checkRandCodeAnsyn'
|
||||
logurl = 'https://kyfw.12306.cn/otn/login/loginAysnSuggest'
|
||||
surl = 'https://kyfw.12306.cn/otn/login/userLogin'
|
||||
randdata = {
|
||||
"randCode": randCode,
|
||||
"rand": "sjrand"
|
||||
Ofset = raw_input("请输入验证码: ")
|
||||
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)
|
||||
self.randCode = str(post).replace(']', '').replace('[', '').replace("'", '').replace(' ', '')
|
||||
|
||||
def auth(self):
|
||||
"""认证"""
|
||||
authUrl = self.urlConf["auth"]["req_url"]
|
||||
authData = {"appid": "otn"}
|
||||
tk = self.httpClint.send(authUrl, authData)
|
||||
return tk
|
||||
|
||||
def codeCheck(self):
|
||||
"""
|
||||
验证码校验
|
||||
:return:
|
||||
"""
|
||||
codeCheck = self.urlConf["codeCheck"]["req_url"]
|
||||
codeCheckData = {
|
||||
"answer": self.randCode,
|
||||
"rand": "sjrand",
|
||||
"login_site": "E"
|
||||
}
|
||||
logdata = {
|
||||
"loginUserDTO.user_name": user,
|
||||
"userDTO.password": passwd,
|
||||
"randCode": randCode
|
||||
}
|
||||
ldata = {
|
||||
"_json_att": None
|
||||
}
|
||||
fresult = json.loads(myurllib2.Post(randurl, randdata), encoding='utf8')
|
||||
checkcode = fresult['data']['msg']
|
||||
if checkcode == 'FALSE':
|
||||
errorinput("验证码有误,第{}次尝试重试".format(login_num))
|
||||
fresult = self.httpClint.send(codeCheck, codeCheckData)
|
||||
if "result_code" in fresult and fresult["result_code"] == "4":
|
||||
print ("验证码通过,开始登录..")
|
||||
return True
|
||||
else:
|
||||
stoidinput("验证码通过,开始登录..")
|
||||
if "result_message" in fresult:
|
||||
print(fresult["result_message"])
|
||||
sleep(1)
|
||||
try:
|
||||
tresult = json.loads(myurllib2.Post(logurl, logdata), encoding='utf8')
|
||||
if 'data' not in tresult:
|
||||
errorinput("登录失败: %s" % tresult['messages'][0])
|
||||
# elif "messages" in tresult and tresult["messages"][0].find("密码输入错误") is not -1:
|
||||
# errorinput("登陆失败:{}".format(tresult["messages"][0]))
|
||||
# break
|
||||
elif 'messages' in tresult and tresult['messages']:
|
||||
messages = tresult['messages'][0]
|
||||
if messages.find("密码输入错误") is not -1:
|
||||
errorinput("登陆失败:{}".format(tresult["messages"][0]))
|
||||
self.httpClint.del_cookies()
|
||||
|
||||
def baseLogin(self, user, passwd):
|
||||
"""
|
||||
登录过程
|
||||
:param user:
|
||||
:param passwd:
|
||||
:return: 权限校验码
|
||||
"""
|
||||
logurl = self.urlConf["login"]["req_url"]
|
||||
logData = {
|
||||
"username": user,
|
||||
"password": passwd,
|
||||
"appid": "otn"
|
||||
}
|
||||
tresult = self.httpClint.send(logurl, logData)
|
||||
if 'result_code' in tresult and tresult["result_code"] == 0:
|
||||
print ("登录成功")
|
||||
tk = self.auth()
|
||||
if "newapptk" in tk and tk["newapptk"]:
|
||||
return tk["newapptk"]
|
||||
else:
|
||||
return False
|
||||
elif 'result_message' in tresult and tresult['result_message']:
|
||||
messages = tresult['result_message']
|
||||
if messages.find("密码输入错误") is not -1:
|
||||
raise UserPasswordException("{0}".format(messages))
|
||||
else:
|
||||
print ("登录失败: {0}".format("".join(tresult)))
|
||||
print ("尝试重新登陆")
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
def getUserName(self, uamtk):
|
||||
"""
|
||||
登录成功后,显示用户名
|
||||
:return:
|
||||
"""
|
||||
if not uamtk:
|
||||
return "权限校验码不能为空"
|
||||
else:
|
||||
uamauthclientUrl = self.urlConf["uamauthclient"]["req_url"]
|
||||
data = {"tk": uamtk}
|
||||
uamauthclientResult = self.httpClint.send(uamauthclientUrl, data)
|
||||
if "result_code" in uamauthclientResult and uamauthclientResult["result_code"] == 0:
|
||||
print("欢迎 {} 登录".format(uamauthclientResult["username"]))
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def go_login(self):
|
||||
"""
|
||||
登陆
|
||||
:param user: 账户名
|
||||
:param passwd: 密码
|
||||
:return:
|
||||
"""
|
||||
user, passwd = _get_yaml()["set"]["12306count"][0]["uesr"], _get_yaml()["set"]["12306count"][1]["pwd"]
|
||||
login_num = 0
|
||||
while True:
|
||||
self.cookietp()
|
||||
self.httpClint.set_cookies(_jc_save_wfdc_flag="dc", _jc_save_fromStation="%u4E0A%u6D77%u8679%u6865%2CAOH", _jc_save_toStation="%u5170%u5DDE%u897F%2CLAJ", _jc_save_fromDate="2018-02-14", _jc_save_toDate="2018-01-16", RAIL_DEVICEID="EN_3_EGSe2GWGHXJeCkFQ52kHvNCrNlkz9n1GOqqQ1wR0i98WsD8Gj-a3YHZ-XYKeESWgCiJyyucgSwkFOzVHhHqfpidLPcm2vK9n83uzOPuShO3Pl4lCydAtQu4BdFqz-RVmiduNFixrcrN_Ny43135JiEtqLaI")
|
||||
self.readImg()
|
||||
login_num += 1
|
||||
self.auth()
|
||||
if self.codeCheck():
|
||||
uamtk = self.baseLogin(user, passwd)
|
||||
if uamtk:
|
||||
if self.getUserName(uamtk):
|
||||
break
|
||||
else:
|
||||
errorinput("登录失败: %s" % tresult['messages'][0])
|
||||
stoidinput("尝试重新登陆")
|
||||
else:
|
||||
stoidinput("登录成功")
|
||||
myurllib2.Post(surl, ldata)
|
||||
getUserinfo()
|
||||
break
|
||||
except ValueError as e:
|
||||
errorinput(e)
|
||||
sleep(1)
|
||||
|
||||
def logout(self):
|
||||
url = 'https://kyfw.12306.cn/otn/login/loginOut'
|
||||
result = myurllib2.get(url)
|
||||
if result:
|
||||
print ("已退出")
|
||||
else:
|
||||
print ("退出失败")
|
||||
|
||||
|
||||
def getUserinfo():
|
||||
"""
|
||||
登录成功后,显示用户名
|
||||
:return:
|
||||
"""
|
||||
url = 'https://kyfw.12306.cn/otn/modifyUser/initQueryUserInfo'
|
||||
data = dict(_json_att=None)
|
||||
result = myurllib2.Post(url, data)
|
||||
userinfo = result
|
||||
name = r'<input name="userDTO.loginUserDTO.user_name" style="display:none;" type="text" value="(\S+)" />'
|
||||
try:
|
||||
stoidinput("欢迎 %s 登录" % re.search(name, result).group(1))
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
|
||||
def main():
|
||||
login(_get_yaml()["set"]["12306count"][0]["uesr"], _get_yaml()["set"]["12306count"][1]["pwd"])
|
||||
|
||||
|
||||
def logout():
|
||||
url = 'https://kyfw.12306.cn/otn/login/loginOut'
|
||||
result = myurllib2.get(url)
|
||||
if result:
|
||||
stoidinput("已退出")
|
||||
else:
|
||||
errorinput("退出失败")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
# logout()
|
||||
# if __name__ == "__main__":
|
||||
# # main()
|
||||
# # logout()
|
|
@ -3,20 +3,25 @@ import json
|
|||
import datetime
|
||||
import random
|
||||
import re
|
||||
import threading
|
||||
import socket
|
||||
import urllib
|
||||
import sys
|
||||
import time
|
||||
import Queue
|
||||
from collections import OrderedDict
|
||||
|
||||
from config import urlConf
|
||||
from init import login
|
||||
|
||||
from config.emailConf import sendEmail
|
||||
from config.ticketConf import _get_yaml
|
||||
from damatuCode.damatuWeb import DamatuApi
|
||||
from init.login import GoLogin
|
||||
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 import myurllib2
|
||||
from myUrllib.httpUtils import HTTPClient
|
||||
|
||||
reload(sys)
|
||||
sys.setdefaultencoding('utf-8')
|
||||
|
@ -33,8 +38,9 @@ class select:
|
|||
self.user_info = ""
|
||||
self.secretStr = ""
|
||||
self.ticket_black_list = dict()
|
||||
self.submitQueue = Queue.Queue(5)
|
||||
self.ticket_skip_time = dict()
|
||||
self.is_check_user = dict()
|
||||
self.httpClint = HTTPClient()
|
||||
self.confUrl = urlConf.urls
|
||||
|
||||
def get_ticket_info(self):
|
||||
"""
|
||||
|
@ -53,7 +59,7 @@ class select:
|
|||
expect_refresh_interval = ticket_info_config["expect_refresh_interval"]
|
||||
ticket_black_list_time = ticket_info_config["ticket_black_list_time"]
|
||||
print "*"*20
|
||||
print "当前配置:出发站:{0}\n到达站:{1}\n乘车日期:{2}\n坐席:{3}\n是否有票自动提交:{4}\n乘车人:{5}\n刷新间隔:{6}\n候选购买车次:{7}\n未开始刷票间隔时间:{8}\n僵尸票关小黑屋时长:{9}".format\
|
||||
print "当前配置:出发站:{0}\n到达站:{1}\n乘车日期:{2}\n坐席:{3}\n是否有票自动提交:{4}\n乘车人:{5}\n刷新间隔:{6}\n候选购买车次:{7}\n未开始刷票间隔时间:{8}\n僵尸票关小黑屋时长:{9}\n".format\
|
||||
(
|
||||
from_station,
|
||||
to_station,
|
||||
|
@ -135,12 +141,11 @@ class select:
|
|||
获取提交车票请求token
|
||||
:return: token
|
||||
"""
|
||||
initdc_url = 'https://kyfw.12306.cn/otn/confirmPassenger/initDc'
|
||||
initdc_result = myurllib2.get(initdc_url)
|
||||
initdc_url = self.confUrl["initdc_url"]["req+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=(\{.+\})?')
|
||||
# if token_name and ticketInfoForPassengerForm_name and order_request_params_name:
|
||||
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)
|
||||
|
@ -158,15 +163,14 @@ class select:
|
|||
获取乘客信息
|
||||
:return:
|
||||
"""
|
||||
get_passengerDTOs = 'https://kyfw.12306.cn/otn/confirmPassenger/getPassengerDTOs'
|
||||
get_passengerDTOs = self.confUrl["get_passengerDTOs"]["req_url"]
|
||||
get_data = {
|
||||
'_json_att': None,
|
||||
'REPEAT_SUBMIT_TOKEN': self.token
|
||||
}
|
||||
jsonData = json.loads(myurllib2.Post(get_passengerDTOs, get_data))
|
||||
jsonData = self.httpClint.send(get_passengerDTOs, get_data)
|
||||
if 'data' in jsonData and jsonData['data'] and 'normal_passengers' in jsonData['data'] and jsonData['data'][
|
||||
'normal_passengers']:
|
||||
# return 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] # 如果配置乘车人没有在账号,则默认返回第一个用户
|
||||
|
@ -179,25 +183,13 @@ class select:
|
|||
print("未查找到常用联系人")
|
||||
raise PassengerUserException("未查找到常用联系人,请先添加联系人在试试")
|
||||
|
||||
def leftTicketLog(self, from_station, to_station):
|
||||
"""
|
||||
模拟进入车次列表页
|
||||
:param from_station:
|
||||
:param to_station:
|
||||
:return:
|
||||
"""
|
||||
leftTicketLogUrl = 'https://kyfw.12306.cn/otn/leftTicket/log?leftTicketDTO.train_date={0}&leftTicketDTO.from_station={1}&leftTicketDTO.to_station={2}&purpose_codes=ADULT'.format(
|
||||
self.station_date, from_station, to_station)
|
||||
leftTicketLog = json.loads(myurllib2.get(leftTicketLogUrl), encoding='utf-8')
|
||||
if "status" in leftTicketLog and leftTicketLog["status"] is True:
|
||||
return True
|
||||
else:
|
||||
if "message" in leftTicketLog and leftTicketLog["message"]:
|
||||
print leftTicketLog["message"]
|
||||
elif "validateMessages" in leftTicketLog and leftTicketLog["validateMessages"]:
|
||||
print leftTicketLog["validateMessages"]
|
||||
def submitOrderRequestFunc(self, from_station, to_station, station_date=None):
|
||||
select_url = self.confUrl["select_url"]["req_url"].format(
|
||||
self.station_date if station_date is None else station_date, from_station, to_station)
|
||||
station_ticket = self.httpClint.send(select_url)
|
||||
return station_ticket
|
||||
|
||||
def submitOrderRequest(self, from_station, to_station):
|
||||
def submitOrderRequestImplement(self, from_station, to_station,):
|
||||
"""
|
||||
提交车次信息
|
||||
车次对应字典
|
||||
|
@ -212,8 +204,7 @@ class select:
|
|||
} 参照station_seat()方法
|
||||
:return:
|
||||
"""
|
||||
select_url = 'https://kyfw.12306.cn/otn/leftTicket/queryZ?leftTicketDTO.train_date={0}&leftTicketDTO.from_station={1}&leftTicketDTO.to_station={2}&purpose_codes=ADULT'.format(self.station_date, from_station, to_station)
|
||||
station_ticket = json.loads(myurllib2.get(select_url), encoding='utf-8')
|
||||
station_ticket = self.submitOrderRequestFunc(from_station, to_station)
|
||||
value = station_ticket['data']
|
||||
if not value:
|
||||
print ('{0}-{1} 车次坐席查询为空...'.format(self.from_station, self.to_station))
|
||||
|
@ -234,13 +225,16 @@ class select:
|
|||
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("该车次{} 正在被关小黑屋,跳过此车次".format(train_no))
|
||||
break
|
||||
if self.ticket_skip_time.has_key(train_no) and (datetime.datetime.now() - self.ticket_skip_time[train_no]).seconds < 10:
|
||||
# 判断离上次车次订票时间,如果间隔太小,则跳过,如果想不停地疯狂提交,那请设置99999,就无等待了
|
||||
break
|
||||
else:
|
||||
self.submitQueue.put({"obj": self, "train_no": train_no, "seat": self._station_seat[j].encode("utf8")})
|
||||
print ('正在尝试提交订票...')
|
||||
self.ticket_skip_time[train_no] = 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()
|
||||
if self.checkOrderInfo(train_no, self._station_seat[j].encode("utf8")):
|
||||
break
|
||||
else:
|
||||
pass
|
||||
else:
|
||||
|
@ -254,18 +248,23 @@ class select:
|
|||
检查用户是否达到订票条件
|
||||
:return:
|
||||
"""
|
||||
check_user_url = 'https://kyfw.12306.cn/otn/login/checkUser'
|
||||
check_user_url = self.confUrl["check_user_url"]["req_url"]
|
||||
data = dict(_json_att=None)
|
||||
check_user = json.loads(myurllib2.Post(check_user_url, data), encoding='utf-8')
|
||||
check_user = self.httpClint.send(check_user_url, data)
|
||||
check_user_flag = check_user['data']['flag']
|
||||
if check_user_flag is True:
|
||||
print ('尝试提交订单...')
|
||||
return True
|
||||
else:
|
||||
if check_user['messages']:
|
||||
print ('用户检查失败:%s,可能未登录,可能session已经失效' % check_user['messages'][0])
|
||||
print ('正在尝试重新登录')
|
||||
self.call_login()
|
||||
self.is_check_user["user_time"] = datetime.datetime.now()
|
||||
else:
|
||||
print ('用户检查失败: %s,可能未登录,可能session已经失效' % check_user)
|
||||
print ('正在尝试重新登录')
|
||||
self.call_login()
|
||||
self.is_check_user["user_time"] = datetime.datetime.now()
|
||||
|
||||
def submit_station(self):
|
||||
"""
|
||||
|
@ -278,7 +277,7 @@ class select:
|
|||
:return:
|
||||
"""
|
||||
|
||||
submit_station_url = 'https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest'
|
||||
submit_station_url = self.confUrl["submit_station_url"]["req_url"]
|
||||
data = [('secretStr', urllib.unquote(self.secretStr)), # 字符串加密
|
||||
('train_date', self.time()), # 出发时间
|
||||
('back_train_date', self.time()), # 返程时间
|
||||
|
@ -287,7 +286,7 @@ class select:
|
|||
('query_from_station_name', self.from_station), # 起始车站
|
||||
('query_to_station_name', self.to_station), # 终点车站
|
||||
]
|
||||
submitResult = json.loads(myurllib2.Post(submit_station_url, data), encoding='utf-8')
|
||||
submitResult = self.httpClint.send(submit_station_url, data)
|
||||
if 'data' in submitResult and submitResult['data']:
|
||||
if submitResult['data'] == 'N':
|
||||
print ('出票成功')
|
||||
|
@ -358,7 +357,7 @@ class select:
|
|||
:return:
|
||||
"""
|
||||
passengerTicketStrList, oldPassengerStr = self.getPassengerTicketStrListAndOldPassengerStr()
|
||||
checkOrderInfoUrl = 'https://kyfw.12306.cn/otn/confirmPassenger/checkOrderInfo'
|
||||
checkOrderInfoUrl = self.confUrl["checkOrderInfoUrl"]["req_url"]
|
||||
data = OrderedDict()
|
||||
data['cancel_flag'] = 2
|
||||
data['bed_level_order_num'] = "000000000000000000000000000000"
|
||||
|
@ -367,7 +366,7 @@ class select:
|
|||
data['tour_flag'] = 'dc'
|
||||
data['whatsSelect'] = 1
|
||||
data['REPEAT_SUBMIT_TOKEN'] = self.token
|
||||
checkOrderInfo = json.loads(myurllib2.Post(checkOrderInfoUrl, data, ))
|
||||
checkOrderInfo = self.httpClint.send(checkOrderInfoUrl, data)
|
||||
if 'data' in checkOrderInfo:
|
||||
if "ifShowPassCode" in checkOrderInfo["data"] and checkOrderInfo["data"]["ifShowPassCode"] == "Y":
|
||||
is_need_code = True
|
||||
|
@ -381,6 +380,7 @@ class select:
|
|||
else:
|
||||
if "errMsg" in checkOrderInfo['data'] and checkOrderInfo['data']["errMsg"]:
|
||||
print checkOrderInfo['data']["errMsg"]
|
||||
|
||||
else:
|
||||
print checkOrderInfo
|
||||
elif 'messages' in checkOrderInfo and checkOrderInfo['messages']:
|
||||
|
@ -393,13 +393,11 @@ class select:
|
|||
:param token:
|
||||
:return:
|
||||
"""
|
||||
old_train_date = self.get_ticketInfoForPassengerForm()['queryLeftTicketRequestDTO']['train_date']+"00:00:00" # 模仿12306格式 Sun May 21 2017 00:00:00 GMT+0800 (中国标准时间)
|
||||
m_time = time.mktime(time.strptime(old_train_date, "%Y%m%d%H:%M:%S"))
|
||||
l_time = time.localtime(m_time)
|
||||
new_train_date = time.strftime("%a %b %d %Y %H:%M:%S", l_time)
|
||||
getQueueCountUrl = 'https://kyfw.12306.cn/otn/confirmPassenger/getQueueCount'
|
||||
l_time = time.localtime(time.time())
|
||||
new_train_date = time.strftime("%a %b %d %Y", l_time)
|
||||
getQueueCountUrl = self.confUrl["getQueueCountUrl"]["req_url"]
|
||||
data = {
|
||||
'train_date': new_train_date,
|
||||
'train_date': str(new_train_date) + " 00:00:00 GMT+0800 (中国标准时间)",
|
||||
'train_no': self.get_ticketInfoForPassengerForm()['queryLeftTicketRequestDTO']['train_no'],
|
||||
'stationTrainCode': self.get_ticketInfoForPassengerForm()['queryLeftTicketRequestDTO']['station_train_code'],
|
||||
'seatType': self.set_type,
|
||||
|
@ -410,16 +408,11 @@ class select:
|
|||
'train_location': self.get_ticketInfoForPassengerForm()['train_location'],
|
||||
'REPEAT_SUBMIT_TOKEN': self.get_token(),
|
||||
}
|
||||
getQueueCountResult = json.loads(myurllib2.Post(getQueueCountUrl, data))
|
||||
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
|
||||
# ticket_sum = sum([int(ticket_split[0]),int(ticket_split[1])])
|
||||
# if set_type == "无座": # 修改无座和硬座的座位号提交是个字符串的问题
|
||||
# ticket = ticket_split[1]
|
||||
# elif set_type == "硬座":
|
||||
# ticket = ticket_split[0]
|
||||
countT = getQueueCountResult["data"]["countT"]
|
||||
if int(countT) is 0:
|
||||
if int(ticket_split) < len(self.user_info):
|
||||
|
@ -448,8 +441,9 @@ class select:
|
|||
模拟提交订单是确认按钮,参数获取方法还是get_ticketInfoForPassengerForm 中获取
|
||||
:return:
|
||||
"""
|
||||
|
||||
passengerTicketStrList, oldPassengerStr = self.getPassengerTicketStrListAndOldPassengerStr()
|
||||
checkQueueOrderUrl = "https://kyfw.12306.cn/otn/confirmPassenger/confirmSingleForQueue"
|
||||
checkQueueOrderUrl = self.confUrl["checkQueueOrderUrl"]["req_url"]
|
||||
data = {
|
||||
"passengerTicketStr": self.set_type + "," + ",".join(passengerTicketStrList).rstrip("_{0}".format(self.set_type)),
|
||||
"oldPassengerStr": "".join(oldPassengerStr),
|
||||
|
@ -460,15 +454,17 @@ class select:
|
|||
"seatDetailType": "000", # 开始需要选择座位,但是目前12306不支持自动选择作为,那这个参数为默认
|
||||
"roomType": "00", # 好像是根据一个id来判断选中的,两种 第一种是00,第二种是10,但是我在12306的页面没找到该id,目前写死是00,不知道会出什么错
|
||||
"dwAll": "N",
|
||||
"whatsSelect": 1,
|
||||
"_json_at": "",
|
||||
"REPEAT_SUBMIT_TOKEN": self.get_token(),
|
||||
}
|
||||
try:
|
||||
for i in range(3):
|
||||
if is_node_code:
|
||||
print("正在使用自动识别验证码功能")
|
||||
randurl = 'https://kyfw.12306.cn/otn/passcodeNew/checkRandCodeAnsyn'
|
||||
codeimg = 'https://kyfw.12306.cn/otn/passcodeNew/getPassCodeNew?module=passenger&rand=sjrand&%s' % random.random()
|
||||
result = myurllib2.get(codeimg)
|
||||
checkRandCodeAnsyn = self.confUrl["checkRandCodeAnsyn"]["req_url"]
|
||||
codeImgByOrder = self.confUrl["codeImgByOrder"]["req_url"]
|
||||
result = self.httpClint.send(codeImgByOrder)
|
||||
img_path = './tkcode'
|
||||
open(img_path, 'wb').write(result)
|
||||
randCode = DamatuApi(_get_yaml()["damatu"]["uesr"], _get_yaml()["damatu"]["pwd"],
|
||||
|
@ -479,18 +475,18 @@ class select:
|
|||
"_json_att": None,
|
||||
"REPEAT_SUBMIT_TOKEN": self.get_token()
|
||||
}
|
||||
fresult = json.loads(myurllib2.Post(randurl, randData), encoding='utf8') # 校验验证码是否正确
|
||||
fresult = self.httpClint.send(checkRandCodeAnsyn, randData) # 校验验证码是否正确
|
||||
checkcode = fresult['data']['msg']
|
||||
if checkcode == 'FALSE':
|
||||
print ("验证码有误,第{}次尝试重试".format(i))
|
||||
else:
|
||||
if checkcode == 'TRUE':
|
||||
print("验证码通过,正在提交订单")
|
||||
data['randCode'] = randCode
|
||||
break
|
||||
else:
|
||||
print ("验证码有误, 接口返回{0} 第{1}次尝试重试".format(fresult, i))
|
||||
else:
|
||||
print("不需要验证码")
|
||||
break
|
||||
checkQueueOrderResult = json.loads(myurllib2.Post(checkQueueOrderUrl, data))
|
||||
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:
|
||||
|
@ -514,12 +510,6 @@ class select:
|
|||
排队获取订单等待信息,每隔3秒请求一次,最高请求次数为20次!
|
||||
:return:
|
||||
"""
|
||||
# queryOrderWaitTimeUrl = "https://kyfw.12306.cn/otn/confirmPassenger/queryOrderWaitTime"
|
||||
# data = {
|
||||
# "random": "{0}{1}".format(int(time.time()), random.randint(1, 9)),
|
||||
# "tourFlag": "dc",
|
||||
# "REPEAT_SUBMIT_TOKEN": self.get_token(),
|
||||
# }
|
||||
num = 1
|
||||
while True:
|
||||
_random = int(round(time.time() * 1000))
|
||||
|
@ -528,13 +518,15 @@ class select:
|
|||
print("超出排队时间,自动放弃,正在重新刷票")
|
||||
break
|
||||
try:
|
||||
queryOrderWaitTimeUrl = "https://kyfw.12306.cn/otn/confirmPassenger/queryOrderWaitTime?random={0}&tourFlag=dc&_json_att=&REPEAT_SUBMIT_TOKEN={1}".format(_random, self.get_token())
|
||||
queryOrderWaitTimeResult = json.loads(myurllib2.get(queryOrderWaitTimeUrl))
|
||||
data = {"random": _random, "tourFlag": "dc"}
|
||||
queryOrderWaitTimeUrl = self.confUrl["queryOrderWaitTimeUrl"]["req_url"]
|
||||
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("恭喜您订票成功,订单号为:{0}, 请立即打开浏览器登录12306,访问‘未完成订单’,在30分钟内完成支付!".format(queryOrderWaitTimeResult["data"]["orderId"]))
|
||||
raise ticketIsExitsException("恭喜您订票成功,订单号为:{0}, 请立即打开浏览器登录12306,访问‘未完成订单’,在30分钟内完成支付!".format(queryOrderWaitTimeResult["data"]["orderId"]))
|
||||
elif "msg" in queryOrderWaitTimeResult["data"] and queryOrderWaitTimeResult["data"]["msg"]:
|
||||
print queryOrderWaitTimeResult["data"]["msg"]
|
||||
|
@ -549,10 +541,12 @@ class select:
|
|||
print("第{}次排队中,请耐心等待".format(num))
|
||||
else:
|
||||
print("排队中")
|
||||
time.sleep(2)
|
||||
time.sleep(1)
|
||||
order_id = self.queryMyOrderNoComplete() # 尝试查看订单列表,如果有订单,则判断成功,不过一般可能性不大
|
||||
if order_id:
|
||||
sendEmail("恭喜您订票成功,订单号为:{0}, 请立即打开浏览器登录12306,访问‘未完成订单’,在30分钟内完成支付!".format(order_id))
|
||||
raise ticketIsExitsException("恭喜您订票成功,订单号为:{0}, 请立即打开浏览器登录12306,访问‘未完成订单’,在30分钟内完成支付!".format(order_id))
|
||||
|
||||
else:
|
||||
print(ticketNumOutException("订单提交失败!,正在重新刷票"))
|
||||
|
||||
|
@ -562,10 +556,10 @@ class select:
|
|||
:return:
|
||||
"""
|
||||
self.initNoComplete()
|
||||
queryMyOrderNoCompleteUrl = "https://kyfw.12306.cn/otn/queryOrder/queryMyOrderNoComplete"
|
||||
queryMyOrderNoCompleteUrl = self.confUrl["queryMyOrderNoCompleteUrl"]["req_url"]
|
||||
data = {"_json_att": None}
|
||||
try:
|
||||
queryMyOrderNoCompleteResult = json.loads(myurllib2.Post(queryMyOrderNoCompleteUrl, data))
|
||||
queryMyOrderNoCompleteResult = self.httpClint.send(queryMyOrderNoCompleteUrl, data)
|
||||
except ValueError:
|
||||
queryMyOrderNoCompleteResult = {}
|
||||
if queryMyOrderNoCompleteResult:
|
||||
|
@ -590,9 +584,9 @@ class select:
|
|||
获取订单前需要进入订单列表页,获取订单列表页session
|
||||
:return:
|
||||
"""
|
||||
initNoCompleteUrl = "https://kyfw.12306.cn/otn/queryOrder/initNoComplete"
|
||||
initNoCompleteUrl = self.confUrl["initNoCompleteUrl"]["req_url"]
|
||||
data = {"_json_att": None}
|
||||
myurllib2.Post(initNoCompleteUrl, data)
|
||||
self.httpClint.send(initNoCompleteUrl, data)
|
||||
|
||||
# def call_submit_ticket(self, function_name=None):
|
||||
# """
|
||||
|
@ -606,81 +600,61 @@ class select:
|
|||
# else:
|
||||
# self.submitOrderRequest()
|
||||
|
||||
def call_login(self):
|
||||
"""登录回调方法"""
|
||||
login = GoLogin(self.httpClint, self.confUrl)
|
||||
login.go_login()
|
||||
|
||||
def main(self):
|
||||
self.call_login()
|
||||
from_station, to_station = self.station_table(self.from_station, self.to_station)
|
||||
if self.leftTicketLog(from_station, to_station):
|
||||
submitOrderConsumer("daemon1", self.submitQueue).start()
|
||||
num = 1
|
||||
runedTime = 0
|
||||
while 1:
|
||||
num += 1
|
||||
sleepTime = self.select_refresh_interval*1000-runedTime
|
||||
if sleepTime > 0:
|
||||
time.sleep(sleepTime/1000.0)
|
||||
if time.strftime('%H:%M:%S', time.localtime(time.time())) > "23:00:00":
|
||||
print "12306休息时间,本程序自动停止,明天早上七点运行"
|
||||
break
|
||||
start_time = datetime.datetime.now()
|
||||
self.submitOrderRequest(from_station, to_station)
|
||||
runedTime = (datetime.datetime.now()-start_time).microseconds/1000
|
||||
print "正在第{0}次查询 乘车日期: {1} 车次{2} 查询无票 代理设置 无 总耗时{3}ms".format(num, self.station_date, ",".join(self.station_trains), runedTime)
|
||||
|
||||
|
||||
class selectProducer(threading.Thread):
|
||||
"""刷票队列"""
|
||||
def __init__(self, t_name, data):
|
||||
self.t_name = t_name
|
||||
self.data = data
|
||||
threading.Thread.__init__(self, name=self.t_name)
|
||||
print "{0} 正在运行".format(self.t_name)
|
||||
|
||||
def run(self):
|
||||
self.worker(self.data)
|
||||
|
||||
def worker(self, data):
|
||||
obj = data['obj']
|
||||
try:
|
||||
if obj.check_user():
|
||||
obj.submit_station()
|
||||
obj.getPassengerTicketStr(data['seat'])
|
||||
obj.getRepeatSubmitToken()
|
||||
obj.user_info = obj.getPassengerDTOs()
|
||||
if obj.checkOrderInfo(data['train_no'], data['seat']):
|
||||
return
|
||||
obj.submitQueue.task_done()
|
||||
except PassengerUserException as e:
|
||||
print e.message
|
||||
except ticketConfigException as e:
|
||||
print e.message
|
||||
except ticketIsExitsException as e:
|
||||
print e.message
|
||||
except ticketNumOutException as e:
|
||||
print e.message
|
||||
except ValueError as e:
|
||||
if e.message == "No JSON object could be decoded":
|
||||
print("12306接口无响应,正在重试")
|
||||
else:
|
||||
print(e.message)
|
||||
print("{0} 线程运行结束".format(self.t_name))
|
||||
|
||||
|
||||
class submitOrderConsumer(threading.Thread):
|
||||
"""订单队列"""
|
||||
def __init__(self, t_name, queue):
|
||||
threading.Thread.__init__(self, name=t_name)
|
||||
self.data = queue
|
||||
print "{0} 正在运行".format(t_name)
|
||||
|
||||
def run(self):
|
||||
# if self.leftTicketLog(from_station, to_station):
|
||||
num = 1
|
||||
while 1:
|
||||
if not self.data.empty():
|
||||
taskData = self.data.get()
|
||||
selectProducer(taskData['train_no']+str(random.random()), taskData).start()
|
||||
try:
|
||||
num += 1
|
||||
if "user_time" in self.is_check_user and (datetime.datetime.now() - self.is_check_user["user_time"]).seconds/60 > 10:
|
||||
# 十分钟调用一次检查用户是否登录
|
||||
self.check_user()
|
||||
time.sleep(self.select_refresh_interval)
|
||||
if time.strftime('%H:%M:%S', time.localtime(time.time())) > "23:00:00":
|
||||
print "12306休息时间,本程序自动停止,明天早上6点将自动运行"
|
||||
time.sleep(60 * 60 * 7)
|
||||
self.call_login()
|
||||
start_time = datetime.datetime.now()
|
||||
self.submitOrderRequestImplement(from_station, to_station)
|
||||
print "正在第{0}次查询 乘车日期: {1} 车次{2} 查询无票 代理设置 无 总耗时{3}ms".format(num, self.station_date, ",".join(self.station_trains), (datetime.datetime.now()-start_time).microseconds/1000)
|
||||
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("12306接口无响应,正在重试")
|
||||
else:
|
||||
time.sleep(1.5)
|
||||
print(e.message)
|
||||
except KeyError as e:
|
||||
print(e.message)
|
||||
except TypeError as e:
|
||||
print(e.message)
|
||||
except socket.error as e:
|
||||
print(e.message)
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
a = select('上海', '北京')
|
||||
a.main()
|
||||
login()
|
||||
# a = select('上海', '北京')
|
||||
# a.main()
|
|
@ -0,0 +1,2 @@
|
|||
class UserPasswordException(Exception):
|
||||
pass
|
|
@ -1,5 +1,8 @@
|
|||
# -*- coding: utf8 -*-
|
||||
import datetime
|
||||
import json
|
||||
import socket
|
||||
|
||||
import requests
|
||||
|
||||
|
||||
|
@ -10,45 +13,84 @@ class HTTPClient(object):
|
|||
:param method:
|
||||
:param headers: Must be a dict. Such as headers={'Content_Type':'text/html'}
|
||||
"""
|
||||
self.session = requests.session()
|
||||
self._set_header()
|
||||
self.initS()
|
||||
|
||||
def initS(self):
|
||||
self._s = requests.Session()
|
||||
self._s.headers.update(self._set_header())
|
||||
return self
|
||||
|
||||
def set_cookies(self, **kwargs):
|
||||
"""
|
||||
设置cookies
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
for k, v in kwargs.items():
|
||||
self._s.cookies.set(k, v)
|
||||
|
||||
def del_cookies(self):
|
||||
"""
|
||||
删除所有的key
|
||||
:return:
|
||||
"""
|
||||
self._s.cookies.clear()
|
||||
|
||||
def del_cookies_by_key(self, key):
|
||||
"""
|
||||
删除指定key的session
|
||||
:return:
|
||||
"""
|
||||
self._s.cookies.set(key, None)
|
||||
|
||||
def _set_header(self):
|
||||
"""设置header"""
|
||||
add_header = {
|
||||
return {
|
||||
"Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
|
||||
"X-Requested-With": "xmlHttpRequest",
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36",
|
||||
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36",
|
||||
"Referer": "https://kyfw.12306.cn/otn/login/init",
|
||||
"Accept": "*/*",
|
||||
}
|
||||
self.session.headers.update(add_header)
|
||||
|
||||
def get(self, url, proxy=None, **kwargs):
|
||||
if proxy:
|
||||
proxies = {"http": proxy}
|
||||
else:
|
||||
proxies = ""
|
||||
response = self.session.request(method="GET",
|
||||
url=url,
|
||||
proxies=proxies,
|
||||
**kwargs)
|
||||
if response.status_code == 200:
|
||||
return response.content
|
||||
else:
|
||||
print("请求失败。{0}".format(response))
|
||||
def setHeaders(self, headers):
|
||||
self._s.headers.update(headers)
|
||||
return self
|
||||
|
||||
def post(self, url, data=None, proxy=None, **kwargs):
|
||||
if proxy:
|
||||
proxies = {"http": proxy}
|
||||
else:
|
||||
proxies = ""
|
||||
response = self.session.request(method="POST",
|
||||
url=url,
|
||||
data=data,
|
||||
proxies=proxies,
|
||||
**kwargs)
|
||||
if response.status_code == 200:
|
||||
return response.content
|
||||
else:
|
||||
print("请求失败。{0}".format(response))
|
||||
def getHeadersHost(self):
|
||||
return self._s.headers["Host"]
|
||||
|
||||
def setHeadersHost(self, host):
|
||||
self._s.headers.update({"Host": host})
|
||||
return self
|
||||
|
||||
def getHeadersReferer(self):
|
||||
return self._s.headers["Referer"]
|
||||
|
||||
def setHeadersReferer(self, referer):
|
||||
self._s.headers.update({"Referer": referer})
|
||||
return self
|
||||
|
||||
def send(self, url, data=None, **kwargs):
|
||||
"""send request to url.If response 200,return response, else return None."""
|
||||
method = "post"if data else "get"
|
||||
response = self._s.request(method=method,
|
||||
url=url,
|
||||
data=data,
|
||||
**kwargs)
|
||||
try:
|
||||
if response.content:
|
||||
return json.loads(response.content) if method == "post" else response.content
|
||||
else:
|
||||
return ""
|
||||
except ValueError as e:
|
||||
if e.message == "No JSON object could be decoded":
|
||||
print("12306接口无响应,正在重试")
|
||||
else:
|
||||
print(e.message)
|
||||
except KeyError as e:
|
||||
print(e.message)
|
||||
except TypeError as e:
|
||||
print(e.message)
|
||||
except socket.error as e:
|
||||
print(e.message)
|
|
@ -20,9 +20,9 @@ def get(url):
|
|||
request = urllib2.Request(url=url)
|
||||
request.add_header("Content-Type", "application/x-www-form-urlencoded; charset=utf-8")
|
||||
request.add_header('X-Requested-With', 'xmlHttpRequest')
|
||||
request.add_header('User-Agent',
|
||||
'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36')
|
||||
request.add_header('Referer', 'https://kyfw.12306.cn/otn/login/init')
|
||||
request.add_header('User-Agent', "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
|
||||
)
|
||||
request.add_header('Referer', 'https://kyfw.12306.cn/otn/confirmPassenger/initDc')
|
||||
request.add_header('Accept', '*/*')
|
||||
result = urllib2.urlopen(request).read()
|
||||
assert isinstance(result, object)
|
||||
|
@ -44,9 +44,9 @@ def Post(url, data):
|
|||
# request = urllib2Post.Request(ajax_url, urllib.urlencode(dc))
|
||||
request.add_header("Content-Type", "application/x-www-form-urlencoded;application/json;charset=utf-8")
|
||||
request.add_header('X-Requested-With', 'xmlHttpRequest')
|
||||
request.add_header('User-Agent',
|
||||
'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36')
|
||||
request.add_header('Referer', 'https://kyfw.12306.cn/otn/login/init')
|
||||
request.add_header('User-Agent', "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
|
||||
)
|
||||
request.add_header('Referer', 'https://kyfw.12306.cn/otn/confirmPassenger/initDc')
|
||||
request.add_header('Accept', '*/*')
|
||||
# request.add_header('Accept-Encoding', 'gzip, deflate')
|
||||
for i in range(3):
|
||||
|
|
6
run.py
6
run.py
|
@ -3,7 +3,9 @@ from init import login, select_ticket_info
|
|||
|
||||
|
||||
def run():
|
||||
login.main()
|
||||
# login.main()
|
||||
select_ticket_info.select().main()
|
||||
|
||||
run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
Loading…
Reference in New Issue