58 Commits
python3 ... dev

Author SHA1 Message Date
wenxianping
bd1a0fcaa3 1、增加cdn轮训功能
2、兼容Windows cmd命令乱码问题
3、规范接口提交参数
4、修改已知bug
2018-01-29 21:59:01 +08:00
wenxianping
004b82831d cdn 2018-01-29 11:19:25 +08:00
wenxianping
f0fea7cba7 margen 2018-01-28 14:27:24 +08:00
wenxianping
b1ab036026 加速需要验证码订票的速度 2018-01-25 21:36:18 +08:00
wenxianping
c1ce4e4469 test version 2018-01-25 14:15:47 +08:00
wenxianping
b056211587 Merge branch 'master' into dev 2018-01-24 22:50:22 +08:00
wenxianping
01d54be85a fix 2018-01-24 22:35:24 +08:00
wenxianping
632a971606 fix 2018-01-24 12:57:43 +08:00
wenxianping
133606f170 增加日志 2018-01-24 12:56:18 +08:00
wenxianping
0b3d04ace4 1、增加若快打码
2、优化提示语
3、修改若干bug
2018-01-24 10:06:25 +08:00
wenxianping
829ec1163e 修改请求超时问题
修改检查登录心跳方式
2018-01-23 21:29:06 +08:00
wenxianping
7d40223973 fix 2018-01-23 17:58:17 +08:00
wenxianping
34456df151 先发一beta版本 解决返回为空的问题 2018-01-23 17:48:09 +08:00
wenxianping
d214892525 1、修改乘车人如果未设置好,返回默认值有误
2、优化登录回调,设置为五分钟一次
3、修改type为null的问题
4、增加请求超时
2018-01-23 12:59:47 +08:00
wenxianping
b36595aead 1、修改登录接口逻辑,暂定办法
2、修改邮箱554 bug
2018-01-22 22:01:57 +08:00
wenxianping
b37aadfc93 yaml fix 2018-01-21 20:35:56 +08:00
wenxianping
235b0000c9 增加多日期查询,请严格按照yaml格式添加 即可
增加如果排队时间超过一分钟,自动取消订单
2018-01-21 13:47:38 +08:00
wenxianping
d7c5c7215c 实现 新版登录逻辑
优化 订票逻辑
2018-01-21 09:12:15 +08:00
wenxianping
1411824016 test version 2018-01-20 23:31:13 +08:00
wenxianping
0d4846e9ba margen 2018-01-20 23:27:24 +08:00
wenxianping
aa6d628c82 1、更新新版登录
2、优化代码
2018-01-20 23:23:51 +08:00
wenxianping
501fd388bd 增加捡漏自动检测用户登录功能
修改自动刷票的时间为早上6点
2018-01-15 23:30:15 +08:00
wenxianping
cd65eeb963 修改排队时间超长问题 2018-01-15 23:00:20 +08:00
wenxianping
a3ba39c757 修改排队时间很长的问题 2018-01-14 20:30:59 +08:00
wenxianping
44a41f9131 fix 2018-01-14 17:35:42 +08:00
wenxianping
35918e1dd8 fix 2018-01-14 17:34:59 +08:00
wenxianping
4c2b435407 fix 2018-01-14 15:33:02 +08:00
wenxianping
5f7b4df19b 邮箱设置升级 2018-01-14 15:27:07 +08:00
wenxianping
d1be6833bb 修改早上7点自动刷票功能 2018-01-14 14:07:06 +08:00
wenxianping
4cc4205d86 readme 2018-01-14 13:47:40 +08:00
wenxianping
46ecb662eb 验证码识别字段增加 2018-01-14 08:58:02 +08:00
wenxianping
f669690a70 优化订票速度 2018-01-13 23:13:00 +08:00
wenxianping
fb92dbaece 验证码识别字段增加
增加邮箱功能
2018-01-13 23:08:03 +08:00
wenxianping
ac1a03834e 验证码识别字段增加 2018-01-13 11:45:39 +08:00
wenxianping
a3f88212d0 捕获异常 2018-01-13 10:08:59 +08:00
wenxianping
1ce2f7719e fix 2018-01-13 09:53:36 +08:00
wenxianping
6ffdaa0048 master margin test 2018-01-13 09:45:41 +08:00
wenxianping
4febb67ac2 fix 2018-01-13 09:44:57 +08:00
wenxianping
9170177769 Merge branch 'test' 2018-01-13 09:39:33 +08:00
wenxianping
b84c5faf8f fix 2018-01-13 09:38:06 +08:00
wenxianping
91b0c471ee Merge branch 'dev' into test
# Conflicts:
#	.idea/workspace.xml
#	config/ticket_config.yaml
#	init/select_ticket_info.py
#	tkcode
2018-01-13 09:32:10 +08:00
wenxianping
a6983a0422 转义 2018-01-12 23:38:50 +08:00
wenxianping
2ed2916397 排队提交订单规范加强,依赖减弱
测试版本
2018-01-12 23:16:02 +08:00
wenxianping
507910d1dd Merge pull request #4 from hawkli-1994/hawkli-optimization
规范run文件的写法
2018-01-12 20:55:22 +08:00
hawkli
26ee65c48e 规范run文件的写法 2018-01-12 19:30:38 +08:00
wenxianping
339c22b5e2 fix 2018-01-11 21:49:10 +08:00
wenxianping
488fd01864 限制队列线程买票大小 2018-01-11 21:45:53 +08:00
wenxianping
66413c9acc fix 2018-01-11 21:44:02 +08:00
wenxianping
39b10e05c0 Merge remote-tracking branch 'origin/dev' into dev
# Conflicts:
#	init/select_ticket_info.py
2018-01-11 18:40:20 +08:00
79277490@qq.com
27d3c8f216 更改队列大小 2018-01-11 16:17:16 +08:00
79277490@qq.com
943ca94b9c Merge remote-tracking branch 'origin/master' 2018-01-11 16:11:06 +08:00
79277490@qq.com
9865021f81 . 2018-01-11 15:39:42 +08:00
79277490@qq.com
ebcd2a7997 命令测试 2018-01-11 15:34:15 +08:00
79277490@qq.com
4383d31878 队列循环提交 2018-01-11 15:26:12 +08:00
79277490@qq.com
f07b33d099 优化睡眠时间,队列循环提交 2018-01-11 15:23:50 +08:00
79277490@qq.com
dffc307b55 Merge remote-tracking branch 'origin/master' 2018-01-11 15:09:28 +08:00
wenxianping
e5b16fe778 test 2018-01-11 13:20:39 +08:00
79277490@qq.com
e5320663e8 增加配置 2018-01-11 12:43:25 +08:00
27 changed files with 3551 additions and 765 deletions

2
.gitignore vendored
View File

@@ -1,3 +1,5 @@
*.html
*.pyc
*.yaml
*.log
idea/

View File

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

View File

@@ -0,0 +1,3 @@
<component name="MarkdownNavigator.ProfileManager">
<settings default="" pdf-export="" />
</component>

781
.idea/workspace.xml generated

File diff suppressed because it is too large Load Diff

122
README.md
View File

@@ -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_type1=打码兔2=若快 若快注册地址http://www.ruokuai.com/client/index?6726
- 修改is_aotu_code字段为全部是否自动打码字段也就是说字段为rue则全部自动打码为False全部手动打码包括提交订单注意centOs不可设置手动打码
- 修复bug
- 优化抢票功能

611
agency/cdn_list Normal file
View 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
View 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
View 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
View 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
View 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
View 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)

View File

@@ -1,8 +1,8 @@
# -*- coding: utf8 -*-
__author__ = 'MR.wen'
import os
import yaml
import PyQt5
def _get_yaml():

View File

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

View File

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

View File

@@ -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.图片位置说明验证码图片中每个图片代表一个下标依次类推12345678
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.图片位置说明验证码图片中每个图片代表一个下标依次类推12345678
3.控制台输入对应下标,按照英文逗号分开,即可手动完成打码,
:return:
"""
print (u"下载验证码...")
codeimgUrl = code_url
img_path = './tkcode'
result = self.httpClint.send(codeimgUrl)
try:
print(u"下载验证码成功")
open(img_path, 'wb').write(result)
except OSError as e:
print (e)
def codexy(self, Ofset=None, is_raw_input=True):
"""
获取验证码
:return: str
"""
if is_raw_input:
Ofset = raw_input(u"请输入验证码: ")
select = Ofset.split(',')
post = []
offsetsX = 0 # 选择的答案的left值,通过浏览器点击8个小图的中点得到的,这样基本没问题
offsetsY = 0 # 选择的答案的top值
for ofset in select:
if ofset == '1':
offsetsY = 46
offsetsX = 42
elif ofset == '2':
offsetsY = 46
offsetsX = 105
elif ofset == '3':
offsetsY = 45
offsetsX = 184
elif ofset == '4':
offsetsY = 48
offsetsX = 256
elif ofset == '5':
offsetsY = 36
offsetsX = 117
elif ofset == '6':
offsetsY = 112
offsetsX = 115
elif ofset == '7':
offsetsY = 114
offsetsX = 181
elif ofset == '8':
offsetsY = 111
offsetsX = 252
else:
pass
post.append(offsetsX)
post.append(offsetsY)
randCode = str(post).replace(']', '').replace('[', '').replace("'", '').replace(' ', '')
print(u"验证码识别坐标为{0}".format(randCode))
return randCode
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()

View File

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

View File

@@ -0,0 +1,2 @@
class UserPasswordException(Exception):
pass

View File

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

View File

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

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 14 KiB

0
tmp/__init__.py Normal file
View File

0
tmp/log/__init__.py Normal file
View File