Compare commits
58 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bd1a0fcaa3 | ||
|
|
004b82831d | ||
|
|
f0fea7cba7 | ||
|
|
b1ab036026 | ||
|
|
c1ce4e4469 | ||
|
|
b056211587 | ||
|
|
01d54be85a | ||
|
|
632a971606 | ||
|
|
133606f170 | ||
|
|
0b3d04ace4 | ||
|
|
829ec1163e | ||
|
|
7d40223973 | ||
|
|
34456df151 | ||
|
|
d214892525 | ||
|
|
b36595aead | ||
|
|
b37aadfc93 | ||
|
|
235b0000c9 | ||
|
|
d7c5c7215c | ||
|
|
1411824016 | ||
|
|
0d4846e9ba | ||
|
|
aa6d628c82 | ||
|
|
501fd388bd | ||
|
|
cd65eeb963 | ||
|
|
a3ba39c757 | ||
|
|
44a41f9131 | ||
|
|
35918e1dd8 | ||
|
|
4c2b435407 | ||
|
|
5f7b4df19b | ||
|
|
d1be6833bb | ||
|
|
4cc4205d86 | ||
|
|
46ecb662eb | ||
|
|
f669690a70 | ||
|
|
fb92dbaece | ||
|
|
ac1a03834e | ||
|
|
a3f88212d0 | ||
|
|
1ce2f7719e | ||
|
|
6ffdaa0048 | ||
|
|
4febb67ac2 | ||
|
|
9170177769 | ||
|
|
b84c5faf8f | ||
|
|
91b0c471ee | ||
|
|
a6983a0422 | ||
|
|
2ed2916397 | ||
|
|
507910d1dd | ||
|
|
26ee65c48e | ||
|
|
339c22b5e2 | ||
|
|
488fd01864 | ||
|
|
66413c9acc | ||
|
|
39b10e05c0 | ||
|
|
27d3c8f216 | ||
|
|
943ca94b9c | ||
|
|
9865021f81 | ||
|
|
ebcd2a7997 | ||
|
|
4383d31878 | ||
|
|
f07b33d099 | ||
|
|
dffc307b55 | ||
|
|
e5b16fe778 | ||
|
|
e5320663e8 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,3 +1,5 @@
|
||||
*.html
|
||||
*.pyc
|
||||
*.yaml
|
||||
*.log
|
||||
idea/
|
||||
|
||||
3
.idea/codeStyleSettings.xml
generated
3
.idea/codeStyleSettings.xml
generated
@@ -4,6 +4,9 @@
|
||||
<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" />
|
||||
|
||||
8
.idea/markdown-exported-files.xml
generated
Normal file
8
.idea/markdown-exported-files.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="MarkdownExportedFiles">
|
||||
<htmlFiles />
|
||||
<imageFiles />
|
||||
<otherFiles />
|
||||
</component>
|
||||
</project>
|
||||
72
.idea/markdown-navigator.xml
generated
Normal file
72
.idea/markdown-navigator.xml
generated
Normal file
@@ -0,0 +1,72 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="MarkdownProjectSettings">
|
||||
<PreviewSettings splitEditorLayout="SPLIT" splitEditorPreview="PREVIEW" useGrayscaleRendering="false" zoomFactor="1.0" maxImageWidth="0" showGitHubPageIfSynced="false" allowBrowsingInPreview="false" synchronizePreviewPosition="true" highlightPreviewType="NONE" highlightFadeOut="5" highlightOnTyping="true" synchronizeSourcePosition="true" verticallyAlignSourceAndPreviewSyncPosition="true" showSearchHighlightsInPreview="false" showSelectionInPreview="true" openRemoteLinks="true">
|
||||
<PanelProvider>
|
||||
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.panel" providerName="Default - Swing" />
|
||||
</PanelProvider>
|
||||
</PreviewSettings>
|
||||
<ParserSettings gitHubSyntaxChange="false">
|
||||
<PegdownExtensions>
|
||||
<option name="ABBREVIATIONS" value="false" />
|
||||
<option name="ANCHORLINKS" value="true" />
|
||||
<option name="ASIDE" value="false" />
|
||||
<option name="ATXHEADERSPACE" value="true" />
|
||||
<option name="AUTOLINKS" value="true" />
|
||||
<option name="DEFINITIONS" value="false" />
|
||||
<option name="DEFINITION_BREAK_DOUBLE_BLANK_LINE" value="false" />
|
||||
<option name="FENCED_CODE_BLOCKS" value="true" />
|
||||
<option name="FOOTNOTES" value="false" />
|
||||
<option name="HARDWRAPS" value="false" />
|
||||
<option name="HTML_DEEP_PARSER" value="false" />
|
||||
<option name="INSERTED" value="false" />
|
||||
<option name="QUOTES" value="false" />
|
||||
<option name="RELAXEDHRULES" value="true" />
|
||||
<option name="SMARTS" value="false" />
|
||||
<option name="STRIKETHROUGH" value="true" />
|
||||
<option name="SUBSCRIPT" value="false" />
|
||||
<option name="SUPERSCRIPT" value="false" />
|
||||
<option name="SUPPRESS_HTML_BLOCKS" value="false" />
|
||||
<option name="SUPPRESS_INLINE_HTML" value="false" />
|
||||
<option name="TABLES" value="true" />
|
||||
<option name="TASKLISTITEMS" value="true" />
|
||||
<option name="TOC" value="false" />
|
||||
<option name="WIKILINKS" value="true" />
|
||||
</PegdownExtensions>
|
||||
<ParserOptions>
|
||||
<option name="COMMONMARK_LISTS" value="true" />
|
||||
<option name="DUMMY" value="false" />
|
||||
<option name="EMOJI_SHORTCUTS" value="true" />
|
||||
<option name="FLEXMARK_FRONT_MATTER" value="false" />
|
||||
<option name="GFM_LOOSE_BLANK_LINE_AFTER_ITEM_PARA" value="false" />
|
||||
<option name="GFM_TABLE_RENDERING" value="true" />
|
||||
<option name="GITBOOK_URL_ENCODING" value="false" />
|
||||
<option name="GITHUB_EMOJI_URL" value="false" />
|
||||
<option name="GITHUB_LISTS" value="false" />
|
||||
<option name="GITHUB_WIKI_LINKS" value="true" />
|
||||
<option name="JEKYLL_FRONT_MATTER" value="false" />
|
||||
<option name="SIM_TOC_BLANK_LINE_SPACER" value="true" />
|
||||
</ParserOptions>
|
||||
</ParserSettings>
|
||||
<HtmlSettings headerTopEnabled="false" headerBottomEnabled="false" bodyTopEnabled="false" bodyBottomEnabled="false" embedUrlContent="false" addPageHeader="true" embedImages="false" embedHttpImages="false">
|
||||
<GeneratorProvider>
|
||||
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.generator" providerName="Default Swing HTML Generator" />
|
||||
</GeneratorProvider>
|
||||
<headerTop />
|
||||
<headerBottom />
|
||||
<bodyTop />
|
||||
<bodyBottom />
|
||||
</HtmlSettings>
|
||||
<CssSettings previewScheme="UI_SCHEME" cssUri="" isCssUriEnabled="false" isCssTextEnabled="false" isDynamicPageWidth="true">
|
||||
<StylesheetProvider>
|
||||
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.css" providerName="Default Swing Stylesheet" />
|
||||
</StylesheetProvider>
|
||||
<ScriptProviders />
|
||||
<cssText />
|
||||
</CssSettings>
|
||||
<HtmlExportSettings updateOnSave="false" parentDir="$ProjectFileDir$" targetDir="$ProjectFileDir$" cssDir="" scriptDir="" plainHtml="false" imageDir="" copyLinkedImages="false" imageUniquifyType="0" targetExt="" useTargetExt="false" noCssNoScripts="false" linkToExportedHtml="true" exportOnSettingsChange="true" regenerateOnProjectOpen="false" linkFormatType="HTTP_ABSOLUTE" />
|
||||
<LinkMapSettings>
|
||||
<textMaps />
|
||||
</LinkMapSettings>
|
||||
</component>
|
||||
</project>
|
||||
3
.idea/markdown-navigator/profiles_settings.xml
generated
Normal file
3
.idea/markdown-navigator/profiles_settings.xml
generated
Normal file
@@ -0,0 +1,3 @@
|
||||
<component name="MarkdownNavigator.ProfileManager">
|
||||
<settings default="" pdf-export="" />
|
||||
</component>
|
||||
781
.idea/workspace.xml
generated
781
.idea/workspace.xml
generated
File diff suppressed because it is too large
Load Diff
122
README.md
122
README.md
@@ -3,10 +3,58 @@
|
||||
- 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-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"
|
||||
```
|
||||
|
||||
- 项目开始
|
||||
- 修改config/ticket_config.yaml文件,按照提示更改自己想要的信息
|
||||
- 运行根目录run.py,即可开始
|
||||
@@ -26,6 +74,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 +138,56 @@
|
||||
- 优化查票流程
|
||||
- 修改二等座的余票数返回为字符串的问题
|
||||
- 优化订单查询bug
|
||||
- 2018.1.12更新
|
||||
- 优化抢票页面逻辑
|
||||
-增强代码稳定性
|
||||
|
||||
- 2018.1.13更新
|
||||
- 修改下单验证码功能
|
||||
- 优化大量调用user接口导致联系人不能用,理论加快订票速度
|
||||
- 增加邮箱功能
|
||||
```
|
||||
#is_email: 是否需要邮件通知 ex: True or False 切记,邮箱加完一定要到config目录下测试emailConf功能是否正常
|
||||
#email: 发送的邮箱地址 ex: 1@qq.com
|
||||
#notice_email_list: 被通知人邮箱 ex: 2@qq.com
|
||||
#username: 邮箱账号
|
||||
#password: 邮箱密码
|
||||
#host: 邮箱地址
|
||||
```
|
||||
|
||||
- 2018.1.14更新
|
||||
- 优化订票流程
|
||||
- 优化挂机功能
|
||||
- 修改之前程序到11点自动跳出功能,现在修改为到早上7点自动开启刷票
|
||||
- 需要开启打码兔代码功能,is_aotu_code 设置为True
|
||||
- 增加异常判断
|
||||
|
||||
- 2018.1.15更新
|
||||
- 增加捡漏自动检测是否登录功能,建议捡漏不要刷新太快,2S最好,否则会封IP
|
||||
- 优化提交订单有很大记录无限排队的情况,感谢群里的小伙伴提供的思路
|
||||
- 修改休眠时间为早上6点
|
||||
|
||||
- 2018.1.20更新,好久没跟新了,群里的小伙伴说登录不行了,今晚抽空改了一版登录,妥妥的
|
||||
- 更新新版登录功能,经测试,更稳定有高效
|
||||
- 优化手动打码功能
|
||||
- 更新请求第三方库
|
||||
- 优化若干代码,小伙伴尽情的放肆起来
|
||||
|
||||
- 2018.1.21跟新
|
||||
- 修复若干bug
|
||||
- 合并dev
|
||||
- 恢复之前因为12306改版引起的订票功能
|
||||
- 增加派对失败自动取消订单功能
|
||||
- 优化接口请求规范
|
||||
- 增加多日期查询,请严格按照yaml格式添加 即可
|
||||
- 注意:如果多日期查询的话,可能查询时间会比较长
|
||||
- 增加如果排队时间超过一分钟,自动取消订单
|
||||
|
||||
- 2018.1.23更新
|
||||
- 增加若快平台打码,yaml新增字段aotu_code_type,1=打码兔,2=若快 若快注册地址:http://www.ruokuai.com/client/index?6726
|
||||
- 修改is_aotu_code字段为全部是否自动打码字段,也就是说字段为rue,则全部自动打码,为False全部手动打码,包括提交订单,注意centOs不可设置手动打码
|
||||
- 修复bug
|
||||
- 优化抢票功能
|
||||
|
||||
|
||||
|
||||
|
||||
611
agency/cdn_list
Normal file
611
agency/cdn_list
Normal file
@@ -0,0 +1,611 @@
|
||||
150.138.169.233
|
||||
183.131.192.83
|
||||
117.27.241.176
|
||||
115.231.22.33
|
||||
115.231.84.169
|
||||
115.231.22.80
|
||||
58.216.21.23
|
||||
123.138.60.143
|
||||
117.27.245.89
|
||||
61.188.191.26
|
||||
61.188.191.84
|
||||
175.43.124.142
|
||||
60.222.221.62
|
||||
222.243.110.146
|
||||
222.243.110.149
|
||||
117.21.168.87
|
||||
182.132.33.24
|
||||
182.132.33.26
|
||||
112.25.35.53
|
||||
61.188.191.30
|
||||
220.162.97.245
|
||||
61.90.241.26
|
||||
61.188.191.215
|
||||
220.162.97.241
|
||||
222.245.77.22
|
||||
222.163.201.28
|
||||
113.5.80.100
|
||||
182.140.147.63
|
||||
182.132.33.22
|
||||
221.229.167.32
|
||||
61.188.191.20
|
||||
220.165.142.37
|
||||
218.58.222.19
|
||||
211.142.22.26
|
||||
113.207.72.19
|
||||
220.194.200.180
|
||||
60.174.241.25
|
||||
61.188.191.27
|
||||
220.162.97.243
|
||||
61.54.219.34
|
||||
113.5.80.93
|
||||
114.80.143.144
|
||||
120.192.199.13
|
||||
175.43.20.60
|
||||
121.18.230.86
|
||||
59.56.26.36
|
||||
182.140.147.58
|
||||
61.54.219.8
|
||||
182.140.147.106
|
||||
122.70.142.160
|
||||
120.192.199.26
|
||||
219.243.47.166
|
||||
162.105.28.232
|
||||
120.192.199.12
|
||||
120.192.199.4
|
||||
120.192.199.13
|
||||
120.192.199.3
|
||||
115.231.82.101
|
||||
106.3.62.198
|
||||
115.231.82.59
|
||||
115.231.82.62
|
||||
115.231.82.58
|
||||
115.231.82.60
|
||||
112.253.19.162
|
||||
112.253.19.161
|
||||
122.70.142.142
|
||||
122.70.142.144
|
||||
175.43.124.143
|
||||
112.253.19.159
|
||||
175.43.124.145
|
||||
122.70.142.145
|
||||
175.43.124.146
|
||||
101.227.66.152
|
||||
121.18.230.43
|
||||
121.18.230.42
|
||||
121.18.230.44
|
||||
121.18.230.45
|
||||
122.70.142.143
|
||||
222.243.110.147
|
||||
222.243.110.149
|
||||
222.243.110.146
|
||||
222.243.110.148
|
||||
110.18.244.138
|
||||
110.18.244.140
|
||||
110.18.244.141
|
||||
112.253.19.163
|
||||
115.231.84.62
|
||||
115.231.84.64
|
||||
218.60.106.91
|
||||
61.188.191.27
|
||||
175.43.124.141
|
||||
61.188.191.26
|
||||
61.188.191.28
|
||||
115.156.188.138
|
||||
112.253.19.164
|
||||
106.3.62.194
|
||||
220.165.142.37
|
||||
220.165.142.38
|
||||
220.165.142.35
|
||||
220.165.142.39
|
||||
220.165.142.40
|
||||
219.146.68.84
|
||||
219.146.68.78
|
||||
219.146.68.79
|
||||
61.138.219.8
|
||||
61.138.219.7
|
||||
182.132.33.24
|
||||
182.132.33.22
|
||||
182.132.33.21
|
||||
182.132.33.23
|
||||
61.138.219.10
|
||||
61.138.219.6
|
||||
58.216.21.23
|
||||
220.165.142.36
|
||||
58.216.21.24
|
||||
58.216.21.25
|
||||
61.138.219.9
|
||||
58.216.21.22
|
||||
60.174.241.31
|
||||
211.142.22.26
|
||||
60.174.241.29
|
||||
60.174.241.30
|
||||
115.156.188.137
|
||||
123.138.60.143
|
||||
222.243.110.150
|
||||
115.231.84.65
|
||||
123.138.60.145
|
||||
123.138.60.144
|
||||
211.142.22.24
|
||||
61.54.219.39
|
||||
61.54.219.75
|
||||
61.54.219.38
|
||||
119.84.111.83
|
||||
175.43.20.56
|
||||
202.122.145.86
|
||||
175.43.20.58
|
||||
175.43.20.57
|
||||
211.142.22.25
|
||||
101.227.66.151
|
||||
112.25.35.52
|
||||
112.25.35.53
|
||||
112.25.35.54
|
||||
202.122.145.214
|
||||
112.25.35.56
|
||||
112.25.35.55
|
||||
119.84.111.44
|
||||
119.84.111.45
|
||||
119.84.111.47
|
||||
175.43.20.60
|
||||
61.54.219.43
|
||||
60.174.241.28
|
||||
175.43.124.144
|
||||
121.18.230.46
|
||||
121.18.230.47
|
||||
114.80.143.158
|
||||
182.140.147.59
|
||||
182.140.147.62
|
||||
182.140.147.79
|
||||
182.140.147.76
|
||||
182.140.147.77
|
||||
180.180.248.185
|
||||
182.140.147.78
|
||||
182.140.147.61
|
||||
182.140.147.58
|
||||
123.138.60.146
|
||||
111.161.22.27
|
||||
101.227.66.150
|
||||
175.154.189.30
|
||||
221.229.167.47
|
||||
36.250.74.83
|
||||
115.231.22.80
|
||||
113.200.235.30
|
||||
119.84.111.43
|
||||
119.84.111.41
|
||||
119.84.111.42
|
||||
116.55.236.36
|
||||
115.231.171.17
|
||||
115.231.171.13
|
||||
116.55.236.38
|
||||
115.231.171.16
|
||||
115.231.171.14
|
||||
220.165.142.51
|
||||
116.55.236.37
|
||||
116.55.236.45
|
||||
221.235.187.76
|
||||
220.162.97.245
|
||||
220.162.97.209
|
||||
220.162.97.241
|
||||
220.162.97.246
|
||||
115.231.84.169
|
||||
116.55.236.39
|
||||
117.27.245.62
|
||||
202.118.10.115
|
||||
118.180.15.110
|
||||
61.188.191.20
|
||||
61.188.191.22
|
||||
61.188.191.21
|
||||
61.167.54.239
|
||||
61.188.191.19
|
||||
61.167.54.238
|
||||
61.167.54.237
|
||||
61.167.54.236
|
||||
61.167.54.109
|
||||
111.26.136.223
|
||||
119.84.111.38
|
||||
113.207.72.17
|
||||
123.138.60.147
|
||||
113.207.72.20
|
||||
113.207.72.19
|
||||
202.118.10.117
|
||||
111.161.22.17
|
||||
111.161.22.16
|
||||
110.18.244.142
|
||||
59.56.26.49
|
||||
59.56.26.35
|
||||
59.56.26.36
|
||||
59.56.26.37
|
||||
118.180.15.74
|
||||
118.180.15.73
|
||||
118.180.15.69
|
||||
118.180.15.71
|
||||
110.18.244.137
|
||||
118.180.15.72
|
||||
59.56.26.34
|
||||
112.253.19.160
|
||||
113.200.235.18
|
||||
113.200.235.17
|
||||
118.180.15.94
|
||||
113.200.235.15
|
||||
36.250.87.94
|
||||
113.200.235.16
|
||||
59.56.26.33
|
||||
183.136.217.73
|
||||
183.136.217.75
|
||||
60.207.246.98
|
||||
117.27.245.89
|
||||
113.207.72.67
|
||||
113.207.69.72
|
||||
220.162.97.243
|
||||
183.136.217.74
|
||||
117.27.245.87
|
||||
117.27.245.85
|
||||
220.162.97.242
|
||||
112.90.246.87
|
||||
61.90.241.26
|
||||
117.27.245.88
|
||||
183.250.179.36
|
||||
61.167.54.108
|
||||
210.66.46.19
|
||||
115.231.171.15
|
||||
182.140.147.81
|
||||
183.250.179.23
|
||||
183.250.179.24
|
||||
183.250.179.12
|
||||
183.250.179.25
|
||||
221.235.187.132
|
||||
183.250.179.11
|
||||
36.250.87.26
|
||||
175.43.20.81
|
||||
60.222.221.65
|
||||
60.222.221.62
|
||||
60.222.221.61
|
||||
36.250.87.30
|
||||
36.250.87.27
|
||||
113.107.112.214
|
||||
113.107.112.168
|
||||
113.107.112.167
|
||||
218.92.220.15
|
||||
61.188.191.30
|
||||
218.92.220.17
|
||||
221.229.167.32
|
||||
61.188.191.29
|
||||
221.229.167.31
|
||||
221.229.167.36
|
||||
60.222.221.66
|
||||
125.90.204.34
|
||||
125.90.204.33
|
||||
58.222.19.59
|
||||
61.188.191.85
|
||||
125.90.204.32
|
||||
58.222.19.51
|
||||
58.222.19.52
|
||||
58.222.19.54
|
||||
61.188.191.215
|
||||
58.222.19.53
|
||||
182.140.147.80
|
||||
61.188.191.217
|
||||
61.188.191.216
|
||||
58.222.19.50
|
||||
222.163.201.24
|
||||
222.163.201.29
|
||||
113.107.112.164
|
||||
182.140.147.104
|
||||
113.207.69.18
|
||||
113.207.69.16
|
||||
222.163.201.27
|
||||
222.163.201.30
|
||||
125.90.204.31
|
||||
222.23.55.208
|
||||
222.245.77.19
|
||||
222.245.77.21
|
||||
121.18.230.86
|
||||
182.132.33.26
|
||||
58.216.21.21
|
||||
61.188.191.84
|
||||
222.245.77.22
|
||||
218.92.220.55
|
||||
182.132.33.25
|
||||
222.245.77.17
|
||||
61.174.63.232
|
||||
60.222.221.59
|
||||
221.235.187.64
|
||||
58.221.78.105
|
||||
61.138.219.85
|
||||
218.58.222.99
|
||||
113.5.80.100
|
||||
218.58.222.19
|
||||
113.5.80.90
|
||||
61.167.54.240
|
||||
180.97.180.44
|
||||
113.5.80.93
|
||||
61.174.63.203
|
||||
61.174.63.205
|
||||
61.174.63.200
|
||||
61.174.63.204
|
||||
180.97.180.47
|
||||
60.223.235.139
|
||||
180.97.180.45
|
||||
180.97.180.46
|
||||
113.5.80.91
|
||||
60.223.235.142
|
||||
118.180.15.113
|
||||
175.43.124.195
|
||||
220.194.200.177
|
||||
220.194.200.179
|
||||
220.194.200.180
|
||||
42.81.5.76
|
||||
42.81.5.79
|
||||
61.156.243.247
|
||||
222.186.17.100
|
||||
60.174.241.88
|
||||
182.34.127.94
|
||||
220.194.200.178
|
||||
218.29.50.48
|
||||
113.5.80.125
|
||||
218.76.105.75
|
||||
218.60.109.74
|
||||
182.140.236.27
|
||||
122.143.27.169
|
||||
211.162.39.113
|
||||
61.138.219.87
|
||||
115.231.22.33
|
||||
121.192.176.198
|
||||
115.231.22.31
|
||||
115.231.22.34
|
||||
115.231.22.32
|
||||
58.216.21.93
|
||||
125.90.204.122
|
||||
180.97.178.210
|
||||
117.27.245.75
|
||||
122.136.46.107
|
||||
222.163.201.28
|
||||
220.194.200.232
|
||||
61.54.219.34
|
||||
119.84.111.46
|
||||
116.211.79.31
|
||||
58.222.19.61
|
||||
222.243.110.164
|
||||
117.27.241.176
|
||||
222.132.5.100
|
||||
121.192.176.196
|
||||
175.43.124.142
|
||||
115.231.84.61
|
||||
61.188.191.218
|
||||
112.65.220.39
|
||||
218.58.222.20
|
||||
60.5.254.10
|
||||
118.122.87.99
|
||||
221.179.172.161
|
||||
60.174.241.25
|
||||
113.207.72.15
|
||||
218.60.106.25
|
||||
183.250.179.32
|
||||
117.21.168.87
|
||||
182.140.147.63
|
||||
112.25.35.79
|
||||
60.174.241.26
|
||||
125.39.1.138
|
||||
221.179.172.204
|
||||
119.84.111.126
|
||||
61.167.54.62
|
||||
111.11.152.225
|
||||
114.80.143.144
|
||||
112.65.220.18
|
||||
113.207.69.17
|
||||
119.84.111.49
|
||||
222.211.64.92
|
||||
222.211.64.89
|
||||
111.11.228.69
|
||||
111.26.136.216
|
||||
202.201.14.181
|
||||
111.26.136.222
|
||||
111.1.59.190
|
||||
218.26.75.208
|
||||
36.250.76.204
|
||||
60.5.255.230
|
||||
101.70.152.37
|
||||
162.105.28.233
|
||||
58.20.164.51
|
||||
121.251.255.226
|
||||
202.98.156.62
|
||||
182.140.236.28
|
||||
182.132.33.43
|
||||
110.18.247.41
|
||||
110.18.247.40
|
||||
175.25.168.40
|
||||
111.1.59.93
|
||||
111.40.195.169
|
||||
121.251.255.227
|
||||
111.44.244.52
|
||||
222.211.64.51
|
||||
36.42.32.68
|
||||
119.84.111.113
|
||||
119.84.86.112
|
||||
218.58.222.15
|
||||
218.76.94.67
|
||||
111.20.250.62
|
||||
218.92.220.78
|
||||
218.202.111.106
|
||||
218.197.116.214
|
||||
124.164.8.65
|
||||
113.107.57.43
|
||||
117.187.19.45
|
||||
117.187.19.19
|
||||
117.187.19.17
|
||||
117.187.19.16
|
||||
117.187.19.18
|
||||
211.142.22.114
|
||||
117.169.17.8
|
||||
117.169.17.7
|
||||
117.169.17.6
|
||||
211.138.60.136
|
||||
125.90.204.117
|
||||
211.138.60.135
|
||||
202.120.1.32
|
||||
221.180.151.118
|
||||
58.20.197.62
|
||||
183.131.168.145
|
||||
122.228.233.206
|
||||
221.180.151.119
|
||||
122.228.233.209
|
||||
58.223.164.87
|
||||
202.194.19.4
|
||||
202.194.19.5
|
||||
36.250.248.66
|
||||
112.84.104.48
|
||||
111.26.17.169
|
||||
121.251.255.237
|
||||
124.165.216.64
|
||||
222.89.68.50
|
||||
117.131.213.238
|
||||
222.184.34.54
|
||||
112.25.35.61
|
||||
111.26.17.170
|
||||
117.156.21.51
|
||||
117.187.19.164
|
||||
60.215.125.71
|
||||
117.187.19.46
|
||||
36.250.248.68
|
||||
60.13.41.74
|
||||
36.250.76.37
|
||||
36.250.76.36
|
||||
36.250.76.35
|
||||
36.250.76.34
|
||||
222.89.68.51
|
||||
117.169.17.45
|
||||
218.199.110.85
|
||||
220.162.97.136
|
||||
42.58.243.157
|
||||
124.228.90.88
|
||||
14.215.100.94
|
||||
113.107.57.41
|
||||
14.215.9.85
|
||||
218.199.110.84
|
||||
58.63.233.35
|
||||
221.230.141.78
|
||||
117.21.204.77
|
||||
218.92.227.121
|
||||
116.211.79.27
|
||||
59.45.42.44
|
||||
122.228.233.208
|
||||
122.225.28.145
|
||||
111.11.228.70
|
||||
58.218.208.199
|
||||
183.134.11.90
|
||||
171.217.254.68
|
||||
61.184.117.53
|
||||
183.134.28.63
|
||||
116.57.77.35
|
||||
60.174.241.23
|
||||
183.134.12.69
|
||||
182.140.218.63
|
||||
182.140.218.64
|
||||
60.211.208.49
|
||||
218.86.111.69
|
||||
218.77.2.32
|
||||
61.163.117.65
|
||||
115.231.20.39
|
||||
117.169.17.46
|
||||
221.182.135.179
|
||||
121.14.117.145
|
||||
218.92.209.74
|
||||
182.106.194.107
|
||||
183.131.119.86
|
||||
183.224.12.87
|
||||
123.183.164.143
|
||||
106.3.62.213
|
||||
36.250.76.65
|
||||
106.3.62.211
|
||||
106.3.62.212
|
||||
183.131.168.154
|
||||
115.156.188.183
|
||||
115.156.188.182
|
||||
117.145.179.96
|
||||
222.186.132.68
|
||||
218.29.49.71
|
||||
112.25.55.143
|
||||
150.138.214.95
|
||||
218.7.220.14
|
||||
59.56.30.221
|
||||
150.138.214.86
|
||||
150.138.214.85
|
||||
183.6.245.178
|
||||
150.138.214.83
|
||||
150.138.214.84
|
||||
122.13.74.252
|
||||
183.134.9.59
|
||||
124.116.133.50
|
||||
112.90.212.126
|
||||
218.60.132.160
|
||||
183.6.245.191
|
||||
14.215.100.95
|
||||
111.23.11.52
|
||||
115.153.176.80
|
||||
112.17.26.100
|
||||
117.23.2.85
|
||||
183.134.11.91
|
||||
221.182.135.156
|
||||
222.186.132.123
|
||||
125.90.206.144
|
||||
42.58.243.34
|
||||
183.61.26.199
|
||||
60.8.123.158
|
||||
150.138.169.233
|
||||
60.220.194.210
|
||||
36.42.32.254
|
||||
222.218.45.216
|
||||
117.27.241.99
|
||||
211.142.22.2
|
||||
59.56.30.207
|
||||
220.194.203.66
|
||||
218.5.238.215
|
||||
123.183.164.136
|
||||
112.65.220.227
|
||||
59.56.30.206
|
||||
111.47.201.207
|
||||
113.5.170.35
|
||||
112.25.82.12
|
||||
49.79.232.225
|
||||
110.157.233.34
|
||||
221.180.137.59
|
||||
60.13.41.78
|
||||
183.131.119.87
|
||||
110.157.233.35
|
||||
183.134.16.86
|
||||
110.157.233.30
|
||||
110.157.233.33
|
||||
58.50.31.33
|
||||
123.138.60.192
|
||||
150.138.168.115
|
||||
61.147.211.20
|
||||
218.12.228.212
|
||||
119.90.19.39
|
||||
221.229.202.154
|
||||
123.138.157.109
|
||||
122.70.142.182
|
||||
60.223.208.78
|
||||
101.66.224.145
|
||||
180.97.247.157
|
||||
116.224.87.45
|
||||
180.97.180.16
|
||||
59.50.75.195
|
||||
211.91.165.175
|
||||
183.222.100.112
|
||||
183.131.192.83
|
||||
59.47.79.43
|
||||
211.91.168.40
|
||||
60.217.22.146
|
||||
183.214.140.236
|
||||
60.213.21.211
|
||||
218.60.51.253
|
||||
125.64.134.78
|
||||
222.163.202.216
|
||||
101.227.102.198
|
||||
223.111.13.62
|
||||
59.47.0.189
|
||||
117.23.2.86
|
||||
111.11.31.114
|
||||
123.172.120.115
|
||||
219.147.141.176
|
||||
120.221.24.123
|
||||
108
agency/cdn_utils.py
Normal file
108
agency/cdn_utils.py
Normal file
@@ -0,0 +1,108 @@
|
||||
# encoding=utf8
|
||||
import collections
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
import csv
|
||||
import requests
|
||||
from config import urlConf
|
||||
reload(sys)
|
||||
sys.setdefaultencoding('utf-8')
|
||||
|
||||
|
||||
class CDNProxy:
|
||||
def __init__(self, host=None):
|
||||
self.host = host
|
||||
self.urlConf = urlConf.urls
|
||||
self.httpClint = requests
|
||||
self.city_list = []
|
||||
self.timeout = 5
|
||||
|
||||
def _set_header(self):
|
||||
"""设置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/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36",
|
||||
"Referer": "https://kyfw.12306.cn/otn/login/init",
|
||||
"Accept": "*/*",
|
||||
}
|
||||
|
||||
def get_city_id(self):
|
||||
"""
|
||||
获取所有城市md5参数
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
if self.host:
|
||||
while True:
|
||||
url = self.urlConf["cdn_host"]["req_url"]
|
||||
data = {"host": self.host, "lintType": "电信,多线,联通,移动"}
|
||||
rep = self.httpClint.post(url, data, headers=self._set_header(), timeout=self.timeout)
|
||||
city_re = re.compile(r"<li id=\"(\S+)\" class=\"PingListCent PingRLlist")
|
||||
self.city_list = re.findall(city_re, rep.content)
|
||||
if self.city_list:
|
||||
print self.city_list
|
||||
break
|
||||
else:
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
|
||||
def open_cdn_file(self):
|
||||
f = open("./cdn_list", "a+")
|
||||
return f
|
||||
|
||||
def get_cdn_list(self):
|
||||
"""
|
||||
筛选代理
|
||||
:return:
|
||||
"""
|
||||
f = self.open_cdn_file()
|
||||
url = self.urlConf["cdn_list"]["req_url"]
|
||||
num = 1
|
||||
f.seek(0)
|
||||
f.truncate()
|
||||
for guid in self.city_list:
|
||||
data = {"guid": guid,
|
||||
"host": "kyfw.12306.cn",
|
||||
"ishost": 0,
|
||||
"encode": "HJXhdRqjh5yCF6G/AZ6EDk9faB1oSk5r",
|
||||
"checktype": 0}
|
||||
try:
|
||||
cdn_info = self.httpClint.post(url, data, headers=self._set_header(), timeout=self.timeout).content
|
||||
print(cdn_info)
|
||||
if cdn_info:
|
||||
split_cdn = cdn_info.split("(")[1].rstrip(")").replace("{", "").replace("}", "").split(",")
|
||||
local_dict = collections.OrderedDict()
|
||||
for i in split_cdn:
|
||||
splits = i.split(":")
|
||||
local_dict[splits[0]] = splits[2] if splits[0] == "result" else splits[1]
|
||||
if local_dict and "state" in local_dict and local_dict["state"] == "1":
|
||||
if "responsetime" in local_dict and local_dict["responsetime"].find("毫秒") != -1 and int(filter(str.isdigit, local_dict["responsetime"])) < 100:
|
||||
f.write(json.dumps(local_dict)+"\n")
|
||||
num += 1
|
||||
except Exception as e:
|
||||
print(e.message)
|
||||
print(u"本次cdn获取完成,总个数{0}".format(num))
|
||||
|
||||
def all_cdn(self):
|
||||
"""获取cdn列表"""
|
||||
with open('./cdn_list', 'r') as f:
|
||||
cdn = f.readlines()
|
||||
return cdn
|
||||
|
||||
def par_csv(self):
|
||||
cdn_csv = csv.reader(open("../cdn1.csv", "r"))
|
||||
for c in cdn_csv:
|
||||
cdn_re = re.compile(r'https://(\S+)/otn/index/init')
|
||||
cdn_ip = re.findall(cdn_re, c[0])
|
||||
if cdn_ip and c[2] == "200":
|
||||
print(cdn_ip[0])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
cdn = CDNProxy()
|
||||
cdn.get_city_id()
|
||||
# cdn.get_cdn_list()
|
||||
cdn.par_csv()
|
||||
915
cdn_list
Normal file
915
cdn_list
Normal file
@@ -0,0 +1,915 @@
|
||||
121.14.117.148
|
||||
183.62.114.157
|
||||
183.61.26.197
|
||||
103.254.188.216
|
||||
183.62.114.247
|
||||
14.18.201.47
|
||||
14.18.17.241
|
||||
112.65.220.226
|
||||
210.38.3.42
|
||||
121.14.117.134
|
||||
159.226.225.139
|
||||
42.81.9.47
|
||||
14.18.17.249
|
||||
218.242.102.151
|
||||
111.206.186.37
|
||||
157.255.68.113
|
||||
101.227.176.34
|
||||
111.206.186.42
|
||||
101.227.102.18
|
||||
183.232.189.31
|
||||
218.78.185.210
|
||||
58.63.233.35
|
||||
14.18.201.37
|
||||
59.81.64.174
|
||||
58.63.233.24
|
||||
58.63.233.30
|
||||
101.227.176.34
|
||||
183.232.189.41
|
||||
14.18.201.48
|
||||
116.199.127.37
|
||||
116.199.127.56
|
||||
157.255.68.114
|
||||
14.18.201.36
|
||||
14.18.201.34
|
||||
111.206.193.209
|
||||
14.18.201.35
|
||||
14.18.201.28
|
||||
101.227.175.218
|
||||
101.227.176.34
|
||||
125.90.206.144
|
||||
125.90.206.182
|
||||
43.243.234.235
|
||||
101.227.97.163
|
||||
125.89.198.81
|
||||
14.119.124.101
|
||||
14.21.78.136
|
||||
61.149.9.136
|
||||
60.207.246.98
|
||||
125.90.206.143
|
||||
111.202.83.137
|
||||
60.207.246.15
|
||||
58.220.71.69
|
||||
111.206.186.41
|
||||
111.13.135.248
|
||||
111.178.233.87
|
||||
42.81.10.94
|
||||
218.242.102.138
|
||||
113.107.58.182
|
||||
61.156.243.247
|
||||
183.58.18.36
|
||||
175.43.20.81
|
||||
112.90.135.238
|
||||
125.90.204.32
|
||||
113.107.44.166
|
||||
112.91.129.184
|
||||
122.70.142.141
|
||||
218.205.75.37
|
||||
61.149.9.224
|
||||
116.199.127.55
|
||||
183.131.168.154
|
||||
114.80.143.105
|
||||
183.131.192.83
|
||||
101.227.176.34
|
||||
116.224.87.45
|
||||
116.224.86.30
|
||||
183.236.10.216
|
||||
183.131.210.66
|
||||
183.134.12.69
|
||||
101.227.175.215
|
||||
14.18.201.26
|
||||
112.90.213.65
|
||||
42.81.9.23
|
||||
42.81.10.88
|
||||
101.227.175.216
|
||||
58.220.71.71
|
||||
125.90.204.122
|
||||
219.138.21.110
|
||||
183.131.168.145
|
||||
117.144.227.9
|
||||
113.107.44.234
|
||||
117.27.241.90
|
||||
101.227.176.34
|
||||
115.231.22.125
|
||||
125.77.130.208
|
||||
222.186.145.188
|
||||
14.119.124.100
|
||||
122.225.28.145
|
||||
101.227.175.207
|
||||
112.90.135.61
|
||||
122.70.142.142
|
||||
58.63.233.29
|
||||
211.68.71.214
|
||||
36.250.87.94
|
||||
116.224.86.29
|
||||
211.68.71.215
|
||||
101.227.98.134
|
||||
183.236.28.147
|
||||
122.226.47.123
|
||||
101.227.176.34
|
||||
43.243.234.20
|
||||
116.224.87.29
|
||||
58.220.71.107
|
||||
58.216.109.186
|
||||
58.222.42.9
|
||||
58.220.72.205
|
||||
183.131.168.24
|
||||
60.210.18.222
|
||||
112.240.60.226
|
||||
58.51.241.34
|
||||
183.236.10.215
|
||||
122.225.28.79
|
||||
183.134.12.70
|
||||
60.28.100.38
|
||||
115.231.20.119
|
||||
115.231.74.76
|
||||
121.18.230.86
|
||||
183.134.9.59
|
||||
36.25.241.152
|
||||
183.131.168.23
|
||||
42.48.110.26
|
||||
183.236.28.144
|
||||
125.90.204.33
|
||||
58.253.193.135
|
||||
113.107.57.43
|
||||
42.81.9.22
|
||||
60.28.100.26
|
||||
124.236.97.222
|
||||
111.161.22.27
|
||||
182.140.147.106
|
||||
122.225.28.75
|
||||
183.134.11.90
|
||||
61.155.237.22
|
||||
101.227.176.34
|
||||
116.224.86.30
|
||||
125.90.205.2
|
||||
221.179.172.203
|
||||
112.90.212.126
|
||||
42.245.252.136
|
||||
125.90.204.52
|
||||
183.232.189.180
|
||||
125.90.206.223
|
||||
183.134.9.58
|
||||
59.56.26.49
|
||||
221.206.120.101
|
||||
58.223.166.231
|
||||
43.226.162.32
|
||||
125.77.130.216
|
||||
163.177.243.251
|
||||
111.206.239.24
|
||||
122.225.28.83
|
||||
113.96.161.100
|
||||
222.245.77.74
|
||||
120.221.66.243
|
||||
42.81.28.75
|
||||
58.51.241.28
|
||||
222.246.212.91
|
||||
125.90.204.54
|
||||
180.97.217.77
|
||||
183.134.14.143
|
||||
61.155.237.56
|
||||
183.134.10.85
|
||||
183.131.168.20
|
||||
122.226.47.106
|
||||
58.220.72.206
|
||||
113.107.57.214
|
||||
60.174.243.166
|
||||
101.227.176.34
|
||||
183.131.210.66
|
||||
183.236.28.143
|
||||
111.206.186.245
|
||||
120.241.66.116
|
||||
122.226.47.105
|
||||
122.225.28.80
|
||||
183.61.26.225
|
||||
183.134.53.224
|
||||
14.215.228.48
|
||||
221.179.172.206
|
||||
42.81.28.99
|
||||
101.70.152.37
|
||||
112.90.246.87
|
||||
61.167.54.109
|
||||
115.231.20.38
|
||||
60.5.255.222
|
||||
117.144.227.14
|
||||
61.147.227.244
|
||||
113.107.46.84
|
||||
14.119.124.41
|
||||
111.161.120.54
|
||||
202.75.220.124
|
||||
111.206.186.50
|
||||
222.245.77.19
|
||||
101.227.176.34
|
||||
122.225.28.80
|
||||
218.92.220.16
|
||||
223.151.245.16
|
||||
116.224.86.46
|
||||
61.184.116.79
|
||||
43.226.162.20
|
||||
101.71.32.162
|
||||
101.227.176.34
|
||||
202.75.220.124
|
||||
115.231.20.37
|
||||
111.161.120.50
|
||||
153.99.235.197
|
||||
113.107.44.245
|
||||
123.183.164.136
|
||||
111.6.184.9
|
||||
101.227.102.199
|
||||
42.81.28.74
|
||||
117.23.6.81
|
||||
183.57.28.61
|
||||
111.6.184.243
|
||||
221.202.204.253
|
||||
101.227.176.34
|
||||
117.144.227.14
|
||||
221.179.172.205
|
||||
101.227.175.42
|
||||
113.16.209.171
|
||||
111.206.239.19
|
||||
42.81.28.114
|
||||
115.231.20.39
|
||||
58.51.168.196
|
||||
61.147.211.20
|
||||
14.21.78.135
|
||||
125.90.47.177
|
||||
101.71.32.157
|
||||
124.236.97.221
|
||||
111.161.22.15
|
||||
115.231.20.40
|
||||
112.17.2.110
|
||||
58.222.19.61
|
||||
111.206.239.35
|
||||
111.206.239.44
|
||||
101.227.176.34
|
||||
101.71.32.157
|
||||
223.151.245.45
|
||||
106.3.62.194
|
||||
125.90.206.136
|
||||
183.214.132.122
|
||||
117.23.2.85
|
||||
60.220.194.210
|
||||
111.161.22.17
|
||||
111.206.239.53
|
||||
122.225.28.146
|
||||
122.228.22.248
|
||||
183.131.208.60
|
||||
221.179.172.238
|
||||
111.161.120.199
|
||||
221.233.145.198
|
||||
153.99.235.198
|
||||
113.16.210.132
|
||||
122.70.142.39
|
||||
59.56.30.221
|
||||
101.66.224.145
|
||||
14.215.100.72
|
||||
111.161.120.63
|
||||
220.194.203.66
|
||||
125.39.1.138
|
||||
116.207.132.219
|
||||
101.227.176.34
|
||||
101.227.176.34
|
||||
183.134.12.69
|
||||
101.227.176.34
|
||||
183.131.208.60
|
||||
101.227.176.34
|
||||
183.134.53.224
|
||||
101.227.176.34
|
||||
122.225.28.146
|
||||
101.227.176.34
|
||||
183.131.168.20
|
||||
101.227.176.34
|
||||
122.225.28.83
|
||||
101.227.176.34
|
||||
122.225.28.79
|
||||
183.214.133.48
|
||||
36.99.32.179
|
||||
111.6.185.245
|
||||
101.227.102.176
|
||||
101.71.32.153
|
||||
42.81.28.118
|
||||
218.75.225.192
|
||||
61.147.211.40
|
||||
115.231.20.108
|
||||
101.227.102.175
|
||||
115.231.20.115
|
||||
58.222.19.49
|
||||
59.63.234.87
|
||||
180.97.178.170
|
||||
222.245.78.6
|
||||
101.227.102.173
|
||||
221.235.187.132
|
||||
60.210.23.47
|
||||
111.178.233.88
|
||||
115.231.171.14
|
||||
101.227.176.34
|
||||
180.97.178.170
|
||||
59.63.244.94
|
||||
222.245.77.75
|
||||
110.18.244.63
|
||||
117.149.145.87
|
||||
115.231.171.13
|
||||
58.51.168.194
|
||||
221.180.209.125
|
||||
59.63.227.214
|
||||
58.216.21.25
|
||||
211.91.168.40
|
||||
101.227.176.34
|
||||
115.231.171.13
|
||||
59.56.30.194
|
||||
115.231.171.17
|
||||
183.66.109.245
|
||||
115.231.171.16
|
||||
42.81.28.117
|
||||
218.60.51.254
|
||||
180.97.180.45
|
||||
58.216.21.22
|
||||
124.239.186.165
|
||||
101.227.176.34
|
||||
115.231.171.16
|
||||
183.131.124.101
|
||||
113.16.212.189
|
||||
115.231.74.154
|
||||
58.220.39.92
|
||||
112.17.2.18
|
||||
119.6.226.144
|
||||
43.226.162.63
|
||||
61.155.237.48
|
||||
182.140.218.64
|
||||
211.91.168.24
|
||||
222.245.77.21
|
||||
153.101.56.251
|
||||
125.90.204.42
|
||||
111.161.120.65
|
||||
113.16.208.101
|
||||
222.243.141.100
|
||||
121.22.252.52
|
||||
61.54.84.212
|
||||
221.235.187.129
|
||||
222.243.141.95
|
||||
111.161.22.16
|
||||
61.184.117.52
|
||||
124.225.163.31
|
||||
119.6.226.157
|
||||
61.184.117.30
|
||||
211.142.197.57
|
||||
222.243.141.98
|
||||
61.184.116.78
|
||||
101.227.176.34
|
||||
58.220.39.92
|
||||
123.138.157.109
|
||||
218.60.51.253
|
||||
222.180.166.229
|
||||
111.161.122.176
|
||||
111.206.239.49
|
||||
116.211.79.26
|
||||
58.216.21.253
|
||||
116.211.79.27
|
||||
111.47.221.223
|
||||
211.91.168.35
|
||||
123.138.128.106
|
||||
101.227.102.185
|
||||
221.235.187.134
|
||||
221.235.187.133
|
||||
115.231.171.18
|
||||
211.91.168.33
|
||||
211.91.168.31
|
||||
220.202.77.119
|
||||
101.227.176.34
|
||||
115.231.171.14
|
||||
27.148.151.214
|
||||
111.47.221.244
|
||||
211.91.168.34
|
||||
101.227.176.34
|
||||
183.131.124.101
|
||||
101.227.176.34
|
||||
122.226.47.106
|
||||
101.227.176.34
|
||||
122.226.47.105
|
||||
101.227.176.34
|
||||
58.216.21.253
|
||||
61.147.210.175
|
||||
218.58.206.55
|
||||
58.221.78.39
|
||||
61.149.22.99
|
||||
111.202.83.253
|
||||
60.28.100.165
|
||||
218.77.92.243
|
||||
60.210.23.112
|
||||
118.180.15.113
|
||||
180.97.244.192
|
||||
182.140.130.25
|
||||
115.231.20.49
|
||||
111.47.220.214
|
||||
125.77.134.79
|
||||
222.218.87.131
|
||||
111.47.219.83
|
||||
218.29.49.71
|
||||
101.227.98.24
|
||||
171.90.249.191
|
||||
101.227.176.34
|
||||
122.228.233.208
|
||||
111.62.244.178
|
||||
36.248.5.36
|
||||
117.27.243.113
|
||||
58.216.109.187
|
||||
58.220.71.109
|
||||
101.227.176.34
|
||||
58.216.109.187
|
||||
58.223.166.227
|
||||
182.106.194.107
|
||||
58.222.42.59
|
||||
180.97.244.205
|
||||
58.50.31.33
|
||||
221.229.202.149
|
||||
115.231.22.80
|
||||
125.46.22.125
|
||||
60.217.22.146
|
||||
180.97.244.193
|
||||
101.227.176.34
|
||||
115.231.171.17
|
||||
59.49.42.253
|
||||
218.60.51.46
|
||||
202.118.10.115
|
||||
124.239.147.112
|
||||
218.92.220.17
|
||||
103.254.191.185
|
||||
182.140.236.57
|
||||
222.211.64.91
|
||||
101.227.176.34
|
||||
218.92.220.17
|
||||
222.20.147.174
|
||||
101.66.224.100
|
||||
183.66.109.244
|
||||
58.218.208.199
|
||||
60.174.241.88
|
||||
222.55.12.67
|
||||
117.144.227.49
|
||||
36.25.241.156
|
||||
122.70.142.34
|
||||
218.21.175.198
|
||||
150.138.169.233
|
||||
36.250.87.27
|
||||
202.118.10.117
|
||||
106.3.62.212
|
||||
101.66.224.112
|
||||
111.6.177.209
|
||||
58.222.19.45
|
||||
14.215.100.48
|
||||
36.99.32.182
|
||||
219.138.21.63
|
||||
111.41.54.182
|
||||
36.102.235.206
|
||||
218.12.228.96
|
||||
222.89.68.50
|
||||
125.77.130.215
|
||||
36.99.32.181
|
||||
101.227.176.34
|
||||
101.66.224.100
|
||||
113.16.212.192
|
||||
111.62.240.181
|
||||
59.56.26.18
|
||||
182.106.194.110
|
||||
113.207.77.191
|
||||
59.44.30.114
|
||||
101.66.224.148
|
||||
218.205.75.186
|
||||
42.243.147.114
|
||||
139.215.210.38
|
||||
218.12.228.93
|
||||
110.18.244.76
|
||||
110.157.233.40
|
||||
218.77.2.32
|
||||
111.6.178.48
|
||||
218.12.228.95
|
||||
211.142.22.114
|
||||
60.210.23.110
|
||||
150.138.111.197
|
||||
112.51.125.201
|
||||
115.153.176.103
|
||||
183.66.109.243
|
||||
118.118.216.115
|
||||
116.207.132.220
|
||||
219.147.93.222
|
||||
222.211.64.87
|
||||
113.6.229.176
|
||||
101.227.176.34
|
||||
218.205.75.186
|
||||
125.64.102.187
|
||||
60.207.246.16
|
||||
180.97.180.150
|
||||
125.44.96.186
|
||||
139.215.210.58
|
||||
59.63.80.114
|
||||
117.161.5.207
|
||||
123.138.60.144
|
||||
125.77.130.207
|
||||
101.227.176.34
|
||||
59.81.64.174
|
||||
58.216.21.10
|
||||
49.79.232.225
|
||||
218.12.228.94
|
||||
58.216.21.23
|
||||
218.7.220.37
|
||||
180.97.178.198
|
||||
123.183.164.123
|
||||
117.21.168.19
|
||||
112.29.203.246
|
||||
218.12.228.87
|
||||
202.114.91.28
|
||||
124.239.186.159
|
||||
60.213.132.71
|
||||
113.207.70.205
|
||||
123.128.14.202
|
||||
221.180.192.143
|
||||
111.19.136.240
|
||||
59.47.226.254
|
||||
60.210.23.125
|
||||
112.240.60.46
|
||||
42.245.233.188
|
||||
218.98.27.64
|
||||
60.174.241.125
|
||||
183.66.109.3
|
||||
219.148.174.55
|
||||
122.226.47.55
|
||||
124.165.216.254
|
||||
36.250.74.100
|
||||
115.231.22.102
|
||||
59.49.42.252
|
||||
125.90.204.44
|
||||
49.79.232.224
|
||||
121.251.255.236
|
||||
221.230.143.101
|
||||
122.228.233.206
|
||||
111.8.9.196
|
||||
219.148.174.21
|
||||
221.235.187.24
|
||||
218.64.94.40
|
||||
59.80.22.192
|
||||
218.92.220.15
|
||||
110.18.244.14
|
||||
106.122.250.172
|
||||
101.227.176.34
|
||||
122.226.47.55
|
||||
183.131.208.50
|
||||
182.140.236.58
|
||||
101.227.176.34
|
||||
183.131.208.50
|
||||
111.62.244.177
|
||||
182.140.147.76
|
||||
113.16.208.70
|
||||
211.91.168.22
|
||||
124.225.162.68
|
||||
183.236.28.148
|
||||
112.51.121.164
|
||||
101.69.104.73
|
||||
43.226.162.39
|
||||
221.235.187.63
|
||||
202.171.255.153
|
||||
118.212.138.52
|
||||
219.155.204.39
|
||||
60.211.208.49
|
||||
115.231.22.29
|
||||
111.206.239.48
|
||||
218.92.220.55
|
||||
36.25.241.162
|
||||
115.231.22.33
|
||||
110.157.232.182
|
||||
113.107.112.214
|
||||
222.243.141.94
|
||||
118.212.138.132
|
||||
218.92.209.74
|
||||
123.53.139.202
|
||||
113.107.112.167
|
||||
112.90.212.116
|
||||
112.90.209.4
|
||||
211.91.168.30
|
||||
125.39.1.130
|
||||
221.230.141.78
|
||||
36.104.132.156
|
||||
222.246.212.24
|
||||
218.92.227.121
|
||||
202.171.255.156
|
||||
58.216.109.107
|
||||
111.161.120.59
|
||||
122.70.142.23
|
||||
113.107.58.17
|
||||
111.178.233.29
|
||||
101.227.176.34
|
||||
115.231.22.33
|
||||
36.250.87.29
|
||||
119.188.130.22
|
||||
218.76.94.172
|
||||
113.107.58.20
|
||||
58.216.110.2
|
||||
218.60.132.31
|
||||
121.31.28.101
|
||||
115.153.176.78
|
||||
117.23.51.105
|
||||
106.122.250.198
|
||||
112.90.212.115
|
||||
221.230.143.102
|
||||
101.227.176.34
|
||||
58.216.109.107
|
||||
115.231.22.34
|
||||
124.236.97.228
|
||||
117.187.46.241
|
||||
120.221.66.242
|
||||
36.25.241.161
|
||||
180.97.180.16
|
||||
61.184.117.53
|
||||
211.142.194.88
|
||||
58.216.23.119
|
||||
110.157.235.63
|
||||
112.90.212.114
|
||||
112.90.135.99
|
||||
211.142.194.163
|
||||
119.188.130.20
|
||||
58.216.21.24
|
||||
221.229.167.32
|
||||
211.91.168.39
|
||||
115.231.22.31
|
||||
125.77.130.209
|
||||
112.51.125.202
|
||||
61.147.210.34
|
||||
101.66.224.115
|
||||
183.214.132.121
|
||||
61.136.165.32
|
||||
222.245.77.51
|
||||
175.43.124.141
|
||||
61.155.237.50
|
||||
220.194.203.75
|
||||
220.194.200.180
|
||||
61.147.227.140
|
||||
61.184.116.33
|
||||
182.140.147.80
|
||||
113.16.212.193
|
||||
60.222.221.62
|
||||
211.142.194.67
|
||||
123.138.157.81
|
||||
222.243.141.96
|
||||
115.153.176.39
|
||||
58.222.19.72
|
||||
101.227.176.34
|
||||
101.66.224.115
|
||||
122.228.233.209
|
||||
125.39.1.128
|
||||
36.25.241.153
|
||||
59.56.30.206
|
||||
59.56.26.33
|
||||
113.207.70.204
|
||||
59.49.94.147
|
||||
58.221.78.14
|
||||
58.223.166.188
|
||||
113.207.4.115
|
||||
125.46.22.32
|
||||
111.20.250.62
|
||||
36.102.230.28
|
||||
110.53.75.44
|
||||
150.138.168.115
|
||||
101.100.190.112
|
||||
61.54.121.45
|
||||
124.167.232.125
|
||||
219.147.92.64
|
||||
218.87.111.64
|
||||
101.227.176.34
|
||||
122.228.233.209
|
||||
60.9.1.129
|
||||
122.143.27.169
|
||||
221.180.192.149
|
||||
116.211.79.25
|
||||
122.70.142.30
|
||||
36.250.74.83
|
||||
125.75.34.27
|
||||
219.147.233.232
|
||||
123.138.60.232
|
||||
150.138.214.83
|
||||
113.142.80.173
|
||||
222.186.141.186
|
||||
122.136.46.107
|
||||
101.69.146.229
|
||||
110.18.244.137
|
||||
124.164.8.65
|
||||
60.210.23.42
|
||||
124.116.133.97
|
||||
118.212.148.145
|
||||
183.131.208.85
|
||||
117.145.179.175
|
||||
125.75.32.252
|
||||
113.207.71.12
|
||||
42.123.108.8
|
||||
182.140.147.62
|
||||
221.203.4.70
|
||||
101.227.176.34
|
||||
222.186.141.186
|
||||
106.122.250.162
|
||||
42.123.117.99
|
||||
14.215.100.59
|
||||
36.104.131.6
|
||||
58.216.21.43
|
||||
125.90.204.43
|
||||
123.161.57.38
|
||||
218.92.227.85
|
||||
182.140.236.17
|
||||
220.194.200.179
|
||||
222.138.255.50
|
||||
182.140.130.15
|
||||
220.194.200.178
|
||||
125.42.203.176
|
||||
61.147.227.246
|
||||
36.250.87.26
|
||||
221.229.167.31
|
||||
27.155.72.241
|
||||
59.56.26.100
|
||||
61.157.122.58
|
||||
122.228.233.15
|
||||
218.12.228.92
|
||||
121.18.230.46
|
||||
112.90.246.108
|
||||
117.21.168.87
|
||||
42.123.107.43
|
||||
124.239.186.154
|
||||
123.128.14.223
|
||||
111.6.176.115
|
||||
36.104.131.8
|
||||
123.53.139.232
|
||||
111.47.221.228
|
||||
119.6.226.148
|
||||
58.222.19.50
|
||||
42.56.80.122
|
||||
61.163.111.75
|
||||
61.54.7.193
|
||||
101.100.190.104
|
||||
113.207.4.66
|
||||
115.153.176.66
|
||||
101.227.176.34
|
||||
101.227.102.182
|
||||
58.216.21.43
|
||||
58.221.78.105
|
||||
117.145.179.85
|
||||
219.148.174.43
|
||||
106.3.62.213
|
||||
113.207.79.197
|
||||
219.148.174.54
|
||||
61.54.84.99
|
||||
59.44.25.59
|
||||
221.235.187.64
|
||||
182.140.218.63
|
||||
219.144.78.197
|
||||
60.13.41.74
|
||||
117.23.51.76
|
||||
101.69.104.74
|
||||
121.31.23.53
|
||||
117.23.51.77
|
||||
113.16.210.131
|
||||
106.122.250.194
|
||||
14.215.231.134
|
||||
60.5.254.21
|
||||
125.39.1.129
|
||||
106.122.252.2
|
||||
111.20.250.25
|
||||
211.97.73.244
|
||||
125.44.96.185
|
||||
60.5.254.42
|
||||
60.222.221.66
|
||||
27.148.151.187
|
||||
112.51.125.198
|
||||
122.228.22.247
|
||||
175.43.124.144
|
||||
121.18.230.42
|
||||
125.46.22.126
|
||||
221.235.187.62
|
||||
218.76.105.86
|
||||
112.84.104.48
|
||||
211.142.194.69
|
||||
61.167.54.238
|
||||
222.89.68.32
|
||||
122.228.233.182
|
||||
101.227.176.34
|
||||
58.221.78.105
|
||||
219.148.174.23
|
||||
14.204.74.92
|
||||
124.163.204.105
|
||||
221.229.203.218
|
||||
110.18.244.140
|
||||
59.56.26.17
|
||||
61.188.191.85
|
||||
117.27.245.87
|
||||
150.138.214.84
|
||||
60.174.241.22
|
||||
111.8.9.204
|
||||
180.97.244.206
|
||||
112.90.212.38
|
||||
125.46.22.29
|
||||
58.221.78.91
|
||||
110.18.244.141
|
||||
123.138.60.145
|
||||
221.204.31.100
|
||||
122.138.54.177
|
||||
182.140.147.61
|
||||
111.20.250.26
|
||||
223.111.130.121
|
||||
60.174.241.23
|
||||
60.223.235.142
|
||||
211.142.194.28
|
||||
60.255.143.124
|
||||
36.33.158.48
|
||||
27.148.151.17
|
||||
119.36.82.248
|
||||
125.77.130.214
|
||||
113.207.77.192
|
||||
61.156.243.234
|
||||
222.211.64.51
|
||||
101.227.176.34
|
||||
180.97.180.16
|
||||
61.136.167.72
|
||||
218.92.221.212
|
||||
111.6.192.131
|
||||
58.216.21.21
|
||||
101.227.176.34
|
||||
61.156.243.233
|
||||
221.229.167.32
|
||||
27.148.151.213
|
||||
60.217.22.143
|
||||
58.221.78.17
|
||||
211.97.76.170
|
||||
121.18.230.43
|
||||
60.5.254.39
|
||||
61.132.238.115
|
||||
220.194.200.232
|
||||
111.23.11.52
|
||||
121.18.168.68
|
||||
211.142.22.81
|
||||
117.27.245.88
|
||||
218.26.75.207
|
||||
101.227.176.34
|
||||
58.221.78.17
|
||||
117.27.241.99
|
||||
221.182.135.118
|
||||
182.243.62.48
|
||||
113.59.38.227
|
||||
113.107.44.93
|
||||
118.212.138.181
|
||||
219.157.114.80
|
||||
110.18.246.10
|
||||
218.76.105.168
|
||||
117.27.241.110
|
||||
218.12.228.38
|
||||
60.174.241.29
|
||||
115.153.176.80
|
||||
125.46.22.28
|
||||
120.221.64.229
|
||||
117.27.245.75
|
||||
121.18.230.47
|
||||
183.214.140.236
|
||||
125.46.22.31
|
||||
101.227.176.34
|
||||
58.216.110.2
|
||||
60.5.254.40
|
||||
122.228.24.167
|
||||
117.27.245.85
|
||||
219.146.68.84
|
||||
116.211.248.165
|
||||
218.7.220.40
|
||||
60.5.254.10
|
||||
150.138.214.95
|
||||
36.248.10.49
|
||||
150.138.214.85
|
||||
117.187.19.46
|
||||
123.128.14.197
|
||||
58.216.109.181
|
||||
220.194.200.177
|
||||
61.157.124.209
|
||||
150.138.169.29
|
||||
218.92.209.100
|
||||
123.138.60.143
|
||||
218.29.50.13
|
||||
59.63.80.126
|
||||
123.128.14.201
|
||||
117.27.245.62
|
||||
113.5.80.125
|
||||
101.227.176.34
|
||||
122.228.24.167
|
||||
110.18.244.142
|
||||
221.229.202.148
|
||||
218.29.50.48
|
||||
27.148.163.158
|
||||
60.174.241.27
|
||||
101.227.176.34
|
||||
218.92.209.100
|
||||
202.98.156.62
|
||||
182.140.236.27
|
||||
110.19.182.95
|
||||
101.227.176.34
|
||||
36.25.241.161
|
||||
101.227.176.34
|
||||
58.222.19.45
|
||||
101.227.176.34
|
||||
180.97.178.198
|
||||
101.227.176.34
|
||||
49.79.232.225
|
||||
101.227.176.34
|
||||
61.147.211.20
|
||||
101.227.176.34
|
||||
36.25.241.153
|
||||
117.131.213.238
|
||||
82
config/configCommon.py
Normal file
82
config/configCommon.py
Normal file
@@ -0,0 +1,82 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import time
|
||||
|
||||
saleMinDelayDay = 0
|
||||
saleMaxDelayDay = 59
|
||||
saleStartTime = "06:00:00"
|
||||
saleStopTime = "23:00:00"
|
||||
rushRefreshMinTimeIntval = 2000
|
||||
rushRefreshMaxTimeIntval = 3600000
|
||||
rushRefreshTimeIntval = 100
|
||||
|
||||
RS_SUC = 0
|
||||
RS_TIMEOUT = 1
|
||||
RS_JSON_ERROR = 2
|
||||
RS_OTHER_ERROR = 3
|
||||
|
||||
|
||||
def getNowTimestamp():
|
||||
return time.time()
|
||||
|
||||
|
||||
def getMinimumDate():
|
||||
return time.localtime(getNowTimestamp() + saleMinDelayDay * 24 * 3600)[:3]
|
||||
|
||||
|
||||
def getMaximumDate():
|
||||
return time.localtime(getNowTimestamp() + saleMaxDelayDay * 24 * 3600)[:3]
|
||||
|
||||
|
||||
def getMinimumTime():
|
||||
return [int(x) for x in saleStartTime.split(":")]
|
||||
|
||||
|
||||
def getMaximumTime():
|
||||
return [int(x) for x in saleStopTime.split(":")]
|
||||
|
||||
|
||||
def decMakeDir(func):
|
||||
def handleFunc(*args, **kwargs):
|
||||
dirname = func(*args, **kwargs)
|
||||
if not os.path.exists(dirname):
|
||||
os.makedirs(dirname)
|
||||
elif not os.path.isdir(dirname):
|
||||
pass
|
||||
|
||||
return dirname
|
||||
|
||||
return func
|
||||
|
||||
|
||||
def getWorkDir():
|
||||
return os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
|
||||
@decMakeDir
|
||||
def getTmpDir():
|
||||
return os.path.join(getWorkDir(), "tmp")
|
||||
|
||||
|
||||
@decMakeDir
|
||||
def getLogDir():
|
||||
return os.path.join(getTmpDir(), "log")
|
||||
|
||||
|
||||
@decMakeDir
|
||||
def getCacheDir():
|
||||
return os.path.join(getTmpDir(), "cache")
|
||||
|
||||
|
||||
@decMakeDir
|
||||
def getVCodeDir():
|
||||
return os.path.join(getTmpDir(), "vcode")
|
||||
|
||||
|
||||
def getVCodeImageFile(imageName):
|
||||
return os.path.join(getVCodeDir(), imageName + ".jpg")
|
||||
|
||||
|
||||
def getCacheFile(cacheType):
|
||||
return os.path.join(getCacheDir(), cacheType + ".cache")
|
||||
42
config/emailConf.py
Normal file
42
config/emailConf.py
Normal file
@@ -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, 'plain', '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)
|
||||
61
config/logger.py
Normal file
61
config/logger.py
Normal file
@@ -0,0 +1,61 @@
|
||||
#coding: utf-8
|
||||
|
||||
import os
|
||||
import time
|
||||
import logging
|
||||
|
||||
from config import configCommon
|
||||
|
||||
logger = None
|
||||
loggerHandler = None
|
||||
dateStr = '' #默认拥有日期后缀
|
||||
suffix = '' #除了日期外的后缀
|
||||
|
||||
def setSuffix(s):
|
||||
global suffix
|
||||
suffix = s
|
||||
|
||||
def getTodayDateStr():
|
||||
return time.strftime("%Y-%m-%d", time.localtime(configCommon.getNowTimestamp()))
|
||||
|
||||
def setDateStr(s):
|
||||
global dateStr
|
||||
dateStr = s
|
||||
|
||||
def isAnotherDay(s):
|
||||
global dateStr
|
||||
return dateStr != s
|
||||
|
||||
def getLogFile():
|
||||
global dateStr, suffix
|
||||
rtn = os.path.join(configCommon.getLogDir(), dateStr)
|
||||
if suffix:
|
||||
rtn += "_" + suffix
|
||||
return rtn + ".log"
|
||||
|
||||
def log(msg, func = "info"):
|
||||
global logger
|
||||
if not logger:
|
||||
logger = logging.getLogger()
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
todayStr = getTodayDateStr()
|
||||
if isAnotherDay(todayStr):
|
||||
setDateStr(todayStr)
|
||||
logger.removeHandler(loggerHandler)
|
||||
|
||||
fh = logging.FileHandler(getLogFile())
|
||||
fm = logging.Formatter(u'[%(asctime)s][%(levelname)8s] --- %(message)s (%(filename)s:%(lineno)s)')
|
||||
fh.setFormatter(fm)
|
||||
|
||||
logger.addHandler(fh)
|
||||
|
||||
levels = {
|
||||
"debug": logger.debug,
|
||||
"info": logger.info,
|
||||
"warning": logger.warning,
|
||||
"error": logger.error,
|
||||
"critical": logger.critical
|
||||
}
|
||||
|
||||
levels[func](msg)
|
||||
@@ -1,8 +1,8 @@
|
||||
# -*- coding: utf8 -*-
|
||||
__author__ = 'MR.wen'
|
||||
|
||||
import os
|
||||
import yaml
|
||||
import PyQt5
|
||||
|
||||
|
||||
def _get_yaml():
|
||||
|
||||
@@ -22,44 +22,70 @@
|
||||
#ticke_peoples: 乘客
|
||||
#damatu:打码兔账号,用于自动登录
|
||||
#is_aotu_code是否自动打码,如果选择Ture,则调用打码兔打码,默认不使用打码兔
|
||||
#aotu_code_type 1为打码兔,2为若快
|
||||
#is_email: 是否需要邮件通知 ex: True or False 切记,邮箱加完一定到config目录下测试emailConf功能是否正常
|
||||
#is_cdn: 1为需要,2位本机ip查询
|
||||
|
||||
#邮箱配置 列举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-10"
|
||||
station_dates:
|
||||
- "2018-02-02"
|
||||
station_trains:
|
||||
- "T17"
|
||||
- "T297"
|
||||
# - "G2365"
|
||||
# - "G1371"
|
||||
# - "G1377"
|
||||
# - "G1329"
|
||||
# - "G1305"
|
||||
# - "G1359"
|
||||
# - "G1361"
|
||||
# - "G1373"
|
||||
# - "G1363"
|
||||
# - "G4933"
|
||||
from_station: "北京"
|
||||
to_station: "牡丹江"
|
||||
- "G2366"
|
||||
- "D1813"
|
||||
- "D2975"
|
||||
- "D1825"
|
||||
- "D1829"
|
||||
- "D2841"
|
||||
- "D1833"
|
||||
from_station: "邵阳"
|
||||
to_station: "上海"
|
||||
set_type:
|
||||
- "硬卧"
|
||||
- "一等座"
|
||||
- "二等座"
|
||||
is_more_ticket: True
|
||||
ticke_peoples:
|
||||
- ""
|
||||
- ""
|
||||
- "梁敏"
|
||||
# - "彭淑杰"
|
||||
12306count:
|
||||
# - uesr: ""
|
||||
# - pwd: "649823049lilymin"
|
||||
# - pwd: "apple1995"
|
||||
- uesr: "@qq.com"
|
||||
- pwd: "QWERTY"
|
||||
|
||||
select_refresh_interval: 0.1
|
||||
expect_refresh_interval: 0.3
|
||||
ticket_black_list_time: 3
|
||||
is_aotu_code: False
|
||||
select_refresh_interval: 0.4
|
||||
ticket_black_list_time: 6
|
||||
is_aotu_code: True
|
||||
aotu_code_type: 2
|
||||
#enable_proxy: False
|
||||
|
||||
damatu:
|
||||
uesr: ""
|
||||
pwd: "wen1995"
|
||||
pwd: "qazWSX1995"
|
||||
|
||||
email_conf:
|
||||
is_email: True
|
||||
email: "@qq.com "
|
||||
notice_email_list: "61995120@qq.com"
|
||||
username: ""
|
||||
password: "xwopwxbkupbqbfgb"
|
||||
host: "smtp.qq.com"
|
||||
|
||||
is_cdn: 2
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
235
config/urlConf.py
Normal file
235
config/urlConf.py
Normal file
@@ -0,0 +1,235 @@
|
||||
import random
|
||||
|
||||
import time
|
||||
|
||||
urls = {
|
||||
"auth": {
|
||||
"req_url": "/passport/web/auth/uamtk",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/passport?redirect=/otn/login/userLogin",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"login": {
|
||||
"req_url": "/passport/web/login",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/login/init",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
|
||||
},
|
||||
"getCodeImg": {
|
||||
"req_url": "/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand&{0}",
|
||||
"req_type": "get",
|
||||
"Referer": "https://kyfw.12306.cn/otn/login/init",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"is_logger": False,
|
||||
"is_json": False,
|
||||
},
|
||||
"codeCheck": {
|
||||
"req_url": "/passport/captcha/captcha-check",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/login/init",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"loginInit": {
|
||||
"req_url": "/otn/login/init",
|
||||
"req_type": "get",
|
||||
"Referer": "https://kyfw.12306.cn/otn/index/init",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"is_logger": False,
|
||||
"is_json": False,
|
||||
},
|
||||
"getUserInfo": {
|
||||
"req_url": "/otn/index/initMy12306",
|
||||
"req_type": "get",
|
||||
"Referer": "https://kyfw.12306.cn/otn/passport?redirect=/otn/login/userLogin",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"is_logger": False,
|
||||
"is_json": False,
|
||||
},
|
||||
"userLogin": {
|
||||
"req_url": "/otn/login/userLogin",
|
||||
"req_type": "get",
|
||||
"Referer": "https://kyfw.12306.cn/otn/passport?redirect=/otn/login/userLogin",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"uamauthclient": {
|
||||
"req_url": "/otn/uamauthclient",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/passport?redirect=/otn/login/userLogin",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"initdc_url": {
|
||||
"req_url": "/otn/confirmPassenger/initDc",
|
||||
"req_type": "get",
|
||||
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"is_logger": False,
|
||||
"is_json": False,
|
||||
},
|
||||
"get_passengerDTOs": {
|
||||
"req_url": "/otn/confirmPassenger/getPassengerDTOs",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"select_url": {
|
||||
"req_url": "/otn/leftTicket/queryZ?leftTicketDTO.train_date={0}&leftTicketDTO.from_station={1}&leftTicketDTO.to_station={2}&purpose_codes=ADULT",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"is_logger": False,
|
||||
"is_json": True,
|
||||
},
|
||||
"check_user_url": {
|
||||
"req_url": "/otn/login/checkUser",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.3,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"submit_station_url": {
|
||||
"req_url": "/otn/leftTicket/submitOrderRequest",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"checkOrderInfoUrl": {
|
||||
"req_url": "/otn/confirmPassenger/checkOrderInfo",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"getQueueCountUrl": {
|
||||
"req_url": "/otn/confirmPassenger/getQueueCount",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"checkQueueOrderUrl": {
|
||||
"req_url": "/otn/confirmPassenger/confirmSingleForQueue",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"checkRandCodeAnsyn": {
|
||||
"req_url": "/otn/passcodeNew/checkRandCodeAnsyn",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"codeImgByOrder": {
|
||||
"req_url": "/otn/passcodeNew/getPassCodeNew?module=passenger&rand=randp&%s" % random.random(),
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"is_logger": False,
|
||||
"is_json": False,
|
||||
},
|
||||
"queryOrderWaitTimeUrl": {
|
||||
"req_url": "/otn/confirmPassenger/queryOrderWaitTime",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"queryMyOrderNoCompleteUrl": {
|
||||
"req_url": "/otn/queryOrder/queryMyOrderNoComplete",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/queryOrder/initNoComplete",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"initNoCompleteUrl": {
|
||||
"req_url": "/otn/queryOrder/initNoComplete",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/queryOrder/initNoComplete",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"cancelNoCompleteMyOrder": {
|
||||
"req_url": "/otn/queryOrder/cancelNoCompleteMyOrder",
|
||||
"req_type": "post",
|
||||
"Referer": "https://kyfw.12306.cn/otn/queryOrder/initNoComplete",
|
||||
"Host": "kyfw.12306.cn",
|
||||
"re_try": 10,
|
||||
"re_time": 0.1,
|
||||
"is_logger": True,
|
||||
"is_json": True,
|
||||
},
|
||||
"cdn_host": {
|
||||
"req_url": "http://ping.chinaz.com/kyfw.12306.cn",
|
||||
"req_type": "post"
|
||||
},
|
||||
"cdn_list": {
|
||||
"req_url": "http://ping.chinaz.com/iframe.ashx?t=ping&callback=jQuery111304824429956769827_{}".format(int(round(time.time() * 1000))),
|
||||
"req_type": "post"
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ class DamatuApi():
|
||||
KEY = 'ca9507e17e8d5ddf7c57cd18d8d33010'
|
||||
HOST = 'http://api.dama2.com:7766/app/'
|
||||
|
||||
def __init__(self, username, password, file_path):
|
||||
def __init__(self, username, password, file_path=None):
|
||||
self.username = username
|
||||
self.password = password
|
||||
self.file_path = file_path
|
||||
@@ -108,13 +108,10 @@ class DamatuApi():
|
||||
return jres['ret']
|
||||
|
||||
def main(self):
|
||||
balance = self.getBalance()
|
||||
if int(balance) > 40:
|
||||
result = self.decode(287)
|
||||
img_code = result.replace('|', ',') if not isinstance(result, int) else ""
|
||||
return img_code
|
||||
else:
|
||||
raise balanceException('余额不足,当前余额为: {}'.format(balance))
|
||||
result = self.decode(287)
|
||||
img_code = result.replace('|', ',') if not isinstance(result, int) else ""
|
||||
print("验证码识别坐标为{0}".format(img_code))
|
||||
return img_code
|
||||
|
||||
# # 调用类型实例:
|
||||
# # 1.实例化类型 参数是打码兔用户账号和密码
|
||||
@@ -124,4 +121,3 @@ class DamatuApi():
|
||||
# print(dmt.decode('tkcode', 287)) # 上传打码
|
||||
# # print(dmt.decodeUrl('https://kyfw.12306.cn/otn/passcodeNew/getPassCodeNew?module=login&rand=sjrand&0.7586344633015405', 310)) # 上传打码
|
||||
# # print(dmt.reportError('894657096')) # 上报错误
|
||||
|
||||
|
||||
55
damatuCode/ruokuai.py
Normal file
55
damatuCode/ruokuai.py
Normal file
@@ -0,0 +1,55 @@
|
||||
# coding:utf-8
|
||||
import requests
|
||||
from hashlib import md5
|
||||
|
||||
|
||||
class RClient(object):
|
||||
|
||||
def __init__(self, username, password):
|
||||
self.username = username
|
||||
self.password = md5(password).hexdigest()
|
||||
self.soft_id = '96061'
|
||||
self.soft_key = '6facb9da7bb645ad9c4a229464b2cf89'
|
||||
self.base_params = {
|
||||
'username': self.username,
|
||||
'password': self.password,
|
||||
'softid': self.soft_id,
|
||||
'softkey': self.soft_key,
|
||||
}
|
||||
self.headers = {
|
||||
'Connection': 'Keep-Alive',
|
||||
'Expect': '100-continue',
|
||||
'User-Agent': 'ben',
|
||||
}
|
||||
|
||||
def rk_create(self, im, im_type, timeout=60):
|
||||
"""
|
||||
im: 图片字节
|
||||
im_type: 题目类型
|
||||
"""
|
||||
params = {
|
||||
'typeid': im_type,
|
||||
'timeout': timeout,
|
||||
}
|
||||
params.update(self.base_params)
|
||||
files = {'image': ('a.jpg', im)}
|
||||
r = requests.post('http://api.ruokuai.com/create.json', data=params, files=files, headers=self.headers)
|
||||
return r.json()
|
||||
|
||||
def rk_report_error(self, im_id):
|
||||
"""
|
||||
im_id:报错题目的ID
|
||||
"""
|
||||
params = {
|
||||
'id': im_id,
|
||||
}
|
||||
params.update(self.base_params)
|
||||
r = requests.post('http://api.ruokuai.com/reporterror.json', data=params, headers=self.headers)
|
||||
return r.json()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
rc = RClient('931128603', '',)
|
||||
im = open('tkcode', 'rb').read()
|
||||
print rc.rk_create(im, 6113)
|
||||
|
||||
410
init/login.py
410
init/login.py
@@ -3,202 +3,244 @@
|
||||
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 damatuCode.ruokuai import RClient
|
||||
from myException.UserPasswordException import UserPasswordException
|
||||
from myException.balanceException import balanceException
|
||||
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, is_aotu_code, aotu_code_type):
|
||||
self.httpClint = httpClint
|
||||
self.randCode = ""
|
||||
self.urlConf = urlConf
|
||||
self.is_aotu_code = is_aotu_code
|
||||
self.aotu_code_type = aotu_code_type
|
||||
|
||||
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(u"正在获取cookie")
|
||||
url = self.urlConf["loginInit"]
|
||||
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:
|
||||
pass
|
||||
post.append(offsetsX)
|
||||
post.append(offsetsY)
|
||||
randCode = str(post).replace(']', '').replace('[', '').replace("'", '').replace(' ', '')
|
||||
|
||||
|
||||
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"
|
||||
}
|
||||
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))
|
||||
else:
|
||||
stoidinput("验证码通过,开始登录..")
|
||||
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]))
|
||||
break
|
||||
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:
|
||||
errorinput("登录失败: %s" % tresult['messages'][0])
|
||||
stoidinput("尝试重新登陆")
|
||||
if "Error" in Result and Result["Error"]:
|
||||
print Result["Error"]
|
||||
return ""
|
||||
else:
|
||||
img = Image.open('./tkcode')
|
||||
img.show()
|
||||
return self.codexy()
|
||||
except:
|
||||
pass
|
||||
|
||||
def readImg(self, code_url):
|
||||
"""
|
||||
增加手动打码,只是登录接口,完全不用担心提交订单效率
|
||||
思路
|
||||
1.调用PIL显示图片
|
||||
2.图片位置说明,验证码图片中每个图片代表一个下标,依次类推,1,2,3,4,5,6,7,8
|
||||
3.控制台输入对应下标,按照英文逗号分开,即可手动完成打码,
|
||||
:return:
|
||||
"""
|
||||
print (u"下载验证码...")
|
||||
codeimgUrl = code_url
|
||||
img_path = './tkcode'
|
||||
result = self.httpClint.send(codeimgUrl)
|
||||
try:
|
||||
print(u"下载验证码成功")
|
||||
open(img_path, 'wb').write(result)
|
||||
except OSError as e:
|
||||
print (e)
|
||||
|
||||
def codexy(self, Ofset=None, is_raw_input=True):
|
||||
"""
|
||||
获取验证码
|
||||
:return: str
|
||||
"""
|
||||
if is_raw_input:
|
||||
Ofset = raw_input(u"请输入验证码: ")
|
||||
select = Ofset.split(',')
|
||||
post = []
|
||||
offsetsX = 0 # 选择的答案的left值,通过浏览器点击8个小图的中点得到的,这样基本没问题
|
||||
offsetsY = 0 # 选择的答案的top值
|
||||
for ofset in select:
|
||||
if ofset == '1':
|
||||
offsetsY = 46
|
||||
offsetsX = 42
|
||||
elif ofset == '2':
|
||||
offsetsY = 46
|
||||
offsetsX = 105
|
||||
elif ofset == '3':
|
||||
offsetsY = 45
|
||||
offsetsX = 184
|
||||
elif ofset == '4':
|
||||
offsetsY = 48
|
||||
offsetsX = 256
|
||||
elif ofset == '5':
|
||||
offsetsY = 36
|
||||
offsetsX = 117
|
||||
elif ofset == '6':
|
||||
offsetsY = 112
|
||||
offsetsX = 115
|
||||
elif ofset == '7':
|
||||
offsetsY = 114
|
||||
offsetsX = 181
|
||||
elif ofset == '8':
|
||||
offsetsY = 111
|
||||
offsetsX = 252
|
||||
else:
|
||||
pass
|
||||
post.append(offsetsX)
|
||||
post.append(offsetsY)
|
||||
randCode = str(post).replace(']', '').replace('[', '').replace("'", '').replace(' ', '')
|
||||
print(u"验证码识别坐标为{0}".format(randCode))
|
||||
return randCode
|
||||
|
||||
def auth(self):
|
||||
"""认证"""
|
||||
authUrl = self.urlConf["auth"]
|
||||
authData = {"appid": "otn"}
|
||||
tk = self.httpClint.send(authUrl, authData)
|
||||
return tk
|
||||
|
||||
def codeCheck(self):
|
||||
"""
|
||||
验证码校验
|
||||
:return:
|
||||
"""
|
||||
codeCheck = self.urlConf["codeCheck"]
|
||||
codeCheckData = {
|
||||
"answer": self.randCode,
|
||||
"rand": "sjrand",
|
||||
"login_site": "E"
|
||||
}
|
||||
fresult = self.httpClint.send(codeCheck, codeCheckData)
|
||||
if "result_code" in fresult and fresult["result_code"] == "4":
|
||||
print (u"验证码通过,开始登录..")
|
||||
return True
|
||||
else:
|
||||
if "result_message" in fresult:
|
||||
print(fresult["result_message"])
|
||||
sleep(1)
|
||||
self.httpClint.del_cookies()
|
||||
|
||||
def baseLogin(self, user, passwd):
|
||||
"""
|
||||
登录过程
|
||||
:param user:
|
||||
:param passwd:
|
||||
:return: 权限校验码
|
||||
"""
|
||||
logurl = self.urlConf["login"]
|
||||
logData = {
|
||||
"username": user,
|
||||
"password": passwd,
|
||||
"appid": "otn"
|
||||
}
|
||||
tresult = self.httpClint.send(logurl, logData)
|
||||
if 'result_code' in tresult and tresult["result_code"] == 0:
|
||||
print (u"登录成功")
|
||||
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(u"密码输入错误") is not -1:
|
||||
raise UserPasswordException("{0}".format(messages))
|
||||
else:
|
||||
print (u"登录失败: {0}".format(messages))
|
||||
print (u"尝试重新登陆")
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
def getUserName(self, uamtk):
|
||||
"""
|
||||
登录成功后,显示用户名
|
||||
:return:
|
||||
"""
|
||||
if not uamtk:
|
||||
return u"权限校验码不能为空"
|
||||
else:
|
||||
uamauthclientUrl = self.urlConf["uamauthclient"]
|
||||
data = {"tk": uamtk}
|
||||
uamauthclientResult = self.httpClint.send(uamauthclientUrl, data)
|
||||
if uamauthclientResult:
|
||||
if "result_code" in uamauthclientResult and uamauthclientResult["result_code"] == 0:
|
||||
print(u"欢迎 {} 登录".format(uamauthclientResult["username"]))
|
||||
return True
|
||||
else:
|
||||
stoidinput("登录成功")
|
||||
myurllib2.Post(surl, ldata)
|
||||
getUserinfo()
|
||||
return False
|
||||
else:
|
||||
self.httpClint.send(uamauthclientUrl, data)
|
||||
url = self.urlConf["getUserInfo"]
|
||||
self.httpClint.send(url)
|
||||
|
||||
def go_login(self):
|
||||
"""
|
||||
登陆
|
||||
:param user: 账户名
|
||||
: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 int(balance) < 40:
|
||||
raise balanceException(u'余额不足,当前余额为: {}'.format(balance))
|
||||
user, passwd = _get_yaml()["set"]["12306count"][0]["uesr"], _get_yaml()["set"]["12306count"][1]["pwd"]
|
||||
if not user or not passwd:
|
||||
raise UserPasswordException(u"温馨提示: 用户名或者密码为空,请仔细检查")
|
||||
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.urlConf["getCodeImg"]["req_url"] = self.urlConf["getCodeImg"]["req_url"].format(random.random())
|
||||
self.readImg(self.urlConf["getCodeImg"])
|
||||
self.randCode = self.getRandCode()
|
||||
login_num += 1
|
||||
self.auth()
|
||||
if self.codeCheck():
|
||||
uamtk = self.baseLogin(user, passwd)
|
||||
if uamtk:
|
||||
self.getUserName(uamtk)
|
||||
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 (u"已退出")
|
||||
else:
|
||||
print (u"退出失败")
|
||||
|
||||
|
||||
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()
|
||||
@@ -1,21 +1,27 @@
|
||||
# -*- coding=utf-8 -*-
|
||||
import json
|
||||
import datetime
|
||||
import json
|
||||
import random
|
||||
import re
|
||||
import threading
|
||||
import urllib
|
||||
import socket
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
import urllib
|
||||
from collections import OrderedDict
|
||||
|
||||
from agency.cdn_utils import CDNProxy
|
||||
from config import urlConf
|
||||
from config.emailConf import sendEmail
|
||||
from config.ticketConf import _get_yaml
|
||||
from damatuCode.damatuWeb import DamatuApi
|
||||
from init import login
|
||||
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')
|
||||
@@ -23,7 +29,10 @@ sys.setdefaultencoding('utf-8')
|
||||
|
||||
class select:
|
||||
def __init__(self):
|
||||
self.from_station, self.to_station, self.station_date, self._station_seat, self.is_more_ticket, self.ticke_peoples, self.select_refresh_interval, self.station_trains, self.expect_refresh_interval, self.ticket_black_list_time = self.get_ticket_info()
|
||||
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.order_request_params = {} # 订单提交时的参数
|
||||
self.ticketInfoForPassengerForm = {} # 初始化当前页面参数
|
||||
self.current_seats = {} # 席别信息
|
||||
@@ -32,6 +41,13 @@ class select:
|
||||
self.user_info = ""
|
||||
self.secretStr = ""
|
||||
self.ticket_black_list = 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.cdn_list = []
|
||||
|
||||
def get_ticket_info(self):
|
||||
"""
|
||||
@@ -41,30 +57,28 @@ class select:
|
||||
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_date = ticket_info_config["set"]["station_date"].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"]
|
||||
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}\n".format\
|
||||
print u"当前配置:出发站:{0}\n到达站:{1}\n乘车日期:{2}\n坐席:{3}\n是否有票自动提交:{4}\n乘车人:{5}\n刷新间隔:{6}\n候选购买车次:{7}\n僵尸票关小黑屋时长:{8}\n".format\
|
||||
(
|
||||
from_station,
|
||||
to_station,
|
||||
station_date,
|
||||
station_dates,
|
||||
",".join(set_type),
|
||||
is_more_ticket,
|
||||
",".join(ticke_peoples),
|
||||
select_refresh_interval,
|
||||
",".join(station_trains),
|
||||
expect_refresh_interval,
|
||||
ticket_black_list_time,
|
||||
)
|
||||
print "*"*20
|
||||
return from_station, to_station, station_date, set_type, is_more_ticket, ticke_peoples, select_refresh_interval, station_trains, expect_refresh_interval, ticket_black_list_time
|
||||
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
|
||||
@@ -127,17 +141,36 @@ class select:
|
||||
tomorrow = today+datetime.timedelta(1)
|
||||
return tomorrow.strftime('%Y-%m-%d')
|
||||
|
||||
def callReadImg(self, code_url):
|
||||
"""
|
||||
下载验证码
|
||||
:param code_url: 验证码url
|
||||
:return:
|
||||
"""
|
||||
print(code_url)
|
||||
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 = 'https://kyfw.12306.cn/otn/confirmPassenger/initDc'
|
||||
initdc_result = myurllib2.get(initdc_url)
|
||||
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=(\{.+\})?')
|
||||
# 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)
|
||||
@@ -155,46 +188,33 @@ class select:
|
||||
获取乘客信息
|
||||
:return:
|
||||
"""
|
||||
get_passengerDTOs = 'https://kyfw.12306.cn/otn/confirmPassenger/getPassengerDTOs'
|
||||
get_passengerDTOs = self.confUrl["get_passengerDTOs"]
|
||||
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] # 如果配置乘车人没有在账号,则默认返回第一个用户
|
||||
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("未查找到常用联系人")
|
||||
raise PassengerUserException("未查找到常用联系人,请先添加联系人在试试")
|
||||
print(u"未查找到常用联系人")
|
||||
raise PassengerUserException(u"未查找到常用联系人,请先添加联系人在试试")
|
||||
|
||||
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):
|
||||
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 submitOrderRequest(self, from_station, to_station):
|
||||
def submitOrderRequestImplement(self, from_station, to_station,):
|
||||
"""
|
||||
提交车次信息
|
||||
车次对应字典
|
||||
@@ -209,62 +229,69 @@ 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')
|
||||
value = station_ticket['data']
|
||||
if not value:
|
||||
print ('{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 ('车次: ' + 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("该车次{} 正在被关小黑屋,跳过此车次".format(train_no))
|
||||
break
|
||||
else:
|
||||
print ('正在尝试提交订票...')
|
||||
if self.check_user():
|
||||
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.submitOrderRequestFunc(from_station, to_station, self.time())
|
||||
self.submit_station()
|
||||
self.getPassengerTicketStr(self._station_seat[j].encode("utf8"))
|
||||
self.getRepeatSubmitToken()
|
||||
self.user_info = self.getPassengerDTOs()
|
||||
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:
|
||||
pass
|
||||
time.sleep(self.expect_refresh_interval)
|
||||
else:
|
||||
print "车次配置信息有误,或者返回数据异常,请检查 {}".format(station_ticket)
|
||||
else:
|
||||
pass
|
||||
else:
|
||||
pass
|
||||
# time.sleep(self.expect_refresh_interval)
|
||||
else:
|
||||
print u"车次配置信息有误,或者返回数据异常,请检查 {}".format(station_ticket)
|
||||
|
||||
def check_user(self):
|
||||
"""
|
||||
检查用户是否达到订票条件
|
||||
:return:
|
||||
"""
|
||||
check_user_url = 'https://kyfw.12306.cn/otn/login/checkUser'
|
||||
data = dict(_json_att=None)
|
||||
check_user = json.loads(myurllib2.Post(check_user_url, data), encoding='utf-8')
|
||||
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:
|
||||
print ('尝试提交订单...')
|
||||
return True
|
||||
self.is_check_user["user_time"] = datetime.datetime.now()
|
||||
else:
|
||||
if check_user['messages']:
|
||||
print ('用户检查失败:%s,可能未登录,可能session已经失效' % check_user['messages'][0])
|
||||
print (u'用户检查失败:%s,可能未登录,可能session已经失效' % check_user['messages'][0])
|
||||
print (u'正在尝试重新登录')
|
||||
self.call_login()
|
||||
self.is_check_user["user_time"] = datetime.datetime.now()
|
||||
else:
|
||||
print ('用户检查失败: %s,可能未登录,可能session已经失效' % check_user)
|
||||
print (u'用户检查失败: %s,可能未登录,可能session已经失效' % check_user)
|
||||
print (u'正在尝试重新登录')
|
||||
self.call_login()
|
||||
self.is_check_user["user_time"] = datetime.datetime.now()
|
||||
|
||||
def submit_station(self):
|
||||
"""
|
||||
@@ -276,8 +303,7 @@ class select:
|
||||
:param secretStr: 提交车次加密
|
||||
:return:
|
||||
"""
|
||||
|
||||
submit_station_url = 'https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest'
|
||||
submit_station_url = self.confUrl["submit_station_url"]
|
||||
data = [('secretStr', urllib.unquote(self.secretStr)), # 字符串加密
|
||||
('train_date', self.time()), # 出发时间
|
||||
('back_train_date', self.time()), # 返程时间
|
||||
@@ -286,12 +312,12 @@ 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 ('出票成功')
|
||||
print (u'出票成功')
|
||||
else:
|
||||
print ('出票失败')
|
||||
print (u'出票失败')
|
||||
elif 'messages' in submitResult and submitResult['messages']:
|
||||
raise ticketIsExitsException(submitResult['messages'][0])
|
||||
|
||||
@@ -328,24 +354,24 @@ class select:
|
||||
passengerTicketStrList = []
|
||||
oldPassengerStr = []
|
||||
if not self.user_info:
|
||||
raise PassengerUserException("联系人不在列表中,请查证后添加")
|
||||
raise PassengerUserException(u"联系人不在列表中,请查证后添加")
|
||||
if len(self.user_info) is 1:
|
||||
passengerTicketStrList.append(
|
||||
'0,' + self.user_info[0]['passenger_id_type_code'] + "," + self.user_info[0][
|
||||
'0,' + self.user_info[0]['passenger_type'] + "," + self.user_info[0][
|
||||
"passenger_name"] + "," +
|
||||
self.user_info[0]['passenger_type'] + "," + self.user_info[0]['passenger_id_no'] + "," +
|
||||
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_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]['passenger_type'] + '_')
|
||||
else:
|
||||
for i in range(len(self.user_info)):
|
||||
passengerTicketStrList.append(
|
||||
'0,' + self.user_info[i]['passenger_id_type_code'] + "," + self.user_info[i][
|
||||
"passenger_name"] + "," + self.user_info[i]['passenger_type'] + "," + self.user_info[i][
|
||||
'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_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]['passenger_type'] + '_')
|
||||
return passengerTicketStrList, oldPassengerStr
|
||||
|
||||
@@ -357,7 +383,7 @@ class select:
|
||||
:return:
|
||||
"""
|
||||
passengerTicketStrList, oldPassengerStr = self.getPassengerTicketStrListAndOldPassengerStr()
|
||||
checkOrderInfoUrl = 'https://kyfw.12306.cn/otn/confirmPassenger/checkOrderInfo'
|
||||
checkOrderInfoUrl = self.confUrl["checkOrderInfoUrl"]
|
||||
data = OrderedDict()
|
||||
data['cancel_flag'] = 2
|
||||
data['bed_level_order_num'] = "000000000000000000000000000000"
|
||||
@@ -366,14 +392,14 @@ 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
|
||||
if self.getQueueCount(train_no, set_type, is_need_code):
|
||||
return True
|
||||
if "ifShowPassCode" in checkOrderInfo["data"] and checkOrderInfo['data']['submitStatus'] is True:
|
||||
print ('车票提交通过,正在尝试排队')
|
||||
print (u'车票提交通过,正在尝试排队')
|
||||
is_need_code = False
|
||||
if self.getQueueCount(train_no, set_type, is_need_code):
|
||||
return True
|
||||
@@ -393,13 +419,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"]
|
||||
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,38 +434,48 @@ 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):
|
||||
print("当前余票数小于乘车人数,放弃订票")
|
||||
print(u"当前余票数小于乘车人数,放弃订票")
|
||||
else:
|
||||
print("排队成功, 当前余票还剩余: {0} 张".format(ticket_split))
|
||||
print(u"排队成功, 当前余票还剩余: {0} 张".format(ticket_split))
|
||||
if self.checkQueueOrder(is_need_code):
|
||||
return True
|
||||
else:
|
||||
print("当前排队人数:" + str(countT) + "当前余票还剩余:{0} 张,继续排队中".format(ticket_split))
|
||||
print(u"当前排队人数: {1} 当前余票还剩余:{0} 张,继续排队中".format(ticket_split, countT))
|
||||
else:
|
||||
print("排队发现未知错误{0},将此列车 {1}加入小黑屋".format(getQueueCountResult, train_no))
|
||||
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("排队异常,错误信息:{0}, 将此列车 {1}加入小黑屋".format(getQueueCountResult["messages"][0], train_no))
|
||||
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("未知错误 {0}".format("".join(getQueueCountResult)))
|
||||
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):
|
||||
"""
|
||||
@@ -450,7 +484,7 @@ class select:
|
||||
"""
|
||||
|
||||
passengerTicketStrList, oldPassengerStr = self.getPassengerTicketStrListAndOldPassengerStr()
|
||||
checkQueueOrderUrl = "https://kyfw.12306.cn/otn/confirmPassenger/confirmSingleForQueue"
|
||||
checkQueueOrderUrl = self.confUrl["checkQueueOrderUrl"]
|
||||
data = {
|
||||
"passengerTicketStr": self.set_type + "," + ",".join(passengerTicketStrList).rstrip("_{0}".format(self.set_type)),
|
||||
"oldPassengerStr": "".join(oldPassengerStr),
|
||||
@@ -461,101 +495,91 @@ 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)
|
||||
img_path = './tkcode'
|
||||
open(img_path, 'wb').write(result)
|
||||
randCode = DamatuApi(_get_yaml()["damatu"]["uesr"], _get_yaml()["damatu"]["pwd"],
|
||||
img_path).main()
|
||||
randData = {
|
||||
"randCode": randCode,
|
||||
"rand": "randp",
|
||||
"_json_att": None,
|
||||
"REPEAT_SUBMIT_TOKEN": self.get_token()
|
||||
}
|
||||
fresult = json.loads(myurllib2.Post(randurl, randData), encoding='utf8') # 校验验证码是否正确
|
||||
checkcode = fresult['data']['msg']
|
||||
if checkcode == 'FALSE':
|
||||
print ("验证码有误,第{}次尝试重试".format(i))
|
||||
else:
|
||||
print("验证码通过,正在提交订单")
|
||||
if is_node_code:
|
||||
print(u"正在使用自动识别验证码功能")
|
||||
for i in range(3):
|
||||
codeImgByOrder = self.confUrl["codeImgByOrder"]
|
||||
self.login.readImg(codeImgByOrder)
|
||||
randCode = self.login.getRandCode()
|
||||
checkcode = self.checkRandCodeAnsyn(randCode)
|
||||
if checkcode == 'TRUE':
|
||||
print(u"验证码通过,正在提交订单")
|
||||
data['randCode'] = randCode
|
||||
break
|
||||
else:
|
||||
print("不需要验证码")
|
||||
break
|
||||
checkQueueOrderResult = json.loads(myurllib2.Post(checkQueueOrderUrl, data))
|
||||
else:
|
||||
print (u"验证码有误, {0}次尝试重试".format(i+1))
|
||||
print(u"验证码超过限定次数3次,放弃此次订票机会!")
|
||||
else:
|
||||
print(u"不需要验证码")
|
||||
time.sleep(0.5)
|
||||
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("提交订单成功!")
|
||||
print(u"提交订单成功!")
|
||||
self.queryOrderWaitTime()
|
||||
else:
|
||||
if 'errMsg' in c_data and c_data['errMsg']:
|
||||
print("提交订单失败,{0}".format(c_data['errMsg']))
|
||||
print(u"提交订单失败,{0}".format(c_data['errMsg']))
|
||||
else:
|
||||
print(c_data)
|
||||
print('订票失败!很抱歉,请重试提交预订功能!')
|
||||
print(u'订票失败!很抱歉,请重试提交预订功能!')
|
||||
elif "messages" in checkQueueOrderResult and checkQueueOrderResult["messages"]:
|
||||
print("提交订单失败,错误信息: " + checkQueueOrderResult["messages"])
|
||||
print(u"提交订单失败,错误信息: " + checkQueueOrderResult["messages"])
|
||||
else:
|
||||
print("提交订单中,请耐心等待:" + str(checkQueueOrderResult["validateMessages"]))
|
||||
print(u"提交订单中,请耐心等待:" + checkQueueOrderResult["message"])
|
||||
except ValueError:
|
||||
print("接口 {} 无响应".format(checkQueueOrderUrl))
|
||||
print(u"接口 {} 无响应".format(checkQueueOrderUrl))
|
||||
|
||||
def queryOrderWaitTime(self):
|
||||
"""
|
||||
排队获取订单等待信息,每隔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))
|
||||
num += 1
|
||||
if num > 30:
|
||||
print("超出排队时间,自动放弃,正在重新刷票")
|
||||
print(u"超出排队时间,自动放弃,正在重新刷票")
|
||||
order_id = self.queryMyOrderNoComplete() # 排队失败,自动取消排队订单
|
||||
if order_id:
|
||||
self.cancelNoCompleteMyOrder(order_id)
|
||||
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"]
|
||||
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:
|
||||
raise ticketIsExitsException("恭喜您订票成功,订单号为:{0}, 请立即打开浏览器登录12306,访问‘未完成订单’,在30分钟内完成支付!".format(queryOrderWaitTimeResult["data"]["orderId"]))
|
||||
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("排队等待时间预计还剩 {0} ms".format(0-queryOrderWaitTimeResult["data"]["waitTime"]))
|
||||
print(u"排队等待时间预计还剩 {0} ms".format(0-queryOrderWaitTimeResult["data"]["waitTime"]))
|
||||
else:
|
||||
print ("正在等待中")
|
||||
elif "messages" in queryOrderWaitTimeResult and queryOrderWaitTimeResult["messages"]:
|
||||
print("排队等待失败: " + queryOrderWaitTimeResult["messages"])
|
||||
print(u"排队等待失败: " + queryOrderWaitTimeResult["messages"])
|
||||
else:
|
||||
print("第{}排队中,请耐心等待".format(num))
|
||||
print(u"第{}次排队中,请耐心等待".format(num+1))
|
||||
else:
|
||||
print("排队中")
|
||||
print(u"排队中")
|
||||
time.sleep(2)
|
||||
order_id = self.queryMyOrderNoComplete() # 尝试查看订单列表,如果有订单,则判断成功,不过一般可能性不大
|
||||
if order_id:
|
||||
raise ticketIsExitsException("恭喜您订票成功,订单号为:{0}, 请立即打开浏览器登录12306,访问‘未完成订单’,在30分钟内完成支付!".format(order_id))
|
||||
|
||||
else:
|
||||
print(ticketNumOutException("订单提交失败!,正在重新刷票"))
|
||||
print(ticketNumOutException(u"订单提交失败!,正在重新刷票"))
|
||||
|
||||
def queryMyOrderNoComplete(self):
|
||||
"""
|
||||
@@ -563,10 +587,10 @@ class select:
|
||||
:return:
|
||||
"""
|
||||
self.initNoComplete()
|
||||
queryMyOrderNoCompleteUrl = "https://kyfw.12306.cn/otn/queryOrder/queryMyOrderNoComplete"
|
||||
data = {"_json_att": None}
|
||||
queryMyOrderNoCompleteUrl = self.confUrl["queryMyOrderNoCompleteUrl"]
|
||||
data = {"_json_att": ""}
|
||||
try:
|
||||
queryMyOrderNoCompleteResult = json.loads(myurllib2.Post(queryMyOrderNoCompleteUrl, data))
|
||||
queryMyOrderNoCompleteResult = self.httpClint.send(queryMyOrderNoCompleteUrl, data)
|
||||
except ValueError:
|
||||
queryMyOrderNoCompleteResult = {}
|
||||
if queryMyOrderNoCompleteResult:
|
||||
@@ -584,86 +608,145 @@ class select:
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
print("接口 {} 无响应".format(queryMyOrderNoCompleteUrl))
|
||||
print(u"接口 {} 无响应".format(queryMyOrderNoCompleteUrl))
|
||||
|
||||
def initNoComplete(self):
|
||||
"""
|
||||
获取订单前需要进入订单列表页,获取订单列表页session
|
||||
:return:
|
||||
"""
|
||||
initNoCompleteUrl = "https://kyfw.12306.cn/otn/queryOrder/initNoComplete"
|
||||
data = {"_json_att": None}
|
||||
myurllib2.Post(initNoCompleteUrl, data)
|
||||
self.httpClint.set_cookies(acw_tc="AQAAAEnFJnekLwwAtGHjZZCr79B6dpXk", current_captcha_type="Z")
|
||||
initNoCompleteUrl = self.confUrl["initNoCompleteUrl"]
|
||||
data = {"_json_att": ""}
|
||||
self.httpClint.send(initNoCompleteUrl, data)
|
||||
|
||||
# def call_submit_ticket(self, function_name=None):
|
||||
# """
|
||||
# 订票失败回调方法,默认执行submitOrderRequest()
|
||||
# 此方法暂不使用
|
||||
# :param function_name:
|
||||
# :return:
|
||||
# """
|
||||
# if function_name:
|
||||
# self.function_name()
|
||||
# else:
|
||||
# self.submitOrderRequest()
|
||||
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):
|
||||
"""
|
||||
登录回调方法
|
||||
:return:
|
||||
"""
|
||||
if auth:
|
||||
return self.login.auth()
|
||||
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 < 400:
|
||||
self.cdn_list.append(cdn[i].replace("\n", ""))
|
||||
|
||||
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()
|
||||
self.call_login()
|
||||
from_station, to_station = self.station_table(self.from_station, self.to_station)
|
||||
if self.leftTicketLog(from_station, to_station):
|
||||
num = 1
|
||||
while 1:
|
||||
try:
|
||||
num += 1
|
||||
time.sleep(self.select_refresh_interval)
|
||||
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)
|
||||
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 ValueError as e:
|
||||
if e.message == "No JSON object could be decoded":
|
||||
print("12306接口无响应,正在重试")
|
||||
else:
|
||||
print(e.message)
|
||||
except KeyError as e:
|
||||
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()
|
||||
time.sleep(self.select_refresh_interval)
|
||||
if time.strftime('%H:%M:%S', time.localtime(time.time())) > "23:00:00":
|
||||
print u"12306休息时间,本程序自动停止,明天早上6点将自动运行"
|
||||
time.sleep(60 * 60 * 7)
|
||||
self.call_login()
|
||||
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()
|
||||
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)
|
||||
|
||||
|
||||
# class selectProducer(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):
|
||||
# pass
|
||||
#
|
||||
#
|
||||
# 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):
|
||||
# pass
|
||||
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__':
|
||||
a = select('上海', '北京')
|
||||
a.main()
|
||||
login()
|
||||
# a = select('上海', '北京')
|
||||
# a.main()
|
||||
2
myException/UserPasswordException.py
Normal file
2
myException/UserPasswordException.py
Normal file
@@ -0,0 +1,2 @@
|
||||
class UserPasswordException(Exception):
|
||||
pass
|
||||
@@ -1,7 +1,12 @@
|
||||
# -*- coding: utf8 -*-
|
||||
import datetime
|
||||
import json
|
||||
import socket
|
||||
from time import sleep
|
||||
|
||||
import requests
|
||||
|
||||
from config import logger
|
||||
|
||||
|
||||
class HTTPClient(object):
|
||||
|
||||
@@ -10,45 +15,121 @@ 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()
|
||||
self._cdn = None
|
||||
|
||||
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}
|
||||
def resetHeaders(self):
|
||||
self._s.headers.clear()
|
||||
self._s.headers.update(self._set_header())
|
||||
|
||||
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
|
||||
|
||||
@property
|
||||
def cdn(self):
|
||||
return self._cdn
|
||||
|
||||
@cdn.setter
|
||||
def cdn(self, cdn):
|
||||
self._cdn = cdn
|
||||
|
||||
def send(self, urls, data=None, **kwargs):
|
||||
"""send request to url.If response 200,return response, else return None."""
|
||||
allow_redirects = False
|
||||
is_logger = urls["is_logger"]
|
||||
error_data = {"code": 99999, "message": u"重试次数达到上限"}
|
||||
self.setHeadersReferer(urls["Referer"])
|
||||
if data:
|
||||
method = "post"
|
||||
self.setHeaders({"Content-Length": "{0}".format(len(data))})
|
||||
else:
|
||||
proxies = ""
|
||||
response = self.session.request(method="POST",
|
||||
url=url,
|
||||
data=data,
|
||||
proxies=proxies,
|
||||
**kwargs)
|
||||
if response.status_code == 200:
|
||||
return response.content
|
||||
method = "get"
|
||||
self.resetHeaders()
|
||||
if is_logger:
|
||||
logger.log(
|
||||
u"url: {0}\n入参: {1}\n请求方式: {2}\n".format(urls["req_url"],data,method,))
|
||||
self.setHeadersHost(urls["Host"])
|
||||
if self.cdn:
|
||||
url_host = self.cdn
|
||||
else:
|
||||
print("请求失败。{0}".format(response))
|
||||
url_host = urls["Host"]
|
||||
for i in range(urls["re_try"]):
|
||||
try:
|
||||
requests.packages.urllib3.disable_warnings()
|
||||
response = self._s.request(method=method,
|
||||
timeout=2,
|
||||
url="https://" + url_host + urls["req_url"],
|
||||
data=data,
|
||||
allow_redirects=allow_redirects,
|
||||
verify=False,
|
||||
**kwargs)
|
||||
if response.status_code == 200:
|
||||
if response.content:
|
||||
if is_logger:
|
||||
logger.log(
|
||||
u"出参:{0}".format(response.content))
|
||||
return json.loads(response.content) if method == "post" else response.content
|
||||
else:
|
||||
logger.log(
|
||||
u"url: {} 返回参数为空".format(urls["req_url"]))
|
||||
return error_data
|
||||
else:
|
||||
sleep(urls["re_time"])
|
||||
except (requests.exceptions.Timeout, requests.exceptions.ReadTimeout, requests.exceptions.ConnectionError):
|
||||
pass
|
||||
except socket.error:
|
||||
pass
|
||||
return error_data
|
||||
|
||||
@@ -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()
|
||||
BIN
tkcode
BIN
tkcode
Binary file not shown.
|
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 14 KiB |
0
tmp/__init__.py
Normal file
0
tmp/__init__.py
Normal file
0
tmp/log/__init__.py
Normal file
0
tmp/log/__init__.py
Normal file
Reference in New Issue
Block a user