pull/5/head
zoeda 1 year ago
parent 6bc86a9fa5
commit ddc735f288

@ -1,15 +0,0 @@
**/*.html
**/*.pyc
**/*.yaml
**/*.log
**/*~
**/.DS_Store
**/Thumbs.db
*.png
.idea/
.git/
.github/
*.md
UnitTest/
uml/
*.h5

@ -1,6 +0,0 @@
*.html
*.pyc
*.yaml
*.log
.idea/
tkcode.png

Binary file not shown.

@ -1,24 +0,0 @@
FROM python:2.7.15
WORKDIR /usr/src/app
ADD . /usr/src/app
ENV DEBIAN_FRONTEND noninteractive
ENV TZ Asia/Shanghai
## install python requirements
RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyspider --no-cache-dir -r requirements.txt
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
## install ntpdate, not accept but saving code
#RUN echo 'deb http://mirrors.163.com/debian/ jessie main non-free contrib \
# deb http://mirrors.163.com/debian/ jessie-updates main non-free contrib \
# deb http://mirrors.163.com/debian-security/ jessie/updates main non-free contrib' > /etc/apt/sources.list \
# && apt-get update\
# && apt-get install ntpdate -y \
#EXPOSE 5010
CMD [ "python", "run.py" ]
#ENTRYPOINT [ "python", "run.py" ]

@ -1,51 +0,0 @@
FROM python:3.7-slim-buster
ARG CDV=77.0.3865.40
RUN sed -i 's/deb.debian.org/ftp.cn.debian.org/g' /etc/apt/sources.list
RUN apt-get -y update && apt-get install -y \
fonts-liberation \
libappindicator3-1 \
libasound2 \
libatk-bridge2.0-0 \
libatk1.0-0 \
libatspi2.0-0 \
libcups2 \
libdbus-1-3 \
libgtk-3-0 \
libnspr4 \
libnss3 \
libx11-xcb1 \
libxcomposite1 \
libxcursor1 \
libxdamage1 \
libxfixes3 \
libxi6 \
libxrandr2 \
libxss1 \
libxtst6 \
lsb-release \
unzip \
wget \
xdg-utils \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
ENV TZ Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
WORKDIR /usr/src/app
RUN wget -q https://dl.lancdn.com/landian/soft/chrome/m/77.0.3865.120_amd64.deb && \
dpkg -i 77.0.3865.120_amd64.deb && rm -f 77.0.3865.120_amd64.deb
RUN wget -q https://npm.taobao.org/mirrors/chromedriver/$CDV/chromedriver_linux64.zip && \
unzip chromedriver_linux64.zip && rm -f chromedriver_linux64.zip
## install python requirements
COPY requirements-docker37.txt ./
RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --no-cache-dir -r requirements-docker37.txt
COPY . .
CMD [ "sh", "-c", "python run.py c && python run.py r" ]

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2017
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -1,141 +0,0 @@
### 12306 购票小助手
#### python版本
- [ ] 2.7.10 - 2.7.15
- [x] 3.6 - 3.7.4
- [ ] 2.7.9
#### 已有功能
- [x] 自动打码
- [x] 自动登录
- [x] 准点预售和捡漏
- [x] 智能候补
- [x] 邮件通知
- [x] server酱通知
#### 依赖库
- 验证码目前可以本地识别,需要下载模型,放于项目根目录,全部代码来源于此项目 [传送门](https://github.com/zhaipro/easy12306),表示感谢
```
1. 模型下载链接:https://pan.baidu.com/s/1rS155VjweWVWIJogakechA 密码:bmlm
群里面也可以下载
2. git仓库下载https://github.com/testerSunshine/12306model.git
```
- 自托管云打码服务器搭建:[12306_code_server](https://github.com/YinAoXiong/12306_code_server)
- 如果大家有空闲的服务器,可搭建之后在这个 [issues](https://github.com/testerSunshine/12306/issues/446) 里面填入自己的服务器(请注意服务器安全!)
- 项目依赖 [requirements.txt](requirements.txt)
- 安装方法x:
- root用户(避免多python环境产生问题): `pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt`
- 非root用户避免安装和运行时使用了不同环境: `pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt`
- 许多windows的用户装不了tensorflow的话可以适当降低版本或者升高版本都是可以的
```
1. tensorflow的兼容版本 1.14.0rc\1.14.0rc\1.15.0\1.15.0rc
以上版本都测试无问题
2. 如果pip代理的清华源无法下载可以更换其他源解决此问题
```
#### 项目使用说明
- 服务器启动:
- 修改[配置](TickerConfig.py)文件
- 可以配置邮箱,配置邮箱的格式在[配置](TickerConfig.py)里面可以看到ex
```
# 测试邮箱和server酱是否可用 server酱测试的前提是server酱开关开启
# 可以配置server酱提醒推荐[配置教程](https://www.jianshu.com/p/8d10b5b9c4e3)
# 用python3 还是python 完全取决于安装的时候配置的环境变量是否为python3,以下启动默认环境变量为python3
python3 run.py t
```
- 配置[配置](TickerConfig.py)文件的时候需注意空格和遵循python语法格式
- 启动前请先筛选cdn这点很`重要`
```
python3 run.py c
```
- 启动服务
```
python3 run.py r
```
- 如果你不知道如何操作,下面的命令可能会帮助你
```
python3 run.py -h
——————————————————————————
sage: run.py [-h] operate
positional arguments:
operate r: 运行抢票程序, c: 过滤cdn, t: 测试邮箱和server酱server酱
```
- 如果你的服务器安装了docker与docker-compose, 那么你可以忽略上面的**所有**步骤,直接按以下步骤操作,即可开始抢票:
- 前提条件:
- 请确认你安装的docker版本为18.09及以上: `docker -v`
- 请确认你安装的docker-compose版本为1.23.2及以上: `docker-compose -v`
- 请根据自己需要修改好配置文件:`TickerConfig.py`
- 请修改配置文件`TickerConfig.py`中的变量`AUTO_CODE_TYPE`和`HOST``AUTO_CODE_TYPE`改为`3`, HOST改为`"captcha:80"`(这里很重要,这是本地打码服务器的配置)
- 运行命令:
- 开始抢票:`docker-compose up --build -d`
- 停止抢票:`docker-compose down`
- 查看抢票log: `docker logs --follow ticket`
#### 目录对应说明
- agency - cdn代理
- config - 项目配置
- verify - 自动打码
- init - 项目主运行目录
- inter - 接口
- myException - 异常
- myUrllib request网络请求库
#### 思路图
- ![image](uml/uml.png)
#### 项目声明:
- 本软件只供学习交流使用,勿作为商业用途,交流群号
- 1群286271084(已满)
- 2群649992274(已满)
- 3群632501142(已满)
- 4群: 606340519(已满)
- 5群: 948526733(已满)
- 7群: 660689659(已满)
- 8群: 620629239(已满)
- 6群: 608792930(未满)
- 9群: 693035807(未满)
- 请不要重复加群,一个群就可以了,把机会留给更多人
- **进群先看公告!!!进群先看公告!!!进群先看公告!!! 重要的事情说三遍**
- 能为你抢到一张回家的票,是我最大的心愿
#### 日志列子
- 成功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分钟内完成支付
```
#### 使用帮助(一些安装问题和使用反馈较多的问题)
- 测试邮箱是否可用 [邮箱配置问题看issues](https://github.com/testerSunshine/12306/issues/107)
- 学生票issues [学生票修改](https://github.com/testerSunshine/12306/issues/47)
- 依赖安装不对的问题ImportError[requirements.txt问题](https://github.com/testerSunshine/12306/issues/91)
- 若快豆子疑问 [点我](https://github.com/testerSunshine/12306/issues/67)
- IOError: 【Errno 0】 Error 问题 [点我](https://github.com/testerSunshine/12306/issues/159)
- 测试下单接口是否可用有两个下单接口随便用哪个都ok
- 如果下载验证码过期或者下载失败的问题应该是12306封ip的策略多重试几次12306现在封服务器(阿里云和腾讯云)ip比较严重尽量不要放在服务器里面
- 目前12306对服务器ip比较敏感大家还是在自己家里挂着吧
- 自动更换ip软件目前已支持TPLINK和小米路由器只限家庭网络[点我跳转](https://github.com/testerSunshine/AutoRouterIP)
#### 感谢一下小伙伴对本项目提供的帮助
- @sun7127@126.com
- @ 才
- @[MonsterTan](https://github.com/MonsterTan)
- 以及所有为此项目提供pr的同学
#### 更新日志
- [更新日志](Update.md)

@ -1,157 +0,0 @@
# -*- coding=utf-8 -*-
# 关于软件使用配置说明,一定要看!!!
# ps: 如果是候补车票需要通过人证一致性核验的用户及激活的“铁路畅行”会员可以提交候补需求请您按照操作说明在铁路12306app.上完成人证核验
# 关于候补了之后是否还能继续捡漏的问题在此说明: 软件为全自动候补加捡漏,如果软件候补成功则会停止抢票,发出邮件通知,但是不会影响你继续捡漏,
# 如果这个时候捡漏捡到的话,也是可以付款成功的,也就是说,捡漏+候补,可以最大程度提升抢票成功率
# 刷票模式1=刷票 2=候补+刷票
TICKET_TYPE = 1
# 出发日期(list) "2018-01-06", "2018-01-07"
STATION_DATES = [
"2020-01-18"
]
# 填入需要购买的车次(list)"G1353"
# 修改车次填入规则,注:(以前设置的车次逻辑不变),如果车次填入为空,那么就是当日乘车所有车次都纳入筛选返回
# 不填车次是整个list为空才算如果不是为空依然会判断车次的这种是错误的写法 [""], 正确的写法 []
STATION_TRAINS = []
# 出发城市,比如深圳北,就填深圳就搜得到
FROM_STATION = "广州南"
# 到达城市 比如深圳北,就填深圳就搜得到
TO_STATION = "隆回"
# 座位(list) 多个座位ex:
# "商务座",
# "一等座",
# "二等座",
# "特等座",
# "软卧",
# "硬卧",
# "硬座",
# "无座",
# "动卧",
SET_TYPE = ["二等座"]
# 当余票小于乘车人,如果选择优先提交,则删减联系人和余票数一致在提交
# bool
IS_MORE_TICKET = True
# 乘车人(list) 多个乘车人ex:
# "张三",
# "李四"
TICKET_PEOPLES = []
# 12306登录账号
USER = ""
PWD = ""
# 加入小黑屋时间默认为5分钟此功能为了防止僵尸票导致一直下单不成功错过正常的票
TICKET_BLACK_LIST_TIME = 5
# 自动打码
IS_AUTO_CODE = True
# 设置2本地自动打码需要配置tensorflow和keras库3为云打码由于云打码服务器资源有限(为2h4C的cpu服务器),请不要恶意请求,不然只能关闭服务器
# ps: 请不要一直依赖云服务器资源,在此向所有提供服务器同学表示感谢
AUTO_CODE_TYPE = 3
# 此处设置云打码服务器地址,如果有自建的服务器,可以自行更改
HOST = "120.77.154.140:8000"
REQ_URL = "/verify/base64/"
HTTP_TYPE = "http"
# HOST="12306.yinaoxiong.cn" #备用服务器稳定性较差
# REQ_URL="/verify/base64/"
# HTTP_TYPE="https"
# 邮箱配置,如果抢票成功,将通过邮件配置通知给您
# 列举163
# email: "xxx@163.com"
# notice_email_list: "123@qq.com"
# username: "xxxxx"
# password: "xxxxx
# host: "smtp.163.com"
# 列举qq qq设置比较复杂需要在邮箱-->账户-->开启smtp服务取得授权码==邮箱登录密码
# email: "xxx@qq.com"
# notice_email_list: "123@qq.com"
# username: "xxxxx"
# password: "授权码"
# host: "smtp.qq.com"
EMAIL_CONF = {
"IS_MAIL": True,
"email": "",
"notice_email_list": "",
"username": "",
"password": "",
"host": "smtp.qq.com",
}
# 是否开启 server酱 微信提醒, 使用前需要前往 http://sc.ftqq.com/3.version 扫码绑定获取 SECRET 并关注获得抢票结果通知的公众号
SERVER_CHAN_CONF = {
"is_server_chan": False,
"secret": ""
}
# 是否开启cdn查询可以更快的检测票票 1为开启2为关闭
IS_CDN = 1
# 下单接口分为两种1 模拟网页自动捡漏下单不稳定2 模拟车次后面的购票按钮下单(稳如老狗)
ORDER_TYPE = 2
# 下单模式 1 为预售整点刷新刷新间隔0.1-0.5S, 然后会校验时间比如12点的预售那脚本就会在12.00整检票,刷新订单
# 2 是捡漏捡漏的刷新间隔时间为0.5-3秒时间间隔长不容易封ip
ORDER_MODEL = 1
# 是否开启代理, 0代表关闭 1表示开始
# 开启此功能的时候请确保代理ip是否可用在测试放里面经过充分的测试再开启此功能不然可能会耽误你购票的宝贵时间
# 使用方法:
# 1、在agency/proxy_list列表下填入代理ip
# 2、测试UnitTest/TestAll/testProxy 测试代理是否可以用
# 3、开启代理ip
IS_PROXY = 0
# 预售放票时间, 如果是捡漏模式,可以忽略此操作
OPEN_TIME = "12:59:57"
# 1=使用selenium获取devicesID
# 2=使用网页端/otn/HttpZF/logdevice获取devicesId这个接口的算法目前可能有点问题如果登录一直302的请改为配置1
# 3=自己打开浏览器在headers-Cookies中抓取RAIL_DEVICEID和RAIL_EXPIRATION这个就不用配置selenium
COOKIE_TYPE = 3
# 如果COOKIE_TYPE=1则需配置chromeDriver路径,下载地址http://chromedriver.storage.googleapis.com/index.html
# chromedriver配置版本只要和chrome的大版本匹配就行
CHROME_PATH = "/usr/src/app/chromedriver"
# 为了docker37 准备的环境变量windows环境可以不用管这个参数
CHROME_CHROME_PATH = "/opt/google/chrome/google-chrome"
# 如果COOKIE_TYPE=3, 则需配置RAIL_EXPIRATION、RAIL_DEVICEID的值
RAIL_EXPIRATION = ""
RAIL_DEVICEID = ""
# RAIL_EXPIRATION = "1577034103293"
# RAIL_DEVICEID = "CDno29Erc_Pf3FSXb4dzq-Op64EhWrsi5yUZKVIKR1MAfYo2qFlCeXD8VkexY7_1qg-ClV-fE8j9jgVlPZxRh3wVc2iqLe_5A8sdr62qZx4B22JPF8lFCjpgTKZ5ODW90HJd5tiQsJ1KR9nOqHRxHj1FT5LEIwfw"
# 1=>为一直随机ua,2->只启动的时候随机一次ua
RANDOM_AGENT = 2
PASSENGER_TICKER_STR = {
'一等座': 'M',
'特等座': 'P',
'二等座': 'O',
'商务座': 9,
'硬座': 1,
'无座': 1,
'软座': 2,
'软卧': 4,
'硬卧': 3,
}
# 保护12306官网请求频率设置随机请求时间原则为5分钟不大于80次
# 最大间隔请求时间
MAX_TIME = 3
# 最小间隔请求时间
MIN_TIME = 1
# 软件版本
RE_VERSION = "1.2.004"

File diff suppressed because one or more lines are too long

@ -1,191 +0,0 @@
- 2017.5.13跟新
- 增加登陆错误判断(密码错误&ip校验
- 修改queryOrderWaitTime校验orderId字段bug校验msg字段bug校验messagesbug
- 修改checkQueueOrder 校验 data 字段的列表推导式bug
- 增加代理ip方法目前已可以过滤有用ip
- 2018.1.7 号更新
- 增加自动配置
```
#station_date:出发日期格式ex2018-01-06
#from_station: 始发站
#to_station: 到达站
#set_type: 坐席(商务座,二等座,特等座,软卧,硬卧,硬座,无座)
#is_more_ticket:余票不足是否自动提交
#select_refresh_interval:刷新间隔时间1为一秒0.1为100毫秒以此类推
#ticke_peoples: 乘客
#damatu:打码图账号,用于自动登录
```
- 优化订票流程
- 支持自动刷票,自动订票
- 2018.1.8 更新
- 增加小黑屋功能
- 修复bug若干
- 增加多账号同时订票功能
- 增加按照选定车次筛选购买车次
- 2018.1.9 更新
- 增加手动打码只是登录接口完全不用担心提交票的效率问题要挂linux系统的话还是去注册个打码兔吧
```
思路
1.调用PIL显示图片
2.图片位置说明验证码图片中每个图片代表一个下标依次类推12345678
3.控制台输入对应下标,按照英文逗号分开,即可手动完成打码,
```
- 修改无座和硬座的座位号提交是个字符串的问题
- 增加校验下单需要验证码功能
- 增强下单成功判断接口校验
- 2018.1.10 更新
- 优化查票流程
- 修改二等座的余票数返回为字符串的问题
- 优化订单查询bug
- 2018.1.12更新
- 优化抢票页面逻辑
-增强代码稳定性
- 2018.1.13更新
- 修改下单验证码功能
- 优化大量调用user接口导致联系人不能用理论加快订票速度
- 增加邮箱功能
```
#is_email: 是否需要邮件通知 ex: True or False 切记邮箱加完一定要到config目录下测试emailConf功能是否正常
#email: 发送的邮箱地址 ex: 1@qq.com
#notice_email_list: 被通知人邮箱 ex: 2@qq.com
#username: 邮箱账号
#password: 邮箱密码
#host: 邮箱地址
```
- 2018.1.14更新
- 优化订票流程
- 优化挂机功能
- 修改之前程序到11点自动跳出功能现在修改为到早上7点自动开启刷票
- 需要开启打码兔代码功能is_auto_code 设置为True
- 增加异常判断
- 2018.1.15更新
- 增加捡漏自动检测是否登录功能建议捡漏不要刷新太快2S最好否则会封IP
- 优化提交订单有很大记录无限排队的情况,感谢群里的小伙伴提供的思路
- 修改休眠时间为早上6点
- 2018.1.20更新,好久没跟新了,群里的小伙伴说登录不行了,今晚抽空改了一版登录,妥妥的
- 更新新版登录功能,经测试,更稳定有高效
- 优化手动打码功能
- 更新请求第三方库
- 优化若干代码,小伙伴尽情的放肆起来
- 2018.1.21跟新
- 修复若干bug
- 合并dev
- 恢复之前因为12306改版引起的订票功能
- 增加派对失败自动取消订单功能
- 优化接口请求规范
- 增加多日期查询请严格按照yaml格式添加 即可
- 注意:如果多日期查询的话,可能查询时间会比较长
- 增加如果排队时间超过一分钟,自动取消订单
- 2018.1.23更新
- 增加若快平台打码yaml新增字段auto_code_type1=打码兔2=若快 若快注册地址http://www.ruokuai.com/client/index?6726
- 修改is_auto_code字段为全部是否自动打码字段也就是说字段为True则全部自动打码为False全部手动打码包括提交订单注意centOs不可设置手动打码
- 修复bug
- 优化抢票功能
- 2018.1.25更新
- 删除 expect_refresh_interval 无用字段,优化代码
- 2018.1.29更新
- 增加cdn轮训功能优势 is_cdn=1为开启cdn2为普通查询
- 能够一定程度躲避封ip
- 查询余票快人一步
- 提交订单快人一步
- 僵尸票可能会少很多
- 兼容Windows cmd命令乱码问题
- 规范12306接口提交参数
- 修改已知bug
- 最后感谢群里提供测试和代码的小伙伴,能为你们买到一张回家的票真的感到灰常开心
- 2018.2.28更新收12306风控影响代码可能有时候会进入慢排队请自行调整刷新参数
- 修改已知bug
- 优化接口提交参数规范
- 2018.8.29更新,解决慢排队问题,增加双订票接口
- 修改已知bug
- 优化代码结构
- 新增第三方库wrapcache需要重新安装requirements.txt
- 2018.9.21更新,修复已知问题,增加余票不足优先提交功能
- 修改已知bug
- 优化查询攻略
- 优化随机查询1-3秒经测试很稳定不会封ip
- 增加余票不足优先提交功能(当余票小于乘车人,如果选择优先提交,则删减联系人和余票数一致在提交)
- 开关为ticket_config.yaml配置文件中is_more_ticket参数
- 2018.12.26更新
- 优化已知bug
- 开启cdn查询
- 自动识别查询接口
- 2019.01.09更新
- ticket_config 配置文件增加order_model字段下单模式
- mac和linux服务器自动对点
- 增加预售踩点查询下单经测试误差在0.004s
- 2019.01.12更新
- 增加对python3语法的支持
- 删除校验时间很多机器不兼容的问题win10会阻拦对时功能导致大面积报错如果是预售为了不耽误宝贵的时间请手动对时
- 2019.01.15更新
- 删除敏感信息打印
- 增加server酱推送购票成功通知
- 修改11点都登录消耗快豆问题
- 增加gui界面
- 2019.04.01更新
- 增加登录接口解决无法03.31登录
- 2019.04.23更新
- 修复登录302问题如果下次没来得及更新请自行抓包修改urlConf中getDevicesId接口即可登录
- 2019.04.23更新
- 更新本地识别
- 2019.08.31更新
- 删除若快打码
- 修复不能下单问题
- 放弃支持python2.7,只支持3.6以上版本
- 2019.09.01更新
- 去除yaml配置文件改为py文件配置
- 增加候补订单功能
- 新增TICKET_TYPE字段1=刷票 2=候补
- 目前候补只支持单车次,多乘车人候补,由于目前不是很懂候补的需求,所以暂时这样做
- 2019.09.02更新
- 剔除新增TICKET_TYPE字段发现此字段冗余目前改为全天自动候补+捡漏
- 增加候补订单功能
- 优先级:下单再候补
- 2019.09.03更新
- 恢复TICKET_TYPE字段1=刷票 2=候补+刷票
- 优化候补逻辑
- 候补订单只能在规定车次内候补
- 2019.09.07更新
- 优化候补逻辑
- 去除敏感信息打印
- 2019.09.09更新
- 优化候补逻辑
- 2019.09.15更新
- 增长随机停留时长
- 增长用户心跳时间,减少对服务器压力
- 优化下单逻辑
- 2019.09.18更新
- 修改下单问题
- 优化车次打印

@ -1,107 +0,0 @@
# encoding=utf8
import os
import random
import socket
import time
import requests
from bs4 import BeautifulSoup
class proxy:
def __init__(self):
self.proxy_list = []
self.proxy_filter_list = []
def get_proxy(self):
"""
获取未加工代理列表
:return:
"""
User_Agent = 'Mozilla/5.0 (Windows NT 6.3; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0'
header = dict()
header['User-Agent'] = User_Agent
for i in range(1, 5):
time.sleep(1)
url = 'http://www.xicidaili.com/nn/' + str(i)
res = requests.get(url=url, headers=header).content
soup = BeautifulSoup(res, "html.parser")
ips = soup.findAll('tr')
for x in range(1, len(ips)):
ip = ips[x]
tds = ip.findAll("td")
ip_temp = tds[1].contents[0] + ":" + tds[2].contents[0]
print(ip_temp)
self.proxy_list.append(ip_temp)
def filter_proxy(self):
"""
将不可用IP剔除
:return:
"""
socket.setdefaulttimeout(1)
path = os.path.join(os.path.dirname(__file__), './proxy_list')
f = open(path, "w")
head = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36',
'Connection': 'keep-alive'}
url = "http://icanhazip.com"
proxy_num = 0
for proxy in self.proxy_list:
proxy_temp = {"https": "https://{}".format(proxy)}
try:
req = requests.get(url, proxies=proxy_temp, timeout=2, headers=head).content
print(req)
write_proxy = proxy + "\n"
f.write(write_proxy)
proxy_num += 1
except Exception:
print ("代理链接超时去除此IP{0}".format(proxy))
continue
print("总共可使用ip量为{}".format(proxy_num))
def get_filter_proxy(self):
"""
读取该可用ip文件
:return: 可用ip文件list
"""
path = os.path.join(os.path.dirname(__file__), './proxy_list')
try:
with open(path, "r", encoding="utf-8") as f:
lins = f.readlines()
for i in lins:
p = i.strip("\n")
self.proxy_filter_list.append(p)
except Exception:
with open(path, "r", ) as f:
lins = f.readlines()
for i in lins:
p = i.strip("\n")
self.proxy_filter_list.append(p)
return self.proxy_filter_list
def main(self):
# self.get_proxy()
self.filter_proxy()
def setProxy(self):
"""
开启此功能的时候请确保代理ip是否可用
查询的时候设置代理ip,ip设置格式是ip地址+端口推荐可用的ip代理池https://github.com/jhao104/proxy_pool
:return:
"""
ip = self.get_filter_proxy()
setIp = ip[random.randint(0, len(ip) - 1)]
proxie = {
'http': 'http://{}'.format(setIp),
'https': 'http://{}'.format(setIp),
}
return proxie
if __name__ == "__main__":
a = proxy()
print(a.get_filter_proxy())

@ -1,101 +0,0 @@
# encoding=utf8
import datetime
import operator
import os
import requests
from config import urlConf
import threading
from config.urlConf import urls
from myUrllib.httpUtils import HTTPClient
cdn_list = []
class CDNProxy(threading.Thread):
def __init__(self, cdns):
super().__init__()
self.cdns = cdns
self.urlConf = urlConf.urls
self.httpClint = requests
self.city_list = []
self.timeout = 5
def run(self):
for cdn in self.cdns:
http = HTTPClient(0)
url = urls["loginInitCdn"]
http._cdn = cdn.replace("\n", "")
start_time = datetime.datetime.now()
rep = http.send(url)
retTime = (datetime.datetime.now() - start_time).microseconds / 1000
if rep and "message" not in rep and retTime < 3000:
if cdn.replace("\n", "") not in cdn_list: # 如果有重复的cdn则放弃加入
print(f"加入cdn: {cdn}")
cdn_list.append({"ip": cdn.replace("\n", ""), "time": retTime})
def open_cdn_file(cdnFile):
cdn = []
path = os.path.join(os.path.dirname(__file__), f'../{cdnFile}')
try:
with open(path, "r", encoding="utf-8") as f:
for i in f.readlines():
if i and "kyfw.12306.cn:443" not in i:
cdn.append(i.replace("\n", ""))
return cdn
except Exception:
with open(path, "r") as f:
for i in f.readlines():
if i and "kyfw.12306.cn:443" not in i:
cdn.append(i.replace("\n", ""))
return cdn
def sortCdn():
"""
对cdn进行排序
:return:
"""
ips = []
cs = sorted(cdn_list, key=operator.itemgetter('time'))
for c in cs:
print(f"当前ip: {c['ip']}, 延时: {c['time']}")
ips.append(c["ip"])
return ips
def filterCdn():
"""
过滤cdn, 过滤逻辑为当前cdn响应值小于1000毫秒
过滤日志:
加入cdn: 116.77.75.146
:return:
"""
cdns = open_cdn_file("cdn_list")
cdnss = [cdns[i:i + 50] for i in range(0, len(cdns), 50)]
cdnThread = []
for cdn in cdnss:
t = CDNProxy(cdn)
cdnThread.append(t)
for cdn_t in cdnThread:
cdn_t.start()
for cdn_j in cdnThread:
cdn_j.join()
print(f"当前有效cdn个数为: {len(cdn_list)}")
if cdn_list:
ips = sortCdn()
path = os.path.join(os.path.dirname(__file__), f'../filter_cdn_list')
f = open(path, "a+")
f.seek(0)
f.truncate()
f.writelines("")
for ip in ips:
f.writelines(f"{ip}\n")
f.close()
if __name__ == '__main__':
filterCdn()

@ -1 +0,0 @@
119.101.114.196:9999

File diff suppressed because it is too large Load Diff

@ -1,39 +0,0 @@
# coding=utf-8
import os
import platform
import ntplib
import datetime
def autoSynchroTime():
"""
同步北京时间执行时候请务必用sudosudosudo 执行否则会报权限错误windows打开ide或者cmd请用管理员身份
:return:
"""
c = ntplib.NTPClient()
hosts = ['ntp1.aliyun.com', 'ntp2.aliyun.com', 'ntp3.aliyun.com', 'ntp4.aliyun.com', 'cn.pool.ntp.org']
print(u"正在同步时间请耐心等待30秒左右如果下面有错误发送可以忽略")
print(u"系统当前时间{}".format(str(datetime.datetime.now())[:22]))
system = platform.system()
if system == "Windows": # windows 同步时间未测试过参考地址https://www.jianshu.com/p/92ec15da6cc3
for host in hosts:
os.popen('w32tm /register')
os.popen('net start w32time')
os.popen('w32tm /config /manualpeerlist:"{}" /syncfromflags:manual /reliable:yes /update'.format(host))
os.popen('ping -n 3 127.0.0.1 >nul')
sin = os.popen('w32tm /resync')
if sin is 0:
break
else: # mac同步地址如果ntpdate未安装brew install ntpdate linux 安装 yum install -y ntpdate
for host in hosts:
sin = os.popen('ntpdate {}'.format(host))
if sin is 0:
break
print(u"同步后时间:{}".format(str(datetime.datetime.now())[:22]))
if __name__ == '__main__':
autoSynchroTime()

@ -1,41 +0,0 @@
# coding=utf-8
from enum import Enum
class ticket(object):
QUERY_C = u"查询到有余票,尝试提交订单"
QUERY_IN_BLACK_LIST = u"该车次{} 正在被关小黑屋,跳过此车次"
SUCCESS_CODE = 000000
FAIL_CODE = 999999
AUTO_SUBMIT_ORDER_REQUEST_C = u"提交订单成功"
AUTO_SUBMIT_ORDER_REQUEST_F = u"提交订单失败,重新刷票中"
AUTO_SUBMIT_NEED_CODE = u"需要验证码"
AUTO_SUBMIT_NOT_NEED_CODE = u"不需要验证码"
TICKET_BLACK_LIST_TIME = 5 # 加入小黑屋的等待时间默认5 min
DTO_NOT_FOUND = u"未查找到常用联系人, 请查证后添加!!"
DTO_NOT_IN_LIST = u"联系人不在列表中,请查证后添加!!"
QUEUE_TICKET_SHORT = u"当前余票数小于乘车人数,放弃订票"
QUEUE_TICKET_SUCCESS = u"排队成功, 当前余票还剩余: {0}"
QUEUE_JOIN_BLACK = u"排队发现未知错误{0},将此列车 {1}加入小黑屋"
QUEUE_WARNING_MSG = u"排队异常,错误信息:{0}, 将此列车 {1}加入小黑屋"
OUT_NUM = 120 # 排队请求12306的次数
WAIT_OUT_NUM = u"超出排队时间,自动放弃,正在重新刷票"
WAIT_ORDER_SUCCESS = u"恭喜您订票成功,订单号为:{0}, 请立即打开浏览器登录12306访问未完成订单在30分钟内完成支付!"
WAIT_AFTER_NATE_SUCCESS = u"候补订单已完成请立即打开浏览器登录12306访问候补订单在30分钟内完成支付!"
WAIT_ORDER_CONTINUE = u"排队等待时间预计还剩 {0} ms"
WAIT_ORDER_FAIL = u"排队等待失败,错误消息:{0}"
WAIT_ORDER_NUM = u"{0}次排队中,请耐心等待"
WAIT_ORDER_SUB_FAIL = u"订单提交失败!,正在重新刷票"
CANCEL_ORDER_SUCCESS = u"排队超时,已为您自动取消订单,订单编号: {0}"
CANCEL_ORDER_FAIL = u"排队超时,取消订单失败, 订单号{0}"
REST_TIME = u"12306休息时间本程序自动停止,明天早上6点将自动运行"
REST_TIME_PAST = u"休息时间已过,重新开启检票功能"
LOGIN_SESSION_FAIL = u"用户检查失败:{0}可能未登录可能session已经失效, 正在重新登录中"

@ -1,135 +0,0 @@
# -*- coding: utf-8 -*-
import datetime
import os
import random
import sys
import time
from myException.ticketConfigException import ticketConfigException
rushRefreshMinTimeIntval = 2000
rushRefreshMaxTimeIntval = 3600000
rushRefreshTimeIntval = 100
# 最早运行时间
maxRunTime = 6
# 程序停止时间
maxRunStopTime = 23
# 可售天数
maxDate = 29
RS_SUC = 0
RS_TIMEOUT = 1
RS_JSON_ERROR = 2
RS_OTHER_ERROR = 3
seat_conf = {'商务座': 32,
'一等座': 31,
'二等座': 30,
'特等座': 25,
'软卧': 23,
'硬卧': 28,
'软座': 24,
'硬座': 29,
'无座': 26,
'动卧': 33,
}
if sys.version_info.major == 2:
seat_conf_2 = dict([(v, k) for (k, v) in seat_conf.iteritems()])
else:
seat_conf_2 = dict([(v, k) for (k, v) in seat_conf.items()])
def getNowTimestamp():
return time.time()
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__)))
#
# def fileOpen(path):
# """
# 文件读取兼容2和3
# :param path: 文件读取路径
# :return:
# """
# try:
# with open(path, "r", ) as f:
# return f
# except TypeError:
# with open(path, "r", ) as f:
# return f
@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")
def checkSleepTime(session):
now = datetime.datetime.now()
if now.hour >= maxRunStopTime or now.hour < maxRunTime:
print(u"12306休息时间本程序自动停止,明天早上六点将自动运行")
open_time = datetime.datetime(now.year, now.month, now.day, maxRunTime)
if open_time < now:
open_time += datetime.timedelta(1)
time.sleep((open_time - now).seconds + round(random.uniform(1, 10)))
session.call_login()
def checkDate(station_dates):
"""
检查日期是否合法
:param station_dates:
:return:
"""
today = datetime.datetime.now()
maxDay = (today + datetime.timedelta(maxDate)).strftime("%Y-%m-%d")
for station_date in station_dates[::-1]:
date = datetime.datetime.strftime(datetime.datetime.strptime(station_date, "%Y-%m-%d"), "%Y-%m-%d")
if date < today.strftime("%Y-%m-%d") or date > maxDay:
print(u"警告:当前时间配置有小于当前时间或者大于最大时间: {}, 已自动忽略".format(station_date))
station_dates.remove(station_date)
if not station_dates:
print(u"当前日期设置无符合查询条件的,已被全部删除,请查证后添加!!!")
raise ticketConfigException(u"当前日期设置无符合查询条件的,已被全部删除,请查证后添加!!!")
else:
station_dates[station_dates.index(station_date)] = date
return station_dates

@ -1,47 +0,0 @@
# -*- coding: utf8 -*-
import socket
__author__ = 'MR.wen'
import TickerConfig
from email.header import Header
from email.mime.text import MIMEText
import smtplib
def sendEmail(msg):
"""
邮件通知
:param str: email content
:return:
"""
try:
if TickerConfig.EMAIL_CONF["IS_MAIL"]:
sender = TickerConfig.EMAIL_CONF["email"]
receiver = TickerConfig.EMAIL_CONF["notice_email_list"]
subject = '恭喜,您已订票成功'
username = TickerConfig.EMAIL_CONF["username"]
password = TickerConfig.EMAIL_CONF["password"]
host = TickerConfig.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
try:
smtp = smtplib.SMTP_SSL(host)
smtp.connect(host)
except socket.error:
smtp = smtplib.SMTP()
smtp.connect(host)
smtp.connect(host)
smtp.login(username, password)
smtp.sendmail(sender, receiver.split(","), msg.as_string())
smtp.quit()
print(u"邮件已通知, 请查收")
except Exception as e:
print(u"邮件配置有误{}".format(e))
if __name__ == '__main__':
sendEmail(1)

@ -1,195 +0,0 @@
import json
import random
import re
import time
import os
import TickerConfig
from config.urlConf import urls
def getDrvicesID(session):
"""
:return:
"""
print("cookie获取中")
if TickerConfig.COOKIE_TYPE is 1:
from selenium import webdriver
cookies = []
# 解决放镜像里 DevToolsActivePort file doesn't exist的问题
options = webdriver.ChromeOptions()
if os.name != 'nt' and TickerConfig.CHROME_CHROME_PATH:
options = webdriver.ChromeOptions()
options.binary_location = TickerConfig.CHROME_CHROME_PATH
options.add_argument(
'--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36')
options.add_argument("--no-sandbox")
options.add_argument("--headless")
driver = webdriver.Chrome(executable_path=TickerConfig.CHROME_PATH,chrome_options=options)
driver.get("https://www.12306.cn/index/index.html")
time.sleep(10)
for c in driver.get_cookies():
cookie = dict()
print()
if c.get("name") == "RAIL_DEVICEID" or c.get("name") == "RAIL_EXPIRATION":
cookie[c.get("name")] = c.get("value")
cookies.append(cookie)
print(f"获取cookie: {cookies}")
if cookies:
session.httpClint.set_cookies(cookies)
session.cookies = cookies
print("cookie获取完成")
elif TickerConfig.COOKIE_TYPE is 2:
request_device_id(session)
elif TickerConfig.COOKIE_TYPE is 3:
# RAIL_DEVICEID,RAIL_EXPIRATION的值打开12306官网可以获取headers-Cookies
if not TickerConfig.RAIL_DEVICEID or not TickerConfig.RAIL_EXPIRATION:
print("警告!!: RAIL_DEVICEID,RAIL_EXPIRATION的值为空请手动打开12306官网可以获取headers-Cookies中的RAIL_DEVICEID,RAIL_EXPIRATION填入配置文件中")
cookies = [{
"RAIL_DEVICEID": TickerConfig.RAIL_DEVICEID,
"RAIL_EXPIRATION": TickerConfig.RAIL_EXPIRATION,
}]
session.httpClint.set_cookies(cookies)
session.cookies = cookies
def request_device_id(session):
"""
获取加密后的浏览器特征 ID
:return:
"""
params = {"algID": request_alg_id(session), "timestamp": int(time.time() * 1000)}
params = dict(params, **_get_hash_code_params())
response = session.httpClint.send(urls.get("getDevicesId"), params=params)
if response.find('callbackFunction') >= 0:
result = response[18:-2]
try:
result = json.loads(result)
session.httpClint.set_cookies([{
'RAIL_EXPIRATION': result.get('exp'),
'RAIL_DEVICEID': result.get('dfp'),
}])
session.cookies = [{
'RAIL_EXPIRATION': result.get('exp'),
'RAIL_DEVICEID': result.get('dfp'),
}]
except:
return False
def request_alg_id(session):
response = session.httpClint.send(urls.get("GetJS"))
result = re.search(r'algID\\x3d(.*?)\\x26', response)
try:
return result.group(1)
except (IndexError, AttributeError) as e:
pass
return ""
def _get_hash_code_params():
from collections import OrderedDict
data = {
'adblock': '0',
'browserLanguage': 'en-US',
'cookieEnabled': '1',
'custID': '133',
'doNotTrack': 'unknown',
'flashVersion': '0',
'javaEnabled': '0',
'jsFonts': 'c227b88b01f5c513710d4b9f16a5ce52',
'localCode': '3232236206',
'mimeTypes': '52d67b2a5aa5e031084733d5006cc664',
'os': 'MacIntel',
'platform': 'WEB',
'plugins': 'd22ca0b81584fbea62237b14bd04c866',
'scrAvailSize': str(random.randint(500, 1000)) + 'x1920',
'srcScreenSize': '24xx1080x1920',
'storeDb': 'i1l1o1s1',
'timeZone': '-8',
'touchSupport': '99115dfb07133750ba677d055874de87',
'userAgent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.' + str(
random.randint(
5000, 7000)) + '.0 Safari/537.36',
'webSmartID': 'f4e3b7b14cc647e30a6267028ad54c56',
}
data_trans = {
'browserVersion': 'd435',
'touchSupport': 'wNLf',
'systemLanguage': 'e6OK',
'scrWidth': 'ssI5',
'openDatabase': 'V8vl',
'scrAvailSize': 'TeRS',
'hasLiedResolution': '3neK',
'hasLiedOs': 'ci5c',
'timeZone': 'q5aJ',
'userAgent': '0aew',
'userLanguage': 'hLzX',
'jsFonts': 'EOQP',
'scrAvailHeight': '88tV',
'browserName': '-UVA',
'cookieCode': 'VySQ',
'online': '9vyE',
'scrAvailWidth': 'E-lJ',
'flashVersion': 'dzuS',
'scrDeviceXDPI': '3jCe',
'srcScreenSize': 'tOHY',
'storeDb': 'Fvje',
'doNotTrack': 'VEek',
'mimeTypes': 'jp76',
'sessionStorage': 'HVia',
'cookieEnabled': 'VPIf',
'os': 'hAqN',
'hasLiedLanguages': 'j5po',
'hasLiedBrowser': '2xC5',
'webSmartID': 'E3gR',
'appcodeName': 'qT7b',
'javaEnabled': 'yD16',
'plugins': 'ks0Q',
'appMinorVersion': 'qBVW',
'cpuClass': 'Md7A',
'indexedDb': '3sw-',
'adblock': 'FMQw',
'localCode': 'lEnu',
'browserLanguage': 'q4f3',
'scrHeight': '5Jwy',
'localStorage': 'XM7l',
'historyList': 'kU5z',
'scrColorDepth': "qmyu"
}
data = OrderedDict(data)
d = ''
params = {}
for key, item in data.items():
d += key + item
key = data_trans[key] if key in data_trans else key
params[key] = item
d_len = len(d)
d_f = int(d_len / 3) if d_len % 3 == 0 else int(d_len / 3) + 1
if d_len >= 3:
d = d[d_f:2 * d_f] + d[2 * d_f:d_len] + d[0: d_f]
d_len = len(d)
d_f = int(d_len / 3) if d_len % 3 == 0 else int(d_len / 3) + 1
if d_len >= 3:
d = d[2 * d_f:d_len] + d[0: d_f] + d[1 * d_f: 2 * d_f]
d = _encode_data_str_v2(d)
d = _encode_data_str_v2(d)
d = _encode_data_str_v2(d)
data_str = _encode_string(d)
params['hashCode'] = data_str
return params
def _encode_data_str_v2(d):
b = len(d)
if b % 2 == 0:
return d[b // 2: b] + d[0:b // 2]
else:
return d[b // 2 + 1:b] + d[b // 2] + d[0:b // 2]
def _encode_string(str):
import hashlib
import base64
result = base64.b64encode(hashlib.sha256(str.encode()).digest()).decode()
return result.replace('+', '-').replace('/', '_').replace('=', '')

@ -1,61 +0,0 @@
#coding: utf-8
import os
import time
import logging
from config import configCommon
logger = None
loggerHandler = None
dateStr = '' #默认拥有日期后缀
suffix = '' #除了日期外的后缀
def setSuffix(s):
global suffix
suffix = s
def getTodayDateStr():
return time.strftime("%Y-%m-%d", time.localtime(configCommon.getNowTimestamp()))
def setDateStr(s):
global dateStr
dateStr = s
def isAnotherDay(s):
global dateStr
return dateStr != s
def getLogFile():
global dateStr, suffix
rtn = os.path.join(configCommon.getLogDir(), dateStr)
if suffix:
rtn += "_" + suffix
return rtn + ".log"
def log(msg, func = "info"):
global logger
if not logger:
logger = logging.getLogger()
logger.setLevel(logging.INFO)
todayStr = getTodayDateStr()
if isAnotherDay(todayStr):
setDateStr(todayStr)
logger.removeHandler(loggerHandler)
fh = logging.FileHandler(getLogFile())
fm = logging.Formatter(u'[%(asctime)s][%(levelname)8s] --- %(message)s (%(filename)s:%(lineno)s)')
fh.setFormatter(fm)
logger.addHandler(fh)
levels = {
"debug": logger.debug,
"info": logger.info,
"warning": logger.warning,
"error": logger.error,
"critical": logger.critical
}
levels[func](msg)

@ -1,36 +0,0 @@
# -*- coding: utf8 -*-
import TickerConfig
from config.urlConf import urls
from myUrllib.httpUtils import HTTPClient
PUSH_BEAR_API_PATH = "https://pushbear.ftqq.com/sub"
def sendPushBear(msg):
"""
pushBear微信通知
:param str: 通知内容 content
:return:
"""
if TickerConfig.PUSHBEAR_CONF["is_pushbear"] and TickerConfig.PUSHBEAR_CONF["send_key"].strip() != "":
try:
sendPushBearUrls = urls.get("Pushbear")
data = {
"sendkey": TickerConfig.PUSHBEAR_CONF["send_key"].strip(),
"text": "易行购票成功通知",
"desp": msg
}
httpClint = HTTPClient(0)
sendPushBeaRsp = httpClint.send(sendPushBearUrls, data=data)
if sendPushBeaRsp.get("code") is 0:
print(u"已下发 pushbear 微信通知, 请查收")
else:
print(sendPushBeaRsp)
except Exception as e:
print(u"pushbear 配置有误 {}".format(e))
else:
pass
if __name__ == '__main__':
sendPushBear(1)

@ -1,36 +0,0 @@
# -*- coding: utf8 -*-
import TickerConfig
from config.urlConf import urls
from myUrllib.httpUtils import HTTPClient
PUSH_SERVER_CHAN_PATH = "https://sc.ftqq.com"
def sendServerChan(msg):
"""
pushBear微信通知
:param str: 通知内容 content
:return:
"""
if (
TickerConfig.SERVER_CHAN_CONF["is_server_chan"]
and TickerConfig.SERVER_CHAN_CONF["secret"].strip() != ""
):
try:
secret = TickerConfig.SERVER_CHAN_CONF["secret"].strip()
sendServerChanUrls = urls.get("ServerChan")
sendServerChanUrls["req_url"] += f'{secret}.send'
params = {"text": "易行购票成功通知", "desp": msg}
httpClint = HTTPClient(0)
sendServerChanRsp = httpClint.send(sendServerChanUrls, params=params)
if sendServerChanRsp.get("errno") == 0:
print(u"已下发 Server酱 微信通知, 请查收")
else:
print(sendServerChanRsp)
except Exception as e:
print(u"Server酱 配置有误 {}".format(e))
if __name__ == "__main__":
sendServerChan(1)

@ -1,582 +0,0 @@
# coding=utf-8
import random
import TickerConfig
import time
urls = {
"auth": { # 登录接口
"req_url": "/passport/web/auth/uamtk",
"req_type": "post",
"Referer": "https://kyfw.12306.cn/otn/resources/login.html",
"Host": "kyfw.12306.cn",
"Content-Type": 1,
"re_try": 10,
"re_time": 1,
"s_time": 0.1,
"is_logger": True,
"is_json": True,
"is_cdn": True,
},
"uamtk-static": { # 登录接口
"req_url": "/passport/web/auth/uamtk-static",
"req_type": "get",
"Referer": "https://kyfw.12306.cn/otn/resources/login.html",
"Host": "kyfw.12306.cn",
"Content-Type": 1,
"re_try": 10,
"re_time": 3,
"s_time": 0.1,
"is_logger": True,
"is_json": True,
"is_cdn": True,
},
"login": { # 登录接口
"req_url": "/passport/web/login",
"req_type": "post",
"Referer": "https://kyfw.12306.cn/otn/resources/login.html",
"Host": "kyfw.12306.cn",
"Content-Type": 1,
"re_try": 10,
"re_time": 1,
"s_time": 0.5,
"is_logger": True,
"is_cdn": True,
"is_json": True,
},
"left_ticket_init": { # 登录接口
"req_url": "/otn/leftTicket/init",
"req_type": "post",
"Referer": "https://kyfw.12306.cn/otn/resources/login.html",
"Host": "kyfw.12306.cn",
"Content-Type": 1,
"re_try": 10,
"re_time": 1,
"s_time": 0.1,
"is_logger": False,
"is_cdn": True,
"is_json": False,
},
"getCodeImg": { # 登录验证码
"req_url": "/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand&{0}",
"req_type": "get",
"Referer": "https://kyfw.12306.cn/otn/resources/login.html",
"Host": "kyfw.12306.cn",
"Content-Type": 1,
"re_try": 10,
"re_time": 1,
"s_time": 0.1,
"is_logger": False,
"is_json": False,
"is_cdn": True,
"not_decode": True,
},
"getCodeImg1": { # 登录验证码
"req_url": "/passport/captcha/captcha-image64?login_site=E&module=login&rand=sjrand&{0}&callback=jQuery19108016482864806321_1554298927290&_=1554298927293",
"req_type": "get",
"Referer": "https://kyfw.12306.cn/otn/resources/login.html",
"Host": "kyfw.12306.cn",
"Content-Type": 1,
"re_try": 10,
"re_time": 1,
"s_time": 0.1,
"is_logger": True,
"is_cdn": True,
"is_json": False,
},
"codeCheck": { # 验证码校验
"req_url": "/passport/captcha/captcha-check",
"req_type": "post",
"Referer": "https://kyfw.12306.cn/otn/resources/login.html",
"Host": "kyfw.12306.cn",
"Content-Type": 1,
"re_try": 10,
"re_time": 1,
"s_time": 0.1,
"is_logger": True,
"is_cdn": True,
"is_json": False,
},
"codeCheck1": { # 验证码校验
"req_url": "/passport/captcha/captcha-check?callback=jQuery19108016482864806321_1554298927290&answer={0}&rand=sjrand&login_site=E&_={1}",
"req_type": "get",
"Referer": "https://kyfw.12306.cn/otn/resources/login.html",
"Host": "kyfw.12306.cn",
"Content-Type": 1,
"re_try": 10,
"re_time": 1,
"s_time": 0.1,
"is_cdn": True,
"is_logger": True,
"is_json": False,
},
"loginInit": { # 登录页面
"req_url": "/otn/login/init",
"req_type": "get",
"Referer": "https://kyfw.12306.cn/otn/index/init",
"Host": "kyfw.12306.cn",
"re_try": 1,
"re_time": 1,
"s_time": 0.1,
"is_logger": False,
"is_cdn": True,
"is_json": False,
},
"loginInitCdn": { # 登录页面
"req_url": "/otn/login/init",
"req_type": "get",
"Referer": "https://kyfw.12306.cn/otn/index/init",
"Host": "kyfw.12306.cn",
"re_try": 1,
"re_time": 1,
"s_time": 0.1,
"is_logger": False,
"is_test_cdn": True,
"is_cdn": True,
"is_json": False,
},
"loginInitCdn1": { # 登录页面
"req_url": "/otn/resources/login.html",
"req_type": "get",
"Referer": "https://kyfw.12306.cn/otn/view/index.html",
"Host": "kyfw.12306.cn",
"re_try": 1,
"re_time": 1,
"s_time": 0.1,
"is_logger": False,
"is_test_cdn": False,
"is_cdn": True,
"is_json": False,
},
"getDevicesId": { # 获取用户信息
"req_url": "/otn/HttpZF/logdevice",
"req_type": "get",
"Referer": "https://kyfw.12306.cn/otn/passport?redirect=/otn/",
"Host": "kyfw.12306.cn",
"re_try": 10,
"re_time": 1,
"s_time": 0.01,
"is_cdn": True,
"is_logger": True,
"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": 1,
"s_time": 0.01,
"is_cdn": True,
"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": 1,
"s_time": 0.1,
"is_logger": True,
"is_cdn": 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",
"Content-Type": 1,
"re_try": 10,
"re_time": 1,
"s_time": 0.1,
"is_cdn": True,
"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,
"s_time": 1,
"is_logger": False,
"is_cdn": True,
"is_json": False,
},
"GetJS": { # 订单页面js
"req_url": "/otn/HttpZF/GetJS",
"req_type": "get",
"Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc",
"Host": "kyfw.12306.cn",
"re_try": 10,
"re_time": 0.1,
"s_time": 0.1,
"is_logger": False,
"is_cdn": True,
"is_json": False,
},
"odxmfwg": { # 订单页面js
"req_url": "/otn/dynamicJs/odxmfwg",
"req_type": "get",
"Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc",
"Host": "kyfw.12306.cn",
"re_try": 10,
"re_time": 0.1,
"s_time": 0.1,
"is_logger": False,
"is_cdn": True,
"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,
"s_time": 0.1,
"is_cdn": True,
"is_logger": True,
"is_json": True,
},
"select_url": { # 查询余票
"req_url": "/otn/{3}?leftTicketDTO.train_date={0}&leftTicketDTO.from_station={1}&leftTicketDTO.to_station={2}&purpose_codes=ADULT",
"req_type": "get",
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
"Host": "kyfw.12306.cn",
"re_try": 1,
"re_time": 0.01,
"s_time": 0.01,
"is_logger": False,
"is_json": True,
"is_cdn": 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": 1,
"re_time": 1,
"s_time": 1,
"is_cdn": True,
"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.01,
"s_time": 0.1,
"is_cdn": True,
"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.01,
"s_time": 0.1,
"is_logger": True,
"is_cdn": 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.01,
"s_time": 0.1,
"is_logger": True,
"is_cdn": 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.01,
"s_time": 0.1,
"is_logger": True,
"is_cdn": 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.01,
"s_time": 0.1,
"is_cdn": True,
"is_logger": True,
"is_json": True,
},
"codeImgByOrder": { # 订单页面验证码
"req_url": "/otn/passcodeNew/getPassCodeNew?module=passenger&rand=randp&{}",
"req_type": "post",
"Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc",
"Host": "kyfw.12306.cn",
"re_try": 10,
"re_time": 0.01,
"s_time": 0.1,
"is_logger": False,
"is_cdn": True,
"is_json": False,
},
"queryOrderWaitTimeUrl": { # 订单等待页面
"req_url": "/otn/confirmPassenger/queryOrderWaitTime?random={0}&tourFlag=dc&_json_att=",
"req_type": "get",
"Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc",
"Host": "kyfw.12306.cn",
"re_try": 10,
"re_time": 0.01,
"s_time": 0.1,
"is_logger": True,
"is_cdn": 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.01,
"s_time": 0.1,
"is_logger": True,
"is_cdn": 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.01,
"s_time": 0.1,
"is_logger": False,
"is_cdn": True,
"is_json": False,
},
"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.01,
"s_time": 0.1,
"is_cdn": True,
"is_logger": True,
"is_json": True,
},
"autoSubmitOrderRequest": { # 快速自动提交订单
"req_url": "/otn/confirmPassenger/autoSubmitOrderRequest",
"req_type": "post",
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
"Host": "kyfw.12306.cn",
"Content-Type": 1,
"re_try": 10,
"re_time": 0.01,
"s_time": 0.1,
"is_logger": True,
"is_cdn": True,
"is_json": True,
},
"getQueueCountAsync": { # 快速获取订单数据
"req_url": "/otn/confirmPassenger/getQueueCountAsync",
"req_type": "post",
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
"Host": "kyfw.12306.cn",
"Content-Type": 1,
"re_try": 10,
"re_time": 0.01,
"s_time": 0.1,
"is_logger": True,
"is_cdn": True,
"is_json": True,
},
"confirmSingleForQueueAsys": { # 快速订单排队
"req_url": "/otn/confirmPassenger/confirmSingleForQueueAsys",
"req_type": "post",
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
"Content-Type": 1,
"Host": "kyfw.12306.cn",
"re_try": 10,
"re_time": 0.01,
"s_time": 0.1,
"is_logger": True,
"is_cdn": True,
"is_json": True,
},
"Pushbear": { # push通知
"req_url": "/sub",
"req_type": "post",
"Referer": "",
"Content-Type": 1,
"Host": "pushbear.ftqq.com",
"re_try": 10,
"re_time": 0.01,
"s_time": 0.1,
"is_logger": False,
"is_json": True,
},
"ServerChan": { # Server酱 push通知
"req_url": "/",
"req_type": "get",
"Referer": "",
"Content-Type": 1,
"Host": "sc.ftqq.com",
"re_try": 10,
"re_time": 0.01,
"s_time": 0.1,
"is_logger": True,
"is_json": True,
},
"loginHtml": { # 登录接口2
"req_url": "/otn/resources/login.html",
"req_type": "get",
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
"Host": "kyfw.12306.cn",
"re_try": 10,
"re_time": 0.3,
"s_time": 0.1,
"is_cdn": True,
"is_logger": True,
"is_json": True,
},
"loginConf": { # 登录接口2
"req_url": "/otn/login/conf",
"req_type": "post",
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
"Host": "kyfw.12306.cn",
"re_try": 10,
"re_time": 0.3,
"s_time": 0.1,
"is_cdn": True,
"is_logger": True,
"is_json": True,
},
"loginAysnSuggest": { # 登录接口2
"req_url": "/otn/login/loginAysnSuggest",
"req_type": "post",
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
"Host": "kyfw.12306.cn",
"re_try": 10,
"re_time": 0.3,
"is_cdn": True,
"s_time": 0.1,
"is_logger": True,
"is_json": True,
},
# 候补订单接口
"chechFace": { # 人脸识别
"req_url": "/otn/afterNate/chechFace",
"req_type": "post",
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
"Host": "kyfw.12306.cn",
"re_try": 10,
"re_time": 0.01,
"s_time": 0.01,
"is_cdn": True,
"is_logger": True,
"is_json": True,
},
"getSuccessRate": { # 成功信息
"req_url": "/otn/afterNate/getSuccessRate",
"req_type": "post",
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
"Host": "kyfw.12306.cn",
"re_try": 10,
"re_time": 0.01,
"s_time": 0.01,
"is_cdn": True,
"is_logger": True,
"is_json": True,
},
"SubmitOrderRequestRsp": { # 提交候补订单准备
"req_url": "/otn/afterNate/submitOrderRequest",
"req_type": "post",
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
"Host": "kyfw.12306.cn",
"re_try": 10,
"re_time": 0.01,
"s_time": 0.01,
"is_cdn": True,
"is_logger": True,
"is_json": True,
},
"confirmHB": { # 设置订单信息
"req_url": "/otn/afterNate/confirmHB",
"req_type": "post",
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
"Host": "kyfw.12306.cn",
"re_try": 10,
"re_time": 0.01,
"s_time": 0.01,
"is_cdn": True,
"is_logger": True,
"is_json": True,
},
"queryQueue": { # 排队
"req_url": "/otn/afterNate/queryQueue",
"req_type": "post",
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
"Host": "kyfw.12306.cn",
"re_try": 10,
"re_time": 0.01,
"s_time": 0.01,
"is_cdn": True,
"is_logger": True,
"is_json": True,
},
"passengerInitApi": { # 排队
"req_url": "/otn/afterNate/passengerInitApi",
"req_type": "post",
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
"Host": "kyfw.12306.cn",
"re_try": 10,
"re_time": 0.01,
"s_time": 0.01,
"is_cdn": True,
"is_logger": True,
"is_json": True,
},
"autoVerifyImage": { # 云打码接口
"req_url": TickerConfig.REQ_URL,
"req_type": "post",
"Referer": "",
"Host": TickerConfig.HOST,
"re_try": 6,
"re_time": 10,
"s_time": 0.001,
"is_logger": True,
"is_json": True,
"httpType": TickerConfig.HTTP_TYPE
},
}

@ -1,32 +0,0 @@
version: "3"
services:
#抢票服务
ticket:
build:
context: .
dockerfile: ./Dockerfile37
image: ticket:v1.2.004
environment:
- PYTHONUNBUFFERED=1
- CAPTCHALOCAL=1
container_name: ticket
depends_on:
- captcha
networks:
- 12306network
restart: on-failure
#打码服务器
captcha:
image: yinaoxiong/12306_code_server:amd64 #请根据需要修改image
environment:
- WORKERS=1 #gunicorn works 默认为1可以根据服务器配置自行调整
- PYTHONUNBUFFERED=1
container_name: captcha
networks:
- 12306network
restart: unless-stopped
networks:
12306network:
driver: bridge

@ -1,45 +0,0 @@
#!/bin/bash
#author: MonsterTan
#date: 2019-01-15
#this is a script that can install automatically docker software by centos7
function checkSudo (){
if [ $UID -ne 0 ];then
echo -e 'it must be root!'
exit 1
fi
}
checkSudo
## something required system utils
yum install -y yum-utils device-mapper-persistent-data lvm2
## add repo source info
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sudo yum mackecache fast
sudo yum -y install docker-ce
sudo systemctl start docker
str=successed!
if [ $? -eq 0 ];then
echo -e "\033[32msuccessed!\033[0m"
else
echo -e "\033[31msomething wrong, please check!\033[0m"
fi
echo -e "\033[31mstart to install docker-compose\033[0m"
result=`ls /usr/bin/ | grep ^pip$`
if [ ${#result} -eq 0 ];then
echo -e "\033[31mpip must be necessary, it should be installed firstly\033[0m"
fi
sudo pip install docker-compose

@ -1,559 +0,0 @@
111.161.122.240
112.90.135.96
60.9.0.19
61.162.100.102
222.186.141.146
221.235.187.129
58.221.78.231
113.16.212.251
112.47.27.131
112.123.33.18
183.134.42.18
116.77.75.133
112.90.135.97
58.221.78.42
61.162.100.103
111.161.122.67
60.9.0.20
113.16.212.48
112.47.56.174
112.28.196.75
183.134.42.19
116.77.75.137
112.90.135.98
113.16.212.49
36.250.248.220
60.9.0.21
116.199.127.56
221.235.187.130
112.47.27.172
112.90.135.99
183.134.42.190
60.9.0.22
222.186.141.165
116.77.75.138
36.102.230.136
112.47.56.117
183.134.42.191
60.9.0.23
116.77.75.145
36.102.230.137
222.186.141.166
58.221.78.46
61.162.100.107
116.77.75.144
113.207.77.252
60.9.0.252
222.186.141.178
183.134.42.20
61.167.54.55
58.221.78.47
221.180.208.54
116.77.75.169
61.162.100.252
222.186.141.186
60.9.0.254
113.207.79.17
183.134.42.247
61.167.54.57
111.161.22.17
116.77.75.146
58.221.78.48
61.162.100.41
111.6.176.208
113.207.79.34
36.250.248.222
36.102.230.19
183.134.53.153
116.77.75.147
61.162.100.44
111.6.176.209
113.207.79.42
183.134.53.155
116.77.75.170
36.102.230.20
120.221.64.161
222.218.87.252
111.6.176.248
113.207.79.37
120.221.64.169
112.47.56.118
111.6.176.25
113.194.59.80
124.236.28.100
113.207.81.126
111.6.176.94
111.6.176.95
113.194.59.199
221.235.187.220
124.236.28.252
221.235.187.244
111.6.176.97
124.236.28.67
113.194.59.81
120.221.64.53
36.250.248.252
120.221.64.54
124.236.28.247
36.250.248.254
120.221.64.55
124.236.28.69
116.77.75.183
36.250.248.27
221.235.187.66
183.134.53.223
124.236.28.68
113.207.81.78
58.20.179.253
27.195.145.121
221.235.187.90
113.207.81.81
27.195.145.123
221.235.187.98
123.128.14.254
183.134.53.248
111.161.22.62
123.128.14.69
124.236.28.93
117.169.93.249
183.146.22.135
125.39.1.134
36.102.230.254
124.236.28.92
117.169.93.85
27.195.145.249
125.39.1.191
124.236.28.94
42.81.144.179
222.218.87.28
27.195.145.52
124.236.28.95
36.250.248.56
222.218.87.29
42.81.144.180
27.195.145.62
36.159.115.250
36.159.115.88
36.159.115.89
183.146.22.137
110.242.21.24
124.236.28.98
117.169.93.86
123.128.14.70
110.242.21.23
124.236.28.99
117.23.2.252
123.128.14.72
112.28.196.54
110.242.21.254
117.149.154.185
58.20.179.74
150.138.111.251
117.23.2.28
110.242.21.243
117.149.154.186
58.20.179.73
150.138.111.31
110.242.21.41
117.23.2.29
111.47.220.251
150.138.111.32
110.242.21.71
106.41.0.37
111.47.220.66
110.242.21.70
150.138.111.33
111.47.220.67
106.41.0.44
150.138.167.234
150.138.167.50
106.41.0.45
222.186.145.51
150.138.167.52
111.62.194.30
106.41.0.46
122.228.237.248
42.81.144.31
150.138.169.120
222.186.145.54
59.56.30.51
106.41.0.47
42.81.144.39
111.62.194.31
222.44.151.24
150.138.169.121
112.28.196.251
106.41.0.61
111.62.194.254
123.138.157.85
106.120.178.19
150.138.167.51
150.138.169.123
112.28.196.249
106.41.0.62
120.253.100.20
114.112.172.58
123.138.157.122
150.138.169.124
183.146.22.145
112.28.196.53
120.253.100.21
222.44.151.191
183.146.22.146
125.77.147.254
112.28.196.74
120.253.100.22
222.44.151.25
222.186.145.52
120.253.100.23
61.151.238.197
120.253.100.30
61.151.238.222
61.151.238.229
117.149.155.148
117.149.155.147
183.146.22.171
150.138.169.238
60.210.23.26
125.77.147.68
221.235.187.119
125.77.147.69
115.157.63.19
117.149.155.76
115.157.63.49
122.224.186.221
183.201.225.249
119.52.120.138
60.28.100.155
125.77.147.80
122.70.142.148
122.224.186.222
119.52.120.139
60.28.100.156
122.70.142.147
125.77.147.82
122.224.186.225
60.28.100.157
119.52.120.140
125.77.147.88
114.112.172.57
122.224.186.226
60.28.100.158
150.138.214.84
119.52.120.144
58.216.21.250
60.28.100.248
119.52.120.145
150.138.214.124
60.210.23.116
183.66.109.254
117.180.229.254
150.138.214.85
119.52.120.146
61.147.226.46
115.157.63.50
122.224.186.253
58.216.22.17
150.138.214.86
222.186.145.53
117.180.229.142
58.216.22.20
183.222.97.164
61.147.226.48
58.216.22.22
183.222.97.165
122.224.186.223
183.66.109.44
58.216.22.56
183.222.97.166
60.210.23.29
221.235.187.67
183.66.109.45
115.157.63.51
183.222.97.254
183.146.22.142
183.146.22.139
120.226.55.144
221.235.187.121
153.99.235.112
120.226.55.151
120.226.55.254
112.240.60.213
36.25.241.75
122.225.83.25
153.99.235.91
112.240.60.214
122.225.83.28
115.157.63.52
36.25.241.76
121.22.247.202
114.112.172.59
122.228.237.74
36.25.241.77
112.240.60.215
121.22.247.204
223.111.18.161
122.228.237.75
112.240.60.216
121.22.247.254
218.26.75.149
223.111.18.162
122.228.237.76
112.240.60.217
115.157.63.62
218.26.75.150
223.111.18.163
122.225.83.26
122.228.239.233
112.240.60.222
223.111.18.217
218.26.75.151
222.186.145.251
122.228.239.234
112.240.60.236
218.26.75.152
116.207.132.183
122.228.239.235
61.147.227.53
159.226.225.149
218.26.75.153
116.207.132.184
122.228.239.236
116.207.132.253
218.26.75.206
113.207.10.204
122.228.239.238
218.26.75.236
113.207.10.218
122.228.239.243
122.228.239.244
122.228.239.246
139.209.49.140
183.131.124.38
159.226.225.154
139.209.49.138
121.22.247.203
139.209.49.144
123.53.139.253
139.209.49.151
125.74.58.134
139.209.49.152
123.53.139.36
125.74.58.135
125.74.58.136
139.209.49.153
123.184.108.251
210.38.3.23
183.131.124.40
123.184.108.60
123.184.108.61
210.38.3.24
159.226.225.139
183.131.124.58
125.74.58.254
210.38.3.42
159.226.225.140
61.54.7.158
124.95.148.254
183.131.124.59
61.54.7.174
210.38.3.49
124.95.148.30
101.69.146.234
210.38.3.50
61.54.7.179
124.95.148.29
14.204.185.100
210.38.3.60
61.54.7.243
60.220.196.220
124.95.148.31
14.204.185.101
60.220.196.221
59.83.232.18
14.204.185.102
59.83.232.50
61.147.210.193
122.70.142.252
14.204.185.123
61.147.210.195
14.204.185.254
223.111.198.252
61.147.226.185
101.69.146.33
223.111.198.65
113.207.70.194
61.147.210.242
113.207.70.207
101.69.146.35
60.210.23.23
61.147.226.47
113.207.70.208
101.69.146.34
60.210.23.25
61.147.226.49
183.131.168.148
60.210.23.27
61.147.227.102
113.207.72.102
60.213.21.117
58.220.71.253
61.147.227.126
58.220.71.51
60.213.21.118
14.204.185.91
58.220.71.52
113.207.70.209
60.213.21.156
113.207.77.117
60.213.21.214
60.220.196.250
58.220.71.62
116.199.127.50
60.213.21.244
58.220.71.63
118.123.233.254
116.199.127.54
218.29.198.43
58.220.71.64
60.213.21.243
118.123.233.30
218.29.198.62
116.77.73.164
103.254.189.230
58.220.71.65
60.213.21.245
118.123.233.31
223.86.219.254
183.214.132.120
60.213.21.252
223.86.219.65
183.214.132.16
116.199.127.55
223.86.219.66
183.214.132.17
60.255.143.93
61.149.9.150
60.255.143.94
60.255.143.95
60.255.143.96
36.250.233.185
106.40.140.224
36.250.233.208
61.147.228.201
36.250.233.209
183.214.140.204
123.53.139.37
222.24.122.86
61.147.228.60
36.250.233.210
106.40.140.254
183.214.140.238
36.250.233.214
36.250.233.228
58.221.78.186
36.250.248.218
218.12.228.246
112.90.135.244
222.24.122.89
36.250.248.217
221.235.187.106
218.12.228.38
36.250.233.254
112.47.20.250
218.12.228.39
112.90.135.92
117.27.245.227
112.90.135.93
117.27.245.254
117.27.245.52
112.90.135.94
117.27.245.97
112.90.135.95
117.27.245.54
218.60.185.251
113.5.80.33
125.77.130.247
218.60.185.46
125.77.130.251
118.203.202.206
118.203.202.207
218.60.185.47
218.60.185.48
118.203.202.208
118.203.202.209
118.203.202.222
221.180.192.100
125.77.130.46
125.77.130.47
112.47.20.68
125.77.130.48
163.177.132.27
112.47.27.132
125.77.130.49
112.47.20.89
61.147.228.89
112.47.20.79
106.120.178.253
221.180.192.254
221.230.141.170
221.180.192.61
106.120.178.20
163.177.132.30
183.216.176.74
221.230.141.172
183.216.176.75
221.230.141.174
110.19.204.219
110.19.204.220
219.138.27.108
110.19.204.221
219.138.27.249
103.254.189.229
106.120.178.22
219.138.27.30
219.138.27.31
113.16.208.251
222.186.141.132
113.16.208.77
113.16.208.78
222.186.141.141
110.19.204.254
222.186.141.142
221.180.208.252
222.186.141.143
117.161.19.126
221.180.208.46
222.186.141.145
60.9.0.18
117.161.19.19
221.180.208.47
117.161.19.22
113.142.80.223
183.134.42.153
183.134.42.154
183.134.42.155
115.223.24.254
183.134.42.156
111.161.122.100
183.134.42.157
61.136.167.17
183.134.42.158
61.136.167.18
183.134.42.159
113.142.80.69
183.134.42.17
113.142.80.71
61.136.167.19
113.142.80.72
115.223.24.80
111.161.122.133
115.223.24.81
111.161.122.134
115.223.24.82
111.161.122.135
114.112.172.56
222.74.113.196
222.74.113.219
61.167.54.236
61.167.54.242

@ -1,136 +0,0 @@
# -*- coding=utf-8 -*-
import copy
import time
from collections import OrderedDict
from time import sleep
import TickerConfig
from inter.GetPassCodeNewOrderAndLogin import getPassCodeNewOrderAndLogin1
from inter.GetRandCode import getRandCode
from inter.LoginAysnSuggest import loginAysnSuggest
from inter.LoginConf import loginConf
from myException.UserPasswordException import UserPasswordException
class GoLogin:
def __init__(self, session, is_auto_code, auto_code_type):
self.session = session
self.randCode = ""
self.is_auto_code = is_auto_code
self.auto_code_type = auto_code_type
def auth(self):
"""
:return:
"""
self.session.httpClint.send(self.session.urls["loginInitCdn1"])
uamtkStaticUrl = self.session.urls["uamtk-static"]
uamtkStaticData = {"appid": "otn"}
return self.session.httpClint.send(uamtkStaticUrl, uamtkStaticData)
def codeCheck(self):
"""
验证码校验
:return:
"""
codeCheckUrl = copy.deepcopy(self.session.urls["codeCheck1"])
codeCheckUrl["req_url"] = codeCheckUrl["req_url"].format(self.randCode, int(time.time() * 1000))
fresult = self.session.httpClint.send(codeCheckUrl)
if not isinstance(fresult, str):
print("登录失败")
return
fresult = eval(fresult.split("(")[1].split(")")[0])
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.session.httpClint.del_cookies()
def baseLogin(self, user, passwd):
"""
登录过程
:param user:
:param passwd:
:return: 权限校验码
"""
logurl = self.session.urls["login"]
loginData = OrderedDict()
loginData["username"] = user,
loginData["password"] = passwd,
loginData["appid"] = "otn",
loginData["answer"] = self.randCode,
tresult = self.session.httpClint.send(logurl, loginData)
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.session.urls["uamauthclient"]
data = {"tk": uamtk}
uamauthclientResult = self.session.httpClint.send(uamauthclientUrl, data)
if uamauthclientResult:
if "result_code" in uamauthclientResult and uamauthclientResult["result_code"] == 0:
print(u"欢迎 {} 登录".format(uamauthclientResult["username"]))
return True
else:
return False
else:
self.session.httpClint.send(uamauthclientUrl, data)
url = self.session.urls["getUserInfo"]
self.session.httpClint.send(url)
def go_login(self):
"""
登陆
:param user: 账户名
:param passwd: 密码
:return:
"""
user, passwd = TickerConfig.USER, TickerConfig.PWD
if not user or not passwd:
raise UserPasswordException(u"温馨提示: 用户名或者密码为空,请仔细检查")
login_num = 0
while True:
if loginConf(self.session):
result = getPassCodeNewOrderAndLogin1(session=self.session, imgType="login")
if not result:
continue
self.randCode = getRandCode(self.is_auto_code, self.auto_code_type, result)
print(self.randCode)
login_num += 1
self.auth()
if self.codeCheck():
uamtk = self.baseLogin(user, passwd)
if uamtk:
self.getUserName(uamtk)
break
else:
loginAysnSuggest(self.session, username=user, password=passwd)
login_num += 1
break

@ -1,252 +0,0 @@
# -*- coding=utf-8 -*-
import datetime
import random
import os
import socket
import sys
import threading
import time
import TickerConfig
import wrapcache
from agency.cdn_utils import CDNProxy, open_cdn_file
from config import urlConf, configCommon
from config.TicketEnmu import ticket
from config.configCommon import seat_conf_2, seat_conf
from config.getCookie import getDrvicesID
from init.login import GoLogin
from inter.AutoSubmitOrderRequest import autoSubmitOrderRequest
from inter.ChechFace import chechFace
from inter.CheckUser import checkUser
from inter.GetPassengerDTOs import getPassengerDTOs
from inter.LiftTicketInit import liftTicketInit
from inter.Query import query
from inter.SubmitOrderRequest import submitOrderRequest
from myException.PassengerUserException import PassengerUserException
from myException.UserPasswordException import UserPasswordException
from myException.ticketConfigException import ticketConfigException
from myException.ticketIsExitsException import ticketIsExitsException
from myException.ticketNumOutException import ticketNumOutException
from myUrllib.httpUtils import HTTPClient
class select:
"""
快速提交车票通道
"""
def __init__(self):
self.cdn_list = open_cdn_file("filter_cdn_list")
self.get_ticket_info()
self._station_seat = [seat_conf[x] for x in TickerConfig.SET_TYPE]
self.auto_code_type = TickerConfig.AUTO_CODE_TYPE
self.httpClint = HTTPClient(TickerConfig.IS_PROXY, self.cdn_list)
self.httpClint.cdn = self.cdn_list[random.randint(0, 4)]
self.urls = urlConf.urls
self.login = GoLogin(self, TickerConfig.IS_AUTO_CODE, self.auto_code_type)
self.cookies = ""
self.queryUrl = "leftTicket/queryO"
self.passengerTicketStrList = ""
self.passengerTicketStrByAfterLate = ""
self.oldPassengerStr = ""
self.set_type = ""
self.flag = True
@staticmethod
def get_ticket_info():
"""
获取配置信息
:return:
"""
print(u"*" * 50)
print(f"检查当前版本为: {TickerConfig.RE_VERSION}")
version = sys.version.split(" ")[0]
print(u"检查当前python版本为{}目前版本只支持3.6以上".format(version))
if version < "3.6.0":
raise Exception
print(u"12306刷票小助手最后更新于2019.09.18,请勿作为商业用途,交流群号:"
u" 1群286271084(已满)\n"
u" 2群649992274(已满)\n"
u" 3群632501142(已满)\n"
u" 4群: 606340519(已满)\n"
u" 5群: 948526733(已满)\n"
u" 7群: 660689659(已满)\n"
u" 8群: 620629239(已满)\n"
u" 6群: 608792930(未满)\n"
u" 9群: 693035807(未满)\n"
)
print(
f"当前配置:\n出发站:{TickerConfig.FROM_STATION}\n到达站:{TickerConfig.TO_STATION}\n车次: {','.join(TickerConfig.STATION_TRAINS) or '所有车次'}\n乘车日期:{','.join(TickerConfig.STATION_DATES)}\n坐席:{','.join(TickerConfig.SET_TYPE)}\n是否有票优先提交:{TickerConfig.IS_MORE_TICKET}\n乘车人:{TickerConfig.TICKET_PEOPLES}\n" \
f"刷新间隔: 随机(1-3S)\n僵尸票关小黑屋时长: {TickerConfig.TICKET_BLACK_LIST_TIME}\n下单接口: {TickerConfig.ORDER_TYPE}\n下单模式: {TickerConfig.ORDER_MODEL}\n预售踩点时间:{TickerConfig.OPEN_TIME}")
print(u"*" * 50)
def station_table(self, from_station, to_station):
"""
读取车站信息
:param station:
:return:
"""
path = os.path.join(os.path.dirname(__file__), '../station_name.txt')
try:
with open(path, encoding="utf-8") as result:
info = result.read().split('=')[1].strip("'").split('@')
except Exception:
with open(path) as result:
info = result.read().split('=')[1].strip("'").split('@')
del info[0]
station_name = {}
for i in range(0, len(info)):
n_info = info[i].split('|')
station_name[n_info[1]] = n_info[2]
try:
from_station = station_name[from_station.encode("utf8")]
to_station = station_name[to_station.encode("utf8")]
except KeyError:
from_station = station_name[from_station]
to_station = station_name[to_station]
return from_station, to_station
def call_login(self, auth=False):
"""
登录回调方法
:return:
"""
if auth:
return self.login.auth()
else:
configCommon.checkSleepTime(self) # 防止网上启动晚上到点休眠
self.login.go_login()
def main(self):
l = liftTicketInit(self)
l.reqLiftTicketInit()
getDrvicesID(self)
self.call_login()
check_user = checkUser(self)
t = threading.Thread(target=check_user.sendCheckUser)
t.setDaemon(True)
t.start()
from_station, to_station = self.station_table(TickerConfig.FROM_STATION, TickerConfig.TO_STATION)
num = 0
s = getPassengerDTOs(selectObj=self, ticket_peoples=TickerConfig.TICKET_PEOPLES)
passenger = s.sendGetPassengerDTOs()
wrapcache.set("user_info", passenger, timeout=9999999)
now = datetime.datetime.now()
if TickerConfig.ORDER_MODEL is 1:
print(f"预售还未开始,阻塞中,预售时间为{TickerConfig.OPEN_TIME}, 当前时间为: {now.strftime('%H:%M:%S')}")
sleep_time_s = 0.1
sleep_time_t = 0.3
# 测试了一下有微妙级的误差应该不影响测试结果2019-01-02 22:30:00.004555,预售还是会受到前一次刷新的时间影响,暂时没想到好的解决方案
while now.strftime("%H:%M:%S") < TickerConfig.OPEN_TIME:
now = datetime.datetime.now()
time.sleep(0.0001)
print(f"预售开始,开启时间为: {now.strftime('%H:%M:%S')}")
else:
sleep_time_s = TickerConfig.MIN_TIME
sleep_time_t = TickerConfig.MAX_TIME
while 1:
try:
num += 1
now = datetime.datetime.now() # 感谢群里大佬提供整点代码
configCommon.checkSleepTime(self) # 晚上到点休眠
q = query(selectObj=self,
from_station=from_station,
to_station=to_station,
from_station_h=TickerConfig.FROM_STATION,
to_station_h=TickerConfig.TO_STATION,
_station_seat=self._station_seat,
station_trains=TickerConfig.STATION_TRAINS,
station_dates=TickerConfig.STATION_DATES,
ticke_peoples_num=len(TickerConfig.TICKET_PEOPLES),
)
queryResult = q.sendQuery()
# 查询接口
if queryResult.get("status"):
train_no = queryResult.get("train_no", "")
train_date = queryResult.get("train_date", "")
stationTrainCode = queryResult.get("stationTrainCode", "")
secretStr = queryResult.get("secretStr", "")
secretList = queryResult.get("secretList", "")
seat = queryResult.get("seat", "")
leftTicket = queryResult.get("leftTicket", "")
query_from_station_name = queryResult.get("query_from_station_name", "")
query_to_station_name = queryResult.get("query_to_station_name", "")
is_more_ticket_num = queryResult.get("is_more_ticket_num", len(TickerConfig.TICKET_PEOPLES))
if wrapcache.get(train_no):
print(ticket.QUEUE_WARNING_MSG.format(train_no))
else:
# 获取联系人
s = getPassengerDTOs(selectObj=self, ticket_peoples=TickerConfig.TICKET_PEOPLES,
set_type="" if isinstance(seat, list) else seat_conf_2[seat],
# 候补订单需要设置多个坐席
is_more_ticket_num=is_more_ticket_num)
getPassengerDTOsResult = s.getPassengerTicketStrListAndOldPassengerStr(secretStr, secretList)
if getPassengerDTOsResult.get("status", False):
self.passengerTicketStrList = getPassengerDTOsResult.get("passengerTicketStrList", "")
self.passengerTicketStrByAfterLate = getPassengerDTOsResult.get(
"passengerTicketStrByAfterLate", "")
self.oldPassengerStr = getPassengerDTOsResult.get("oldPassengerStr", "")
self.set_type = getPassengerDTOsResult.get("set_type", "")
# 提交订单
# 订单分为两种,一种为抢单,一种为候补订单
if secretStr: # 正常下单
if TickerConfig.ORDER_TYPE == 1: # 快速下单
a = autoSubmitOrderRequest(selectObj=self,
secretStr=secretStr,
train_date=train_date,
passengerTicketStr=self.passengerTicketStrList,
oldPassengerStr=self.oldPassengerStr,
train_no=train_no,
stationTrainCode=stationTrainCode,
leftTicket=leftTicket,
set_type=self.set_type,
query_from_station_name=query_from_station_name,
query_to_station_name=query_to_station_name,
)
a.sendAutoSubmitOrderRequest()
elif TickerConfig.ORDER_TYPE == 2: # 普通下单
sor = submitOrderRequest(self, secretStr, from_station, to_station, train_no,
self.set_type,
self.passengerTicketStrList, self.oldPassengerStr, train_date,
TickerConfig.TICKET_PEOPLES)
sor.sendSubmitOrderRequest()
elif secretList: # 候补订单
c = chechFace(self, secretList, train_no)
c.sendChechFace()
else:
random_time = round(random.uniform(sleep_time_s, sleep_time_t), 2)
nateMsg = ' 无候补机会' if TickerConfig.ORDER_TYPE == 2 else ""
print(f"正在第{num}次查询 停留时间:{random_time} 乘车日期: {','.join(TickerConfig.STATION_DATES)} 车次:{','.join(TickerConfig.STATION_TRAINS) or '所有车次'} 下单无票{nateMsg} 耗时:{(datetime.datetime.now() - now).microseconds / 1000} {queryResult.get('cdn')}")
time.sleep(random_time)
except PassengerUserException as e:
print(e)
break
except ticketConfigException as e:
print(e)
break
except ticketIsExitsException as e:
print(e)
break
except ticketNumOutException as e:
print(e)
break
except UserPasswordException as e:
print(e)
break
except ValueError as e:
if e == "No JSON object could be decoded":
print(u"12306接口无响应正在重试")
else:
print(e)
except KeyError as e:
print(e)
except TypeError as e:
print(u"12306接口无响应正在重试 {0}".format(e))
except socket.error as e:
print(e)
if __name__ == '__main__':
s = select()
cdn = s.station_table("长沙", "深圳")

@ -1,124 +0,0 @@
# coding=utf-8
import urllib
from collections import OrderedDict
from config.TicketEnmu import ticket
from inter.CheckRandCodeAnsyn import checkRandCodeAnsyn
from inter.GetQueueCountAsync import getQueueCountAsync
from inter.GetRandCode import getRandCode
import TickerConfig
class autoSubmitOrderRequest:
"""
快读提交订单通道
"""
def __init__(self, selectObj,
secretStr,
train_date,
query_from_station_name,
query_to_station_name,
passengerTicketStr,
oldPassengerStr,
train_no,
stationTrainCode,
leftTicket,
set_type,):
self.set_type = set_type
try:
self.secretStr = urllib.unquote(secretStr)
except AttributeError:
self.secretStr = urllib.parse.unquote(secretStr)
self.train_date = train_date
self.query_from_station_name = query_from_station_name
self.query_to_station_name = query_to_station_name
self.passengerTicketStr = passengerTicketStr.rstrip("_{0}".format(self.set_type))
self.oldPassengerStr = oldPassengerStr
self.session = selectObj
self.train_no = train_no
self.stationTrainCode = stationTrainCode
self.leftTicket = leftTicket
def data_par(self):
"""
参数结构
自动提交代码接口-autoSubmitOrderRequest
- 字段说明
- secretStr 车票代码
- train_date 乘车日期
- tour_flag 乘车类型
- purpose_codes 学生还是成人
- query_from_station_name 起始车站
- query_to_station_name 结束车站
- cancel_flag 默认2我也不知道干嘛的
- bed_level_order_num 000000000000000000000000000000
- passengerTicketStr 乘客乘车代码
- oldPassengerStr 乘客编号代码
:return:
"""
data = OrderedDict()
data["secretStr"] = self.secretStr
data["train_date"] = self.train_date
data["tour_flag"] = "dc"
data["purpose_codes"] = "ADULT"
data["query_from_station_name"] = TickerConfig.FROM_STATION
data["query_to_station_name"] = TickerConfig.TO_STATION
data["cancel_flag"] = 2
data["bed_level_order_num"] = "000000000000000000000000000000"
data["passengerTicketStr"] = self.passengerTicketStr
data["oldPassengerStr"] = self.oldPassengerStr
return data
def sendAutoSubmitOrderRequest(self):
"""
请求下单接口
:return:
"""
urls = self.session.urls["autoSubmitOrderRequest"]
data = self.data_par()
autoSubmitOrderRequestResult = self.session.httpClint.send(urls, data)
if autoSubmitOrderRequestResult and \
autoSubmitOrderRequestResult.get("status", False) and\
autoSubmitOrderRequestResult.get("httpstatus", False) == 200:
requestResultData = autoSubmitOrderRequestResult.get("data", {})
if requestResultData:
result = requestResultData.get("result", "")
ifShowPassCode = requestResultData.get("ifShowPassCode", "N")
ifShowPassCodeTime = int(requestResultData.get("ifShowPassCodeTime", "1000")) / float(1000)
print(ticket.AUTO_SUBMIT_ORDER_REQUEST_C)
g = getQueueCountAsync(session=self.session,
train_no=self.train_no,
stationTrainCode=self.stationTrainCode,
fromStationTelecode=self.query_from_station_name,
toStationTelecode=self.query_to_station_name,
leftTicket=self.leftTicket,
set_type=self.set_type,
users=len(TickerConfig.TICKET_PEOPLES),
station_dates=self.train_date,
passengerTicketStr=self.passengerTicketStr,
oldPassengerStr=self.oldPassengerStr,
result=result,
ifShowPassCodeTime=ifShowPassCodeTime,
)
if ifShowPassCode == "Y": # 如果需要验证码
print(u"需要验证码")
print(u"正在使用自动识别验证码功能")
for i in range(3):
randCode = getRandCode(is_auto_code=True, auto_code_type=2)
checkcode = checkRandCodeAnsyn(self.session, randCode, "")
if checkcode == 'TRUE':
print(u"验证码通过,正在提交订单")
data['randCode'] = randCode
break
else:
print (u"验证码有误, {0}次尝试重试".format(i + 1))
print(u"验证码超过限定次数3次放弃此次订票机会!")
g.sendGetQueueCountAsync()
else:
print(ticket.AUTO_SUBMIT_ORDER_REQUEST_F)
if autoSubmitOrderRequestResult.get("messages", ""):
print("".join(autoSubmitOrderRequestResult.get("messages", "")))
elif autoSubmitOrderRequestResult.get("validateMessages", ""):
print("".join(autoSubmitOrderRequestResult.get("validateMessages", "")))

@ -1,68 +0,0 @@
import datetime
import urllib
from collections import OrderedDict
from config.urlConf import urls
import TickerConfig
from inter.GetSuccessRate import getSuccessRate
from myException.ticketConfigException import ticketConfigException
import wrapcache
class chechFace:
def __init__(self, selectObj, secretList, train_no):
"""
人脸识别
"""
self.secretList = secretList
self.session = selectObj
self.train_no = train_no
def data_apr(self):
"""
secretList 9vqa9%2B%2F%2Fsdozmm22hpSeDTGqRUwSuA2D0r%2BmU%2BLZj7MK7CDuf5Ep1xpxl4Dyxfmoah%2BaB9TZSesU%0AkxBbo5oNgR1vqMfvq66VP0T7tpQtH%2BbVGBz1FolZG8jDD%2FHqnz%2FnvdBP416Og6WGS14O%2F3iBSwT8%0AkRPsNF0Vq0U082g0tlJtP%2BPn7TzW3z7TDCceMJIjFcfEOA%2BW%2BuK%2Bpy6jCQMv0TmlkXf5aKcGnE02%0APuv4I8nF%2BOWjWzv9CrJyiCZiWaXd%2Bi7p69V3a9dhF787UgS660%2BqKRFB4RLwAfic3MkAlfpGWhMY%0ACfARVQ%3D%3D#O|
_json_att
候补一次只能补一个座位默认取TICKET_TYPE第一个
:return:
"""
ticker = TickerConfig.PASSENGER_TICKER_STR.get(TickerConfig.SET_TYPE[0])
data = OrderedDict()
data["secretList"] = f"{self.secretList}#{ticker}|"
data["_json_att"] = ""
return data
def sendChechFace(self):
chechFaceRsp = self.session.httpClint.send(urls.get("chechFace"), self.data_apr())
if not chechFaceRsp.get("status"):
print("".join(chechFaceRsp.get("messages")) or chechFaceRsp.get("validateMessages"))
wrapcache.set(key=f"hb{self.train_no}", value=datetime.datetime.now(),
timeout=TickerConfig.TICKET_BLACK_LIST_TIME * 60)
return
data = chechFaceRsp["data"]
if not data.get("face_flag"):
print("".join(chechFaceRsp.get("messages")) or chechFaceRsp.get("validateMessages"))
if data.get("face_check_code") == "14":
"""
未通过人脸核验
"""
raise ticketConfigException("通过人证一致性核验的用户及激活的“铁路畅行”会员可以提交候补需求请您按照操作说明在铁路12306app.上完成人证核验")
elif data.get("face_check_code") in ["12", "02"]:
"""
系统忙请稍后再试
"""
print("系统忙,请稍后再试!")
wrapcache.set(key=f"hb{self.train_no}", value=datetime.datetime.now(),
timeout=TickerConfig.TICKET_BLACK_LIST_TIME * 60)
elif data.get("face_check_code") in ["03", "13"]:
"""
证件信息审核失败请检查所填写的身份信息内容与原证件是否一致
"""
raise ticketConfigException("证件信息审核失败,请检查所填写的身份信息内容与原证件是否一致。")
elif data.get("face_check_code") in ["01", "11"]:
"""
证件信息正在审核中请您耐心等待审核通过后可继续完成候补操作
"""
print("证件信息正在审核中,请您耐心等待,审核通过后可继续完成候补操作。")
wrapcache.set(key=f"hb{self.train_no}", value=datetime.datetime.now(),
timeout=TickerConfig.TICKET_BLACK_LIST_TIME * 60)
g = getSuccessRate(self.session, self.secretList)
g.sendSuccessRate()

@ -1,74 +0,0 @@
# coding=utf-8
from collections import OrderedDict
from inter.GetQueueCount import getQueueCount
from inter.GetRepeatSubmitToken import getRepeatSubmitToken
class checkOrderInfo:
def __init__(self, session, train_no, set_type, passengerTicketStrList, oldPassengerStr, station_dates, ticket_peoples):
self.train_no = train_no
self.set_type = set_type
self.passengerTicketStrList = passengerTicketStrList
self.oldPassengerStr = oldPassengerStr
self.station_dates = station_dates
self.ticket_peoples = ticket_peoples
self.RepeatSubmitToken = getRepeatSubmitToken(session)
self.getTicketInfoForPassengerForm = self.RepeatSubmitToken.sendGetRepeatSubmitToken()
self.ticketInfoForPassengerForm = self.getTicketInfoForPassengerForm.get("ticketInfoForPassengerForm", "")
self.token = self.getTicketInfoForPassengerForm.get("token", "")
self.session = self.getTicketInfoForPassengerForm.get("session", "")
def data_par(self):
"""
参数结构
:return:
"""
data = OrderedDict()
data['bed_level_order_num'] = "000000000000000000000000000000"
data['passengerTicketStr'] = self.passengerTicketStrList.rstrip("_{0}".format(self.set_type))
data['oldPassengerStr'] = self.oldPassengerStr
data['tour_flag'] = 'dc'
data['randCode'] = ""
data['cancel_flag'] = 2
data['_json_att'] = ""
data['REPEAT_SUBMIT_TOKEN'] = self.token
return data
def sendCheckOrderInfo(self):
"""
检查支付订单需要提交REPEAT_SUBMIT_TOKEN
passengerTicketStr : 座位编号,0,票类型,乘客名,证件类型,证件号,手机号码,保存常用联系人(Y或N)
oldPassengersStr: 乘客名,证件类型,证件号,乘客类型
:return:
"""
CheckOrderInfoUrls = self.session.urls["checkOrderInfoUrl"]
data = self.data_par()
checkOrderInfoRep = self.session.httpClint.send(CheckOrderInfoUrls, data)
data = checkOrderInfoRep.get("data", {})
if data and data.get("submitStatus", False):
print (u'车票提交通过,正在尝试排队')
ifShowPassCodeTime = int(checkOrderInfoRep["data"]["ifShowPassCodeTime"]) / float(1000)
if "ifShowPassCode" in checkOrderInfoRep["data"] and checkOrderInfoRep["data"]["ifShowPassCode"] == "Y":
is_need_code = True
elif "ifShowPassCode" in checkOrderInfoRep["data"] and checkOrderInfoRep['data']['submitStatus'] is True:
is_need_code = False
else:
is_need_code = False
QueueCount = getQueueCount(self.session,
is_need_code,
ifShowPassCodeTime,
self.set_type,
self.station_dates,
self.train_no,
self.ticket_peoples,
self.ticketInfoForPassengerForm,
self.token,
self.oldPassengerStr,
self.passengerTicketStrList,
)
QueueCount.sendGetQueueCount()
elif "errMsg" in data and data["errMsg"]:
print(checkOrderInfoRep['data']["errMsg"])
elif 'messages' in checkOrderInfoRep and checkOrderInfoRep['messages']:
print (checkOrderInfoRep['messages'][0])

@ -1,27 +0,0 @@
# coding=utf-8
class checkRandCodeAnsyn:
def __init__(self, session, randCode, token):
self.session = session
self.randCode = randCode
self.token = token
def data_par(self):
"""
:return:
"""
data = {
"randCode": self.randCode,
"rand": "randp",
"_json_att": "",
"REPEAT_SUBMIT_TOKEN": self.token
}
return data
def sendCheckRandCodeAnsyn(self):
"""
下单验证码识别
:return:
"""
checkRandCodeAnsynUrl = self.session.urls["checkRandCodeAnsyn"]
fresult = self.session.httpClint.send(checkRandCodeAnsynUrl, self.data_par()) # 校验验证码是否正确
return fresult['data']['msg']

@ -1,39 +0,0 @@
# coding=utf-8
import datetime
import random
import time
import wrapcache
from config import configCommon
from config.TicketEnmu import ticket
class checkUser:
def __init__(self, session):
self.session = session
def sendCheckUser(self):
"""
检查用户登录, 检查间隔为2分钟
:return:
"""
CHENK_TIME = 1
while 1:
time.sleep(3) # 防止cpu占用过高
configCommon.checkSleepTime(self.session) # 修复晚上查询线程休眠时,检查登录线程为休眠,造成快豆迅速消耗
if wrapcache.get("user_time") is None:
check_user_url = self.session.urls["check_user_url"]
data = {"_json_att": ""}
check_user = self.session.httpClint.send(check_user_url, data)
if check_user.get("data", False):
check_user_flag = check_user["data"]["flag"]
if check_user_flag is True:
wrapcache.set("user_time", datetime.datetime.now(), timeout=random.randint(60, 80) * CHENK_TIME)
else:
if check_user['messages']:
print(ticket.LOGIN_SESSION_FAIL.format(check_user['messages']))
self.session.call_login()
wrapcache.set("user_time", datetime.datetime.now(), timeout=random.randint(60, 80) * CHENK_TIME)
else:
print(ticket.LOGIN_SESSION_FAIL.format(check_user['messages']))
self.session.call_login()
wrapcache.set("user_time", datetime.datetime.now(), timeout=random.randint(60, 80) * CHENK_TIME)

@ -1,48 +0,0 @@
from collections import OrderedDict
from config.urlConf import urls
import TickerConfig
from inter.GetQueueCount import queryQueueByAfterNate
class confirmHB:
def __init__(self, secretList, session, tickerNo, jzdhDate):
"""
人脸识别
"""
self.secretList = secretList
self.session = session
self.passengerTicketStrByAfterLate = session.passengerTicketStrByAfterLate
self.tickerNo = tickerNo
self.jzdhDate = jzdhDate
def data_apr(self):
"""
passengerInfo 1#XXXX#1#***************77X#bf6ae40d3655ae7eff005ee21d95876b38ab97a8031b464bc2f74a067e3ec957;
jzParam 2019-08-31#19#00
hbTrain 5l000G177230,O#
lkParam
:return:
"""
ticker = TickerConfig.PASSENGER_TICKER_STR.get(TickerConfig.SET_TYPE[0])
data = OrderedDict()
data["passengerInfo"] = self.passengerTicketStrByAfterLate
data["jzParam"] = self.jzdhDate
data["hbTrain"] = f"{self.tickerNo},{ticker}#"
data["lkParam"] = ""
return data
def sendChechFace(self):
ChechFaceRsp = self.session.httpClint.send(urls.get("confirmHB"), self.data_apr())
if not ChechFaceRsp.get("status"):
print("".join(ChechFaceRsp.get("messages")) or ChechFaceRsp.get("validateMessages"))
return
data = ChechFaceRsp.get("data")
if not data.get("flag"):
print(f"错误信息:{data.get('msg')}")
return
queue = queryQueueByAfterNate(self.session)
queue.sendQueryQueueByAfterNate()

@ -1,94 +0,0 @@
# coding=utf-8
import datetime
import time
from inter.CheckRandCodeAnsyn import checkRandCodeAnsyn
from inter.GetPassengerDTOs import getPassengerDTOs
from inter.GetRandCode import getRandCode
from inter.QueryOrderWaitTime import queryOrderWaitTime
class confirmSingleForQueue:
def __init__(self, session, ifShowPassCodeTime, is_node_code, token, set_type, ticket_peoples, ticketInfoForPassengerForm,
oldPassengerStr, passengerTicketStrList):
self.session = session
self.ifShowPassCodeTime = ifShowPassCodeTime
self.is_node_code = is_node_code
self.token = token
self.set_type = set_type
self.ticket_peoples = ticket_peoples
self.ticketInfoForPassengerForm = ticketInfoForPassengerForm
self.passengerTicketStrList = passengerTicketStrList
self.oldPassengerStr = oldPassengerStr
def data_par(self):
"""
模拟提交订单是确认按钮参数获取方法还是get_ticketInfoForPassengerForm 中获取
:return:
"""
if not self.passengerTicketStrList and not self.oldPassengerStr:
s = getPassengerDTOs(session=self.session, ticket_peoples=self.ticket_peoples, set_type=self.set_type)
getPassengerDTOsResult = s.getPassengerTicketStrListAndOldPassengerStr()
if getPassengerDTOsResult.get("status", False):
self.passengerTicketStrList = getPassengerDTOsResult.get("passengerTicketStrList", "")
self.oldPassengerStr = getPassengerDTOsResult.get("oldPassengerStr", "")
data = {
"passengerTicketStr": self.passengerTicketStrList.rstrip("_{0}".format(self.set_type)),
"oldPassengerStr": "".join(self.oldPassengerStr),
"purpose_codes": self.ticketInfoForPassengerForm["purpose_codes"],
"key_check_isChange": self.ticketInfoForPassengerForm["key_check_isChange"],
"leftTicketStr": self.ticketInfoForPassengerForm["leftTicketStr"],
"train_location": self.ticketInfoForPassengerForm["train_location"],
"seatDetailType": "", # 开始需要选择座位但是目前12306不支持自动选择作为那这个参数为默认
"roomType": "00", # 好像是根据一个id来判断选中的两种 第一种是00第二种是10但是我在12306的页面没找到该id目前写死是00不知道会出什么错
"dwAll": "N",
"whatsSelect": 1,
"_json_at": "",
"randCode": "",
"choose_seats": "",
"REPEAT_SUBMIT_TOKEN": self.token,
}
return data
def sendConfirmSingleForQueue(self):
"""
# 模拟查询当前的列车排队人数的方法
# 返回信息组成的提示字符串
:return:
"""
data = self.data_par()
checkQueueOrderUrl = self.session.urls["checkQueueOrderUrl"]
try:
if self.is_node_code:
print(u"正在使用自动识别验证码功能")
for i in range(3):
randCode = getRandCode(is_auto_code=True, auto_code_type=2)
checkcode = checkRandCodeAnsyn(self.session, randCode, self.token)
if checkcode == 'TRUE':
print(u"验证码通过,正在提交订单")
data['randCode'] = randCode
break
else:
print (u"验证码有误, {0}次尝试重试".format(i + 1))
print(u"验证码超过限定次数3次放弃此次订票机会!")
else:
print(u"不需要验证码")
time.sleep(self.ifShowPassCodeTime)
checkQueueOrderResult = self.session.httpClint.send(checkQueueOrderUrl, data)
if "status" in checkQueueOrderResult and checkQueueOrderResult["status"]:
c_data = checkQueueOrderResult["data"] if "data" in checkQueueOrderResult else {}
if 'submitStatus' in c_data and c_data['submitStatus'] is True:
qow = queryOrderWaitTime(self.session)
qow.sendQueryOrderWaitTime()
else:
if 'errMsg' in c_data and c_data['errMsg']:
print(u"提交订单失败,{0}".format(c_data['errMsg']))
else:
print(c_data)
print(u'订票失败!很抱歉,请重试提交预订功能!')
elif "messages" in checkQueueOrderResult and checkQueueOrderResult["messages"]:
print(u"提交订单失败,错误信息: " + checkQueueOrderResult["messages"])
else:
print(u"提交订单中,请耐心等待:" + checkQueueOrderResult["message"])
except ValueError:
print(u"接口 {} 无响应".format(checkQueueOrderUrl))

@ -1,72 +0,0 @@
# coding=utf-8
import json
import urllib
from collections import OrderedDict
from inter.QueryOrderWaitTime import queryOrderWaitTime
class confirmSingleForQueueAsys:
"""
订单快读排队
"""
def __init__(self,
session,
passengerTicketStr,
oldPassengerStr,
result,
randCode="",
):
self.session = session
self.passengerTicketStr = passengerTicketStr
self.oldPassengerStr = oldPassengerStr
self.result = result if isinstance(result, str) else str(result)
self.randCode = randCode
def data_par(self):
"""
字段说明
passengerTicketStr 乘客乘车代码
oldPassengerStr 乘客编号代码
randCode 填空
purpose_codes 学生还是成人
key_check_isChange autoSubmitOrderRequest返回的result字段做切割即可
leftTicketStr autoSubmitOrderRequest返回的result字段做切割即可
train_location autoSubmitOrderRequest返回的result字段做切割即可
choose_seats
seatDetailType
_json_att
:return:
"""
results = self.result.split("#")
key_check_isChange = results[1]
leftTicketStr = results[2]
train_location = results[0]
data = OrderedDict()
data["passengerTicketStr"] = self.passengerTicketStr
data["oldPassengerStr"] = self.oldPassengerStr
data["randCode"] = self.randCode
data["purpose_codes"] = "ADULT"
data["key_check_isChange"] = key_check_isChange
data["leftTicketStr"] = leftTicketStr
data["train_location"] = train_location
data["choose_seats"] = ""
data["seatDetailType"] = ""
data["_json_att"] = ""
return data
def sendConfirmSingleForQueueAsys(self):
"""
请求订单快读排队接口
:return:
"""
urls = self.session.urls["confirmSingleForQueueAsys"]
data = self.data_par()
confirmSingleForQueueAsysResult = self.session.httpClint.send(urls, data)
if confirmSingleForQueueAsysResult.get("status", False) and confirmSingleForQueueAsysResult.get("data", False):
queueData = confirmSingleForQueueAsysResult.get("data", {})
if queueData.get("submitStatus", False):
qwt = queryOrderWaitTime(session=self.session)
qwt.sendQueryOrderWaitTime()
else:
print(queueData.get("errMsg", ""))

@ -1,78 +0,0 @@
# coding=utf-8
import base64
import copy
import random
def getPassCodeNewOrderAndLogin(session, imgType):
"""
下载验证码
:param session:
:param imgType: 下载验证码类型login=登录验证码其余为订单验证码
:return:
"""
if imgType == "login":
codeImgUrl = copy.deepcopy(session.urls["getCodeImg"])
codeImgUrl["req_url"] = codeImgUrl["req_url"].format(random.random())
else:
codeImgUrl = copy.deepcopy(session.urls["codeImgByOrder"])
codeImgUrl["req_url"] = codeImgUrl["req_url"].format(random.random())
print(u"下载验证码...")
img_path = './tkcode.png'
result = session.httpClint.send(codeImgUrl)
try:
if isinstance(result, dict):
print(u"下载验证码失败, 请手动检查是否ip被封或者重试请求地址https://kyfw.12306.cn{}".format(codeImgUrl.get("req_url")))
return False
else:
print(u"下载验证码成功")
try:
with open(img_path, 'wb', encoding="utf-8") as img:
img.write(result)
except Exception:
with open(img_path, 'wb') as img:
img.write(result)
return result
except OSError:
print(u"验证码下载失败可能ip被封确认请手动请求: {0}".format(codeImgUrl))
def getPassCodeNewOrderAndLogin1(session, imgType):
"""
获取验证码2
:param session:
:param imgType:
:return:
"""
if imgType == "login":
codeImgUrl = copy.deepcopy(session.urls["getCodeImg1"])
codeImgUrl["req_url"] = codeImgUrl["req_url"].format(random.random())
else:
codeImgUrl = copy.deepcopy(session.urls["codeImgByOrder"])
codeImgUrl["req_url"] = codeImgUrl["req_url"].format(random.random())
print(u"下载验证码...")
img_path = './tkcode.png'
codeImgUrlRsp = session.httpClint.send(codeImgUrl)
if not isinstance(codeImgUrlRsp, str):
print("验证码获取失败")
return
result = eval(codeImgUrlRsp.split("(")[1].split(")")[0]).get("image")
try:
if isinstance(result, dict):
print(u"下载验证码失败, 请手动检查是否ip被封或者重试请求地址https://kyfw.12306.cn{}".format(codeImgUrl.get("req_url")))
return False
else:
print(u"下载验证码成功")
try:
with open(img_path, 'wb', encoding="utf-8") as img:
img.write(result)
except Exception:
with open(img_path, 'wb') as img:
img.write(base64.b64decode(result))
return result
except OSError:
print(u"验证码下载失败可能ip被封或者文件写入没权限")
if __name__ == '__main__':
pass

@ -1,123 +0,0 @@
# coding=utf-8
import json
from config.TicketEnmu import ticket
from myException.PassengerUserException import PassengerUserException
import wrapcache
import TickerConfig
class getPassengerDTOs:
"""
获取乘客信息
:return:
"""
def __init__(self, selectObj, ticket_peoples=None, set_type=None, is_more_ticket_num=None):
"""
:param session: 登录实例
:param ticket_peoples: 乘客
:param set_type: 坐席
"""
if ticket_peoples is None:
ticket_peoples = []
self.session = selectObj
self.ticket_peoples = ticket_peoples
self.is_more_ticket_num = is_more_ticket_num
self.set_type = set_type
def sendGetPassengerDTOs(self):
getPassengerDTOsResult = self.session.httpClint.send(self.session.urls["get_passengerDTOs"], json.dumps({"_json_att": ""}))
if getPassengerDTOsResult.get("data", False) and getPassengerDTOsResult["data"].get("normal_passengers", False):
normal_passengers = getPassengerDTOsResult['data']['normal_passengers']
_normal_passenger = [normal_passengers[i] for i in range(len(normal_passengers)) if
normal_passengers[i]["passenger_name"] in self.ticket_peoples]
return _normal_passenger if _normal_passenger else [normal_passengers[0]] # 如果配置乘车人没有在账号,则默认返回第一个用户
else:
if getPassengerDTOsResult.get("data", False) and getPassengerDTOsResult['data'].get("exMsg", False):
print(getPassengerDTOsResult['data'].get("exMsg", False))
elif getPassengerDTOsResult.get('messages', False):
print(getPassengerDTOsResult.get('messages', False))
else:
print(u"警告:您的账号可能买票有问题,获取不到联系人,请测试是否能正常下单,在捡漏或者购票!!!")
print(u"警告:您的账号可能买票有问题,获取不到联系人,请测试是否能正常下单,在捡漏或者购票!!!")
print(u"警告:您的账号可能买票有问题,获取不到联系人,请测试是否能正常下单,在捡漏或者购票!!!")
# raise PassengerUserException(ticket.DTO_NOT_FOUND)
def getPassengerTicketStr(self, set_type):
"""
获取getPassengerTicketStr 提交对应的代号码
:param str: 坐席
:return:
"""
passengerTicketStr = {
'一等座': 'M',
'特等座': 'P',
'二等座': 'O',
'商务座': 9,
'硬座': 1,
'无座': 1,
'软座': 2,
'软卧': 4,
'硬卧': 3,
}
return str(passengerTicketStr[set_type.replace(' ', '')])
def getPassengerTicketStrListAndOldPassengerStr(self, secretStr, secretList):
"""
获取提交车次人内容格式
passengerTicketStr O,0,1,文贤平,1,43052419950223XXXX,15618715583,N_O,0,1,梁敏,1,43052719920118XXXX,,N
oldPassengerStr 文贤平,1,43052719920118XXXX,1_梁敏,1,43052719920118XXXX,1
ps: 如果is_more_ticket打开了的话那就是读取联系人列表里面前符合车次数量的前几个联系人
:return:
"""
passengerTicketStrList = []
oldPassengerStr = []
tickers = []
set_type = ""
if wrapcache.get("user_info"): # 如果缓存中有联系人方式,则读取缓存中的联系人
user_info = wrapcache.get("user_info")
print(u"使用缓存中查找的联系人信息")
else:
user_info = self.sendGetPassengerDTOs()
wrapcache.set("user_info", user_info, timeout=9999999)
if not user_info:
raise PassengerUserException(ticket.DTO_NOT_IN_LIST)
if len(user_info) < self.is_more_ticket_num: # 如果乘车人填错了导致没有这个乘车人的话,可能乘车人数会小于自动乘车人
self.is_more_ticket_num = len(user_info)
if secretStr:
set_type = self.getPassengerTicketStr(self.set_type)
if self.is_more_ticket_num is 1:
passengerTicketStrList.append(
'0,' + user_info[0]['passenger_type'] + "," + user_info[0][
"passenger_name"] + "," +
user_info[0]['passenger_id_type_code'] + "," + user_info[0]['passenger_id_no'] + "," +
user_info[0]['mobile_no'] + ',N,' + user_info[0]["allEncStr"])
oldPassengerStr.append(
user_info[0]['passenger_name'] + "," + user_info[0]['passenger_id_type_code'] + "," +
user_info[0]['passenger_id_no'] + "," + user_info[0]['passenger_type'] + '_')
else:
for i in range(self.is_more_ticket_num):
passengerTicketStrList.append(
'0,' + user_info[i]['passenger_type'] + "," + user_info[i][
"passenger_name"] + "," + user_info[i]['passenger_id_type_code'] + "," + user_info[i][
'passenger_id_no'] + "," + user_info[i]['mobile_no'] + ',N,' + user_info[i]["allEncStr"] + '_' + set_type)
oldPassengerStr.append(
user_info[i]['passenger_name'] + "," + user_info[i]['passenger_id_type_code'] + "," +
user_info[i]['passenger_id_no'] + "," + user_info[i]['passenger_type'] + '_')
elif secretList:
"""
候补订单有多少个联系人就候补多少个联系人了没有优先提交之说
1#XXXX#1#***************77X#bf6ae40d3655ae7eff005ee21d95876b38ab97a8031b464bc2f74a067e3ec957;
"""
for user in user_info:
tickers.append(f"1#{user['passenger_name']}#1#{user['passenger_id_no']}#{user['allEncStr']};")
return {
"passengerTicketStrList": set_type + "," + ",".join(passengerTicketStrList),
"passengerTicketStrByAfterLate": "".join(tickers),
"oldPassengerStr": "".join(oldPassengerStr),
"code": ticket.SUCCESS_CODE,
"set_type": set_type,
"status": True,
"user_info": user_info,
}

@ -1,149 +0,0 @@
# coding=utf-8
import datetime
import sys
import time
from collections import OrderedDict
import wrapcache
import TickerConfig
from config.TicketEnmu import ticket
from config.emailConf import sendEmail
from config.serverchanConf import sendServerChan
from config.urlConf import urls
from inter.ConfirmSingleForQueue import confirmSingleForQueue
from myException.ticketIsExitsException import ticketIsExitsException
def conversion_int(str):
return int(str)
class getQueueCount:
def __init__(self, session, is_need_code, ifShowPassCodeTime, set_type, station_dates, train_no, ticket_peoples,
ticketInfoForPassengerForm, token, oldPassengerStr, passengerTicketStrList):
self.station_dates = station_dates
self.session = session
self.is_need_code = is_need_code
self.ifShowPassCodeTime = ifShowPassCodeTime
self.set_type = set_type
self.train_no = train_no
self.ticket_peoples = ticket_peoples
self.ticket_black_list = {}
self.ticketInfoForPassengerForm = ticketInfoForPassengerForm
self.token = token
self.oldPassengerStr = oldPassengerStr
self.passengerTicketStrList = passengerTicketStrList
def data_par(self):
"""
参数结构
自动提交代码接口-autoSubmitOrderRequest
- 字段说明
- secretStr 车票代码
- train_date 乘车日期
- tour_flag 乘车类型
- purpose_codes 学生还是成人
- query_from_station_name 起始车站
- query_to_station_name 结束车站
- cancel_flag 默认2我也不知道干嘛的
- bed_level_order_num 000000000000000000000000000000
- passengerTicketStr 乘客乘车代码
- oldPassengerStr 乘客编号代码
:return:
"""
if sys.version_info.major is 2:
new_train_date = filter(None, str(time.asctime(time.strptime(self.station_dates, "%Y-%m-%d"))).split(" "))
else:
new_train_date = list(filter(None, str(time.asctime(time.strptime(self.station_dates, "%Y-%m-%d"))).split(" ")))
data = OrderedDict()
data['train_date'] = "{0} {1} {2} {3} 00:00:00 GMT+0800 (中国标准时间)".format(
new_train_date[0],
new_train_date[1],
new_train_date[2] if len(new_train_date[2]) is 2 else f"0{new_train_date[2]}",
new_train_date[4],
),
data['train_no'] = self.ticketInfoForPassengerForm['queryLeftTicketRequestDTO']['train_no'],
data['stationTrainCode'] = self.ticketInfoForPassengerForm['queryLeftTicketRequestDTO'][
'station_train_code'],
data['seatType'] = self.set_type,
data['fromStationTelecode'] = self.ticketInfoForPassengerForm['queryLeftTicketRequestDTO'][
'from_station'],
data['toStationTelecode'] = self.ticketInfoForPassengerForm['queryLeftTicketRequestDTO']['to_station'],
data['leftTicket'] = self.ticketInfoForPassengerForm['leftTicketStr'],
data['purpose_codes'] = self.ticketInfoForPassengerForm['purpose_codes'],
data['train_location'] = self.ticketInfoForPassengerForm['train_location'],
data['REPEAT_SUBMIT_TOKEN'] = self.token,
return data
def sendGetQueueCount(self):
"""
# 模拟查询当前的列车排队人数的方法
# 返回信息组成的提示字符串
:return:
"""
getQueueCountResult = self.session.httpClint.send(self.session.urls["getQueueCountUrl"], self.data_par())
if "status" in getQueueCountResult and getQueueCountResult["status"] is True:
if "countT" in getQueueCountResult["data"]:
ticket = getQueueCountResult["data"]["ticket"]
ticket_split = sum(map(conversion_int, ticket.split(","))) if ticket.find(",") != -1 else ticket
countT = getQueueCountResult["data"]["countT"]
if int(ticket_split) is 0:
wrapcache.set(key=self.train_no, value=datetime.datetime.now(),
timeout=TickerConfig.TICKET_BLACK_LIST_TIME * 60)
print(f"排队失败,当前余票数还剩: {ticket_split}")
return
print(u"排队成功, 你排在: {1}位, 当前余票还剩余: {0}".format(ticket_split, countT))
csf = confirmSingleForQueue(self.session, self.ifShowPassCodeTime, self.is_need_code, self.token,
self.set_type, self.ticket_peoples, self.ticketInfoForPassengerForm,
self.oldPassengerStr, self.passengerTicketStrList)
csf.sendConfirmSingleForQueue()
# else:
# print(u"当前排队人数: {1} 当前余票还剩余:{0} 张,继续排队中".format(ticket_split, countT))
else:
print(u"排队发现未知错误{0},将此列车 {1}加入小黑屋".format(getQueueCountResult, self.train_no))
wrapcache.set(key=self.train_no, value=datetime.datetime.now(),
timeout=TickerConfig.TICKET_BLACK_LIST_TIME * 60)
elif "messages" in getQueueCountResult and getQueueCountResult["messages"]:
print(u"排队异常,错误信息:{0}, 将此列车 {1}加入小黑屋".format(getQueueCountResult["messages"][0], self.train_no))
wrapcache.set(key=self.train_no, value=datetime.datetime.now(),
timeout=TickerConfig.TICKET_BLACK_LIST_TIME * 60)
else:
if "validateMessages" in getQueueCountResult and getQueueCountResult["validateMessages"]:
print(str(getQueueCountResult["validateMessages"]))
wrapcache.set(key=self.train_no, value=datetime.datetime.now(),
timeout=TickerConfig.TICKET_BLACK_LIST_TIME * 60)
else:
print(u"未知错误 {0}".format("".join(getQueueCountResult)))
class queryQueueByAfterNate:
def __init__(self, session):
"""
候补排队
:param session:
"""
self.session = session
def sendQueryQueueByAfterNate(self):
for i in range(10):
queryQueueByAfterNateRsp = self.session.httpClint.send(urls.get("queryQueue"))
if not queryQueueByAfterNateRsp.get("status"):
print("".join(queryQueueByAfterNateRsp.get("messages")) or queryQueueByAfterNateRsp.get("validateMessages"))
time.sleep(1)
else:
sendEmail(ticket.WAIT_ORDER_SUCCESS)
sendServerChan(ticket.WAIT_ORDER_SUCCESS)
raise ticketIsExitsException(ticket.WAIT_AFTER_NATE_SUCCESS)
if __name__ == '__main__':
new_train_date = list(filter(None, str(time.asctime(time.strptime("2019-10-07", "%Y-%m-%d"))).split(" ")))
print(new_train_date)
train_date = "{0} {1} {2} {3} 00:00:00 GMT+0800 (中国标准时间)".format(
new_train_date[0],
new_train_date[1],
new_train_date[2] if len(new_train_date[2]) is 2 else f"0{new_train_date[2]}",
new_train_date[4],
)
print(train_date)

@ -1,126 +0,0 @@
import TickerConfig
[]# coding=utf-8
import datetime
import sys
import time
from collections import OrderedDict
import wrapcache
from inter.ConfirmSingleForQueueAsys import confirmSingleForQueueAsys
class getQueueCountAsync:
"""
排队
"""
def __init__(self,
session,
train_no,
stationTrainCode,
fromStationTelecode,
toStationTelecode,
leftTicket,
set_type,
users,
station_dates,
passengerTicketStr,
oldPassengerStr,
result,
ifShowPassCodeTime):
self.train_no = train_no
self.session = session
self.stationTrainCode = stationTrainCode
self.fromStationTelecode = fromStationTelecode
self.toStationTelecode = toStationTelecode
self.set_type = set_type
self.leftTicket = leftTicket
self.users = users
self.station_dates = station_dates
self.passengerTicketStr = passengerTicketStr
self.oldPassengerStr = oldPassengerStr
self.result = result
self.ifShowPassCodeTime=ifShowPassCodeTime
def data_par(self):
"""
- 字段说明
- train_date 时间
- train_no 列车编号,查询代码里面返回
- stationTrainCode 列车编号
- seatType 对应坐席
- fromStationTelecode 起始城市
- toStationTelecode 到达城市
- leftTicket 查询代码里面返回
- purpose_codes 学生还是成人
- _json_att 没啥卵用还是带上吧
:return:
"""
if sys.version_info.major is 2:
new_train_date = filter(None, str(time.asctime(time.strptime(self.station_dates, "%Y-%m-%d"))).split(" "))
else:
new_train_date = list(filter(None, str(time.asctime(time.strptime(self.station_dates, "%Y-%m-%d"))).split(" ")))
data = OrderedDict()
data['train_date'] = "{0} {1} {2} {3} 00:00:00 GMT+0800 (中国标准时间)".format(
new_train_date[0],
new_train_date[1],
new_train_date[2] if len(new_train_date[2]) is 2 else f"0{new_train_date[2]}",
new_train_date[4],
time.strftime("%H:%M:%S", time.localtime(time.time()))
),
data["train_no"] = self.train_no
data["stationTrainCode"] = self.stationTrainCode
data["seatType"] = self.set_type
data["fromStationTelecode"] = self.fromStationTelecode
data["toStationTelecode"] = self.toStationTelecode
data["leftTicket"] = self.leftTicket
data["purpose_codes"] = "ADULT"
data["_json_att"] = ""
return data
def conversion_int(self, str):
return int(str)
def sendGetQueueCountAsync(self):
"""
请求排队接口
:return:
"""
urls = self.session.urls["getQueueCountAsync"]
data = self.data_par()
getQueueCountAsyncResult = self.session.httpClint.send(urls, data)
if getQueueCountAsyncResult.get("status", False) and getQueueCountAsyncResult.get("data", False):
if "status" in getQueueCountAsyncResult and getQueueCountAsyncResult["status"] is True:
if "countT" in getQueueCountAsyncResult["data"]:
ticket_data = getQueueCountAsyncResult["data"]["ticket"]
ticket_split = sum(map(self.conversion_int, ticket_data.split(","))) if ticket_data.find(
",") != -1 else ticket_data
if int(ticket_split) is 0:
# 增加余票数为0时将车次加入小黑屋
wrapcache.set(key=self.train_no, value=datetime.datetime.now(),
timeout=TickerConfig.TICKET_BLACK_LIST_TIME * 60)
print(f"排队失败,当前余票数为{ticket_split}")
return
print(u"排队成功, 当前余票还剩余: {0}".format(ticket_split))
c = confirmSingleForQueueAsys(session=self.session,
passengerTicketStr=self.passengerTicketStr,
oldPassengerStr=self.oldPassengerStr,
result=self.result,)
print(u"验证码提交安全期,等待{}MS".format(self.ifShowPassCodeTime))
time.sleep(self.ifShowPassCodeTime)
c.sendConfirmSingleForQueueAsys()
else:
print(u"排队发现未知错误{0},将此列车 {1}加入小黑屋".format(getQueueCountAsyncResult, self.train_no))
wrapcache.set(key=self.train_no, value=datetime.datetime.now(),
timeout=TickerConfig.TICKET_BLACK_LIST_TIME * 60)
elif "messages" in getQueueCountAsyncResult and getQueueCountAsyncResult["messages"]:
print(u"排队异常,错误信息:{0}, 将此列车 {1}加入小黑屋".format(getQueueCountAsyncResult["messages"][0], self.train_no))
wrapcache.set(key=self.train_no, value=datetime.datetime.now(),
timeout=TickerConfig.TICKET_BLACK_LIST_TIME * 60)
else:
if "validateMessages" in getQueueCountAsyncResult and getQueueCountAsyncResult["validateMessages"]:
print(str(getQueueCountAsyncResult["validateMessages"]))

@ -1,98 +0,0 @@
# coding=utf-8
from PIL import Image
from config.urlConf import urls
from myUrllib.httpUtils import HTTPClient
from verify.localVerifyCode import Verify
import TickerConfig
import os
if TickerConfig.AUTO_CODE_TYPE == 2:
v = Verify()
def getRandCode(is_auto_code, auto_code_type, result):
"""
识别验证码
:return: 坐标
"""
try:
if is_auto_code:
if auto_code_type == 1:
print(u"打码兔已关闭, 如需使用自动识别,请使用如果平台 auto_code_type == 2")
return
elif auto_code_type == 2:
Result = v.verify(result)
return codexy(Ofset=Result, is_raw_input=False)
elif auto_code_type == 3:
print("您已设置使用云打码,但是服务器资源有限,请尽快改为本地打码" if "CAPTCHALOCAL" not in os.environ else "已设置本地打码服务器")
http = HTTPClient(0)
Result = http.send(urls.get("autoVerifyImage"), {"imageFile": result})
if Result and Result.get("code") is 0:
return codexy(Ofset=Result.get("data"), is_raw_input=False)
else:
img = Image.open('./tkcode.png')
img.show()
return codexy()
except Exception as e:
print(e)
def codexy(Ofset=None, is_raw_input=True):
"""
获取验证码
:return: str
"""
if is_raw_input:
print(u"""
*****************
| 1 | 2 | 3 | 4 |
*****************
| 5 | 6 | 7 | 8 |
*****************
""")
print(u"验证码分为8个对应上面数字例如第一和第二张输入1, 2 如果开启cdn查询的话会冲掉提示直接鼠标点击命令行获取焦点输入即可不要输入空格")
print(u"如果是linux无图形界面请使用自动打码is_auto_code: True")
print(u"如果没有弹出验证码请手动双击根目录下的tkcode.png文件")
Ofset = input(u"输入对应的验证码: ")
if isinstance(Ofset, list):
select = Ofset
else:
Ofset = Ofset.replace("", ",")
select = Ofset.split(',')
post = []
offsetsX = 0 # 选择的答案的left值,通过浏览器点击8个小图的中点得到的,这样基本没问题
offsetsY = 0 # 选择的答案的top值
for ofset in select:
if ofset == '1':
offsetsY = 77
offsetsX = 40
elif ofset == '2':
offsetsY = 77
offsetsX = 112
elif ofset == '3':
offsetsY = 77
offsetsX = 184
elif ofset == '4':
offsetsY = 77
offsetsX = 256
elif ofset == '5':
offsetsY = 149
offsetsX = 40
elif ofset == '6':
offsetsY = 149
offsetsX = 112
elif ofset == '7':
offsetsY = 149
offsetsX = 184
elif ofset == '8':
offsetsY = 149
offsetsX = 256
else:
pass
post.append(offsetsX)
post.append(offsetsY)
randCode = str(post).replace(']', '').replace('[', '').replace("'", '').replace(' ', '')
print(u"验证码识别坐标为{0}".format(randCode))
return randCode

@ -1,36 +0,0 @@
# coding=utf-8
import json
import re
class getRepeatSubmitToken:
def __init__(self, session):
self.session = session
def sendGetRepeatSubmitToken(self):
"""
获取提交车票请求token
:return: token
"""
initdc_url = self.session.urls["initdc_url"]
initdc_result = self.session.httpClint.send(initdc_url, )
token_name = re.compile(r"var globalRepeatSubmitToken = '(\S+)'")
ticketInfoForPassengerForm_name = re.compile(r'var ticketInfoForPassengerForm=(\{.+\})?')
order_request_params_name = re.compile(r'var orderRequestDTO=(\{.+\})?')
token = re.search(token_name, initdc_result).group(1)
re_tfpf = re.findall(ticketInfoForPassengerForm_name, initdc_result)
re_orp = re.findall(order_request_params_name, initdc_result)
if re_tfpf:
ticketInfoForPassengerForm = json.loads(re_tfpf[0].replace("'", '"'))
else:
ticketInfoForPassengerForm = ""
if re_orp:
order_request_params = json.loads(re_orp[0].replace("'", '"'))
else:
order_request_params = ""
return {
"token": token,
"ticketInfoForPassengerForm": ticketInfoForPassengerForm,
"order_request_params": order_request_params,
"session": self.session
}

@ -1,41 +0,0 @@
from collections import OrderedDict
from config.urlConf import urls
import TickerConfig
from inter.SubmitOrderRequest import submitOrderRequestByAfterNate
class getSuccessRate:
def __init__(self, session, secretList):
"""
获取成功信息
"""
self.secretList = secretList
self.session = session
def data_apr(self):
"""
secretList 9vqa9%2B%2F%2Fsdozmm22hpSeDTGqRUwSuA2D0r%2BmU%2BLZj7MK7CDuf5Ep1xpxl4Dyxfmoah%2BaB9TZSesU%0AkxBbo5oNgR1vqMfvq66VP0T7tpQtH%2BbVGBz1FolZG8jDD%2FHqnz%2FnvdBP416Og6WGS14O%2F3iBSwT8%0AkRPsNF0Vq0U082g0tlJtP%2BPn7TzW3z7TDCceMJIjFcfEOA%2BW%2BuK%2Bpy6jCQMv0TmlkXf5aKcGnE02%0APuv4I8nF%2BOWjWzv9CrJyiCZiWaXd%2Bi7p69V3a9dhF787UgS660%2BqKRFB4RLwAfic3MkAlfpGWhMY%0ACfARVQ%3D%3D#O
_json_att
候补一次只能补一个座位默认取TICKET_TYPE第一个
:return:
"""
ticker = TickerConfig.PASSENGER_TICKER_STR.get(TickerConfig.SET_TYPE[0])
data = OrderedDict()
data["successSecret"] = f"{self.secretList}#{ticker}"
data["_json_att"] = ""
return data
def sendSuccessRate(self):
successRateRsp = self.session.httpClint.send(urls.get("getSuccessRate"), self.data_apr())
if not successRateRsp.get("status"):
print("".join(successRateRsp.get("messages")) or successRateRsp.get("validateMessages"))
return
flag = successRateRsp.get("data", {}).get("flag")[0]
train_no = flag.get("train_no")
print(f"准备提交候补订单,{flag.get('info')}")
submit = submitOrderRequestByAfterNate(self.session, self.secretList, train_no)
submit.sendSubmitOrderRequest()

@ -1,24 +0,0 @@
# coding=utf-8
import re
class liftTicketInit:
def __init__(self, session):
self.session = session
def reqLiftTicketInit(self):
"""
请求抢票页面
:return:
"""
urls = self.session.urls["left_ticket_init"]
# 获取初始化的结果
result = self.session.httpClint.send(urls)
# 用正则表达式查出CLeftTicketUrl的值
matchObj = re.search('var CLeftTicketUrl = \'(.*)\'', result, re.M|re.I);
if matchObj:
# 如果有值替换queryUrl
self.session.queryUrl = matchObj.group(1)
return {
"status": True
}

@ -1,20 +0,0 @@
# coding=utf-8
from config.urlConf import urls
def loginAysnSuggest(session, username, password):
"""
登录接口
ps: 不需要验证码
:return:
"""
loginAysnSuggestUrls = urls.get("loginAysnSuggest")
data = {
"loginUserDTO.user_name": username,
"userDTO.password": password
}
loginAysnSuggestRsp = session.httpClint.send(urls=loginAysnSuggestUrls, data=data)
if loginAysnSuggestRsp and loginAysnSuggestRsp.get("httpstatus") is 200 and loginAysnSuggestRsp.get("data", {}).get("loginCheck") == "Y":
print(u"登录成功")
else:
print(u"登录失败, {0} {1}".format("".join(loginAysnSuggestRsp.get("messages")), loginAysnSuggestRsp.get("validateMessages")))

@ -1,22 +0,0 @@
# coding=utf-8
from config.urlConf import urls
def loginConf(session):
"""
判断登录是否需要验证码
:param session:
:return:
"""
loginConfUrl = urls.get("loginConf")
loginConfRsp = session.httpClint.send(urls=loginConfUrl, data={})
if loginConfRsp and loginConfRsp.get("data", {}).get("is_login_passCode") == "N":
print(u"不需要验证码")
return False
else:
print(u"需要验证码")
return True
if __name__ == '__main__':
pass

@ -1,37 +0,0 @@
import datetime
import wrapcache
import TickerConfig
from config.urlConf import urls
from inter.ConfirmHB import confirmHB
class passengerInitApi:
def __init__(self, session, secretList, tickerNo):
"""
获取候补信息
"""
self.secretList = secretList
self.tickerNo = tickerNo
self.session = session
def sendPassengerInitApi(self):
passengerInitApiRsp = self.session.httpClint.send(urls.get("passengerInitApi"))
if not passengerInitApiRsp.get("status"):
print("".join(passengerInitApiRsp.get("messages")) or passengerInitApiRsp.get("validateMessages"))
return
data = passengerInitApiRsp.get("data", {})
jzdhDateE = data.get("jzdhDateE")
if not data.get("jzdhHourE"):
wrapcache.set(key=f"hb{self.tickerNo}", value=datetime.datetime.now(),
timeout=TickerConfig.TICKET_BLACK_LIST_TIME * 60)
print(f"获取当前候补日期失败,原因: {data.get('jzdhHourE')}")
return
jzdhHourE = data.get("jzdhHourE").replace(":", "#")
jzdhDate = f"{jzdhDateE}#{jzdhHourE}"
print(f"当前候补日期为:{jzdhDateE} {jzdhHourE}")
confirm = confirmHB(self.secretList, self.session, self.tickerNo, jzdhDate)
confirm.sendChechFace()

@ -1,189 +0,0 @@
# coding=utf-8
import copy
import random
import wrapcache
from config import urlConf
from config.TicketEnmu import ticket
from myUrllib.httpUtils import HTTPClient
from config.configCommon import seat_conf_2
import TickerConfig
class query:
"""
查询接口
"""
def __init__(self, selectObj, from_station, to_station, from_station_h, to_station_h, _station_seat, station_trains,
ticke_peoples_num, station_dates=None, ):
self.session = selectObj
self.httpClint = HTTPClient(TickerConfig.IS_PROXY)
self.httpClint.set_cookies(self.session.cookies)
self.urls = urlConf.urls
self.from_station = from_station
self.to_station = to_station
self.from_station_h = from_station_h
self.to_station_h = to_station_h
self.station_trains = station_trains
self._station_seat = _station_seat if isinstance(_station_seat, list) else list(_station_seat)
self.station_dates = station_dates if isinstance(station_dates, list) else list(station_dates)
self.ticket_black_list = dict()
self.ticke_peoples_num = ticke_peoples_num
def station_seat(self, index):
"""
获取车票对应坐席
:return:
"""
seat = {'商务座': 32,
'一等座': 31,
'二等座': 30,
'特等座': 25,
'软卧': 23,
'硬卧': 28,
'硬座': 29,
'无座': 26,
'动卧': 33,
}
return seat[index]
def check_is_need_train(self, ticket_info):
"""
判断车次是否为想要的车次如果ticket_info为空那么就不校验车次直接返回True
:param ticket_info:
:return:
"""
if self.station_dates and self.station_trains:
return ticket_info[3] in self.station_trains
else:
return True
def sendQuery(self):
"""
查询
:return:
"""
if TickerConfig.IS_CDN == 1 and self.session.cdn_list:
self.httpClint.cdn = self.session.cdn_list[random.randint(4, len(self.session.cdn_list) - 1)]
for station_date in self.station_dates:
select_url = copy.copy(self.urls["select_url"])
select_url["req_url"] = select_url["req_url"].format(station_date, self.from_station, self.to_station,
self.session.queryUrl)
station_ticket = self.httpClint.send(select_url)
value = station_ticket.get("data", "")
if not value:
print(u'{0}-{1} 车次坐席查询为空查询url: https://kyfw.12306.cn{2}, 可以手动查询是否有票'.format(
self.from_station_h,
self.to_station_h,
select_url["req_url"]))
else:
result = value.get('result', [])
if result:
for i in value['result']:
ticket_info = i.split('|')
if self.session.flag:
print(f"车次:{ticket_info[3]} 出发站:{self.from_station_h} 到达站:{self.to_station_h} 历时:{ticket_info[10]}"
f" 商务/特等座:{ticket_info[32] or '--'}"
f" 一等座:{ticket_info[31] or '--'}"
f" 二等座:{ticket_info[30] or '--'}"
f" 动卧:{ticket_info[33] or '--'}"
f" 硬卧:{ticket_info[28] or '--'}"
f" 软座:{ticket_info[23] or '--'}"
f" 硬座:{ticket_info[29] or '--'}"
f" 无座:{ticket_info[26] or '--'}"
f" {ticket_info[1] or '--'}")
if ticket_info[1] == "预订" and self.check_is_need_train(ticket_info): # 筛选未在开始时间内的车次
for j in self._station_seat:
is_ticket_pass = ticket_info[j]
if ticket_info[11] == "Y":
if is_ticket_pass != '' and is_ticket_pass != '' and is_ticket_pass != '*': # 过滤有效目标车次
secretStr = ticket_info[0]
train_no = ticket_info[2]
query_from_station_name = ticket_info[6]
query_to_station_name = ticket_info[7]
train_location = ticket_info[15]
stationTrainCode = ticket_info[3]
leftTicket = ticket_info[12]
start_time = ticket_info[8]
arrival_time = ticket_info[9]
distance_time = ticket_info[10]
print(start_time, arrival_time, distance_time)
seat = j
try:
ticket_num = int(ticket_info[j])
except ValueError:
ticket_num = ""
print(u'车次: {0} 始发车站: {1} 终点站: {2} {3}: {4}'.format(ticket_info[3],
self.from_station_h,
self.to_station_h,
seat_conf_2[j],
ticket_num))
if seat_conf_2[j] == "无座" and ticket_info[3][0] in ["G", "D", "C"]:
seat = 30 # GD开头的无座直接强制改为二等座车次
if wrapcache.get(train_no):
print(ticket.QUERY_IN_BLACK_LIST.format(train_no))
continue
else:
if ticket_num != "" and self.ticke_peoples_num > ticket_num:
if TickerConfig.IS_MORE_TICKET:
print(
u"余票数小于乘车人数,当前余票数: {}, 删减人车人数到: {}".format(ticket_num, ticket_num))
is_more_ticket_num = ticket_num
else:
print(u"余票数小于乘车人数,当前设置不提交,放弃此次提交机会")
continue
else:
print(u"设置乘车人数为: {}".format(self.ticke_peoples_num))
is_more_ticket_num = self.ticke_peoples_num
print(ticket.QUERY_C)
return {
"secretStr": secretStr,
"train_no": train_no,
"stationTrainCode": stationTrainCode,
"train_date": station_date,
"query_from_station_name": query_from_station_name,
"query_to_station_name": query_to_station_name,
"seat": seat,
"leftTicket": leftTicket,
"train_location": train_location,
"code": ticket.SUCCESS_CODE,
"is_more_ticket_num": is_more_ticket_num,
"cdn": self.httpClint.cdn,
"status": True,
}
elif is_ticket_pass == '' and ticket_info[37] == "1" and TickerConfig.TICKET_TYPE is 2:
"""
is_ticket_pass如果有别的显示但是可以候补可以提issues提出来附上query log我将添加上
判断车次是否可以候补
目前的候补机制是只要一有候补位置立马提交候补
"""
# 如果最后一位为1则是可以候补的不知道这些正确嘛
nate = list(ticket_info[38])
if wrapcache.get(f"hb{ticket_info[2]}"):
continue
for set_type in TickerConfig.SET_TYPE:
if TickerConfig.PASSENGER_TICKER_STR[set_type] not in nate:
if ticket_info[3][0] in ["G", "D", "C"] and set_type in ["一等座", "特等座", "二等座", "商务座", "无座"]:
return {
"secretList": ticket_info[0],
"seat": [set_type],
"train_no": ticket_info[2],
"status": True,
"cdn": self.httpClint.cdn,
}
elif ticket_info[3][0] in ["T", "Z", "K"] and set_type in ["硬卧", "硬座", "无座", "软座", "软卧"]:
return {
"secretList": ticket_info[0],
"seat": [set_type],
"train_no": ticket_info[2],
"status": True,
"cdn": self.httpClint.cdn,
}
else:
print(u"车次配置信息有误,或者返回数据异常,请检查 {}".format(station_ticket))
self.session.flag = False
return {"code": ticket.FAIL_CODE, "status": False, "cdn": self.httpClint.cdn, }
if __name__ == "__main__":
q = query()

@ -1,125 +0,0 @@
# coding=utf-8
import copy
import time
from config.TicketEnmu import ticket
from config.emailConf import sendEmail
from config.serverchanConf import sendServerChan
from myException.ticketIsExitsException import ticketIsExitsException
from myException.ticketNumOutException import ticketNumOutException
class queryOrderWaitTime:
"""
排队
"""
def __init__(self, session):
self.session = session
def sendQueryOrderWaitTime(self):
"""
排队获取订单等待信息,每隔3秒请求一次最高请求次数为20次
:return:
"""
num = 1
while True:
num += 1
if num > ticket.OUT_NUM:
print(ticket.WAIT_OUT_NUM)
order_id = self.queryMyOrderNoComplete() # 排队失败,自动取消排队订单
if order_id:
self.cancelNoCompleteMyOrder(order_id)
break
try:
queryOrderWaitTimeUrl = copy.deepcopy(self.session.urls["queryOrderWaitTimeUrl"])
queryOrderWaitTimeUrl["req_url"] = queryOrderWaitTimeUrl["req_url"].format(int(round(time.time() * 1000)))
queryOrderWaitTimeResult = self.session.httpClint.send(queryOrderWaitTimeUrl)
except ValueError:
queryOrderWaitTimeResult = {}
if queryOrderWaitTimeResult:
if queryOrderWaitTimeResult.get("status", False):
data = queryOrderWaitTimeResult.get("data", False)
if data and data.get("orderId", ""):
sendEmail(ticket.WAIT_ORDER_SUCCESS.format(
data.get("orderId", "")))
sendServerChan(ticket.WAIT_ORDER_SUCCESS.format(
data.get("orderId", "")))
raise ticketIsExitsException(ticket.WAIT_ORDER_SUCCESS.format(
data.get("orderId")))
elif data.get("msg", False):
print(data.get("msg", ""))
break
elif data.get("waitTime", False):
print(ticket.WAIT_ORDER_CONTINUE.format(0 - data.get("waitTime", False)))
else:
pass
elif queryOrderWaitTimeResult.get("messages", False):
print(ticket.WAIT_ORDER_FAIL.format(queryOrderWaitTimeResult.get("messages", "")))
else:
print(ticket.WAIT_ORDER_NUM.format(num + 1))
else:
pass
time.sleep(2)
else:
print(ticketNumOutException(ticket.WAIT_ORDER_SUB_FAIL))
def queryMyOrderNoComplete(self):
"""
获取订单列表信息
:return:
"""
self.initNoComplete()
queryMyOrderNoCompleteUrl = self.session.urls["queryMyOrderNoCompleteUrl"]
data = {"_json_att": ""}
try:
queryMyOrderNoCompleteResult = self.session.httpClint.send(queryMyOrderNoCompleteUrl, data)
except ValueError:
queryMyOrderNoCompleteResult = {}
if queryMyOrderNoCompleteResult:
if queryMyOrderNoCompleteResult.get("data", False) and queryMyOrderNoCompleteResult["data"].get("orderDBList", False):
return queryMyOrderNoCompleteResult["data"]
elif queryMyOrderNoCompleteResult.get("data", False) and queryMyOrderNoCompleteResult["data"].get("orderCacheDTO", False):
if queryMyOrderNoCompleteResult["data"]["orderCacheDTO"].get("message", False):
print(queryMyOrderNoCompleteResult["data"]["orderCacheDTO"]["message"]["message"])
raise ticketNumOutException(
queryMyOrderNoCompleteResult["data"]["orderCacheDTO"]["message"]["message"])
else:
if queryMyOrderNoCompleteResult.get("message", False):
print(queryMyOrderNoCompleteResult.get("message", False))
return False
else:
return False
else:
return False
def initNoComplete(self):
"""
获取订单前需要进入订单列表页获取订单列表页session
:return:
"""
initNoCompleteUrl = self.session.urls["initNoCompleteUrl"]
data = {"_json_att": ""}
self.session.httpClint.send(initNoCompleteUrl, data)
def cancelNoCompleteMyOrder(self, sequence_no):
"""
取消订单
:param sequence_no: 订单编号
:return:
"""
cancelNoCompleteMyOrderUrl = self.session.urls["cancelNoCompleteMyOrder"]
cancelNoCompleteMyOrderData = {
"sequence_no": sequence_no,
"cancel_flag": "cancel_order",
"_json_att": ""
}
cancelNoCompleteMyOrderResult = self.session.httpClint.send(cancelNoCompleteMyOrderUrl,
cancelNoCompleteMyOrderData)
if cancelNoCompleteMyOrderResult.get("data", False) and cancelNoCompleteMyOrderResult["data"].get("existError", "N"):
print(ticket.CANCEL_ORDER_SUCCESS.format(sequence_no))
time.sleep(2)
return True
else:
print(ticket.CANCEL_ORDER_FAIL.format(sequence_no))
return False

@ -1,111 +0,0 @@
# coding=utf-8
import datetime
import urllib
from collections import OrderedDict
import TickerConfig
from config.urlConf import urls
from inter.CheckOrderInfo import checkOrderInfo
from inter.ConfirmHB import confirmHB
from inter.PassengerInitApi import passengerInitApi
from myException.ticketIsExitsException import ticketIsExitsException
def time():
"""
获取日期
:return:
"""
today = datetime.date.today()
return today.strftime('%Y-%m-%d')
class submitOrderRequest:
def __init__(self, selectObj, secretStr, from_station, to_station, train_no, set_type,
passengerTicketStrList, oldPassengerStr, train_date, ticke_peoples):
self.session = selectObj
# self.secretStr = secretStr
try:
self.secretStr = urllib.unquote(secretStr)
except AttributeError:
self.secretStr = urllib.parse.unquote(secretStr)
self.from_station = from_station
self.to_station = to_station
self.to_station = to_station
self.train_no = train_no
self.set_type = set_type
self.passengerTicketStrList = passengerTicketStrList
self.oldPassengerStr = oldPassengerStr
self.train_date = train_date
self.ticke_peoples = ticke_peoples
def data_apr(self):
"""
:return:
"""
data = [('secretStr', self.secretStr), # 字符串加密
('train_date', self.train_date), # 出发时间
('back_train_date', time()), # 返程时间
('tour_flag', 'dc'), # 旅途类型
('purpose_codes', 'ADULT'), # 成人票还是学生票
('query_from_station_name', TickerConfig.FROM_STATION), # 起始车站
('query_to_station_name', TickerConfig.TO_STATION), # 终点车站
('undefined', ''),
]
return data
def sendSubmitOrderRequest(self):
"""
提交车次
预定的请求参数注意参数顺序
注意这里为了防止secretStr被urllib.parse过度编码在这里进行一次解码
否则调用HttpTester类的post方法将会将secretStr编码成为无效码,造成提交预定请求失败
:param secretStr: 提交车次加密
:return:
"""
submit_station_url = self.session.urls["submit_station_url"]
submitResult = self.session.httpClint.send(submit_station_url, self.data_apr())
if 'data' in submitResult and submitResult['data']:
if submitResult['data'] == 'N':
coi = checkOrderInfo(self.session, self.train_no, self.set_type, self.passengerTicketStrList,
self.oldPassengerStr,
self.train_date, self.ticke_peoples)
coi.sendCheckOrderInfo()
else:
print (u'出票失败')
elif 'messages' in submitResult and submitResult['messages']:
raise ticketIsExitsException(submitResult['messages'][0])
class submitOrderRequestByAfterNate:
def __init__(self, session, secretList, tickerNo):
"""
提交候补订单
:param secretList:
:param session:
"""
self.secretList = secretList
self.session = session
self.tickerNo = tickerNo
def data_apr(self):
"""
secretList 9vqa9%2B%2F%2Fsdozmm22hpSeDTGqRUwSuA2D0r%2BmU%2BLZj7MK7CDuf5Ep1xpxl4Dyxfmoah%2BaB9TZSesU%0AkxBbo5oNgR1vqMfvq66VP0T7tpQtH%2BbVGBz1FolZG8jDD%2FHqnz%2FnvdBP416Og6WGS14O%2F3iBSwT8%0AkRPsNF0Vq0U082g0tlJtP%2BPn7TzW3z7TDCceMJIjFcfEOA%2BW%2BuK%2Bpy6jCQMv0TmlkXf5aKcGnE02%0APuv4I8nF%2BOWjWzv9CrJyiCZiWaXd%2Bi7p69V3a9dhF787UgS660%2BqKRFB4RLwAfic3MkAlfpGWhMY%0ACfARVQ%3D%3D#O|
_json_att
候补一次只能补一个座位默认取TICKET_TYPE第一个
:return:
"""
ticker = TickerConfig.PASSENGER_TICKER_STR.get(TickerConfig.SET_TYPE[0])
data = OrderedDict()
data["secretList"] = f"{self.secretList}#{ticker}|"
data["_json_att"] = ""
return data
def sendSubmitOrderRequest(self, ):
submitOrderRequestRsp = self.session.httpClint.send(urls.get("SubmitOrderRequestRsp"), self.data_apr())
if not submitOrderRequestRsp.get("status") or not submitOrderRequestRsp.get("data", {}).get("flag"):
print("".join(submitOrderRequestRsp.get("messages")) or submitOrderRequestRsp.get("validateMessages"))
return
pApi = passengerInitApi(self.session, self.secretList, self.tickerNo)
pApi.sendPassengerInitApi()

Binary file not shown.

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

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

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

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

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

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

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

@ -1,204 +0,0 @@
# -*- coding: utf8 -*-
import json
import random
import socket
from collections import OrderedDict
from time import sleep
import requests
from fake_useragent import UserAgent
import TickerConfig
from agency.agency_tools import proxy
from config import logger
def _set_header_default():
header_dict = OrderedDict()
# header_dict["Accept"] = "application/json, text/plain, */*"
header_dict["Accept-Encoding"] = "gzip, deflate"
header_dict[
"User-Agent"] = _set_user_agent()
header_dict["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8"
header_dict["Origin"] = "https://kyfw.12306.cn"
header_dict["Connection"] = "keep-alive"
return header_dict
def _set_user_agent():
# try:
# user_agent = UserAgent(verify_ssl=False).random
# return user_agent
# except:
# print("请求头设置失败,使用默认请求头")
# return 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.' + str(
# random.randint(5000, 7000)) + '.0 Safari/537.36'
return "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
class HTTPClient(object):
def __init__(self, is_proxy, cdnList=None):
"""
cdnList试试切换不包括查询的cdn防止查询cdn污染登陆和下单cdn
:param method:
:param headers: Must be a dict. Such as headers={'Content_Type':'text/html'}
"""
self.initS()
self._cdn = None
self.cdnList = cdnList
self._proxies = None
if is_proxy is 1:
self.proxy = proxy()
self._proxies = self.proxy.setProxy()
# print(u"设置当前代理ip为 {}, 请注意代理ip是否可用请注意代理ip是否可用请注意代理ip是否可用".format(self._proxies))
def initS(self):
self._s = requests.Session()
self._s.headers.update(_set_header_default())
return self
def set_cookies(self, kwargs):
"""
设置cookies
:param kwargs:
:return:
"""
for kwarg in kwargs:
for k, v in kwarg.items():
self._s.cookies.set(k, v)
def get_cookies(self):
"""
获取cookies
:return:
"""
return self._s.cookies.values()
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 setHeaders(self, headers):
self._s.headers.update(headers)
return self
def resetHeaders(self):
self._s.headers.clear()
self._s.headers.update(_set_header_default())
def getHeadersHost(self):
return self._s.headers["Host"]
def setHeadersHost(self, host):
self._s.headers.update({"Host": host})
return self
def setHeadersUserAgent(self):
self._s.headers.update({"User-Agent": _set_user_agent()})
def getHeadersUserAgent(self):
return self._s.headers["User-Agent"]
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.get("is_logger", False)
req_url = urls.get("req_url", "")
re_try = urls.get("re_try", 0)
s_time = urls.get("s_time", 0)
is_cdn = urls.get("is_cdn", False)
is_test_cdn = urls.get("is_test_cdn", False)
error_data = {"code": 99999, "message": u"重试次数达到上限"}
if data:
method = "post"
self.setHeaders({"Content-Length": "{0}".format(len(data))})
else:
method = "get"
self.resetHeaders()
if TickerConfig.RANDOM_AGENT is 1:
self.setHeadersUserAgent()
self.setHeadersReferer(urls["Referer"])
if is_logger:
logger.log(
u"url: {0}\n入参: {1}\n请求方式: {2}\n".format(req_url, data, method))
self.setHeadersHost(urls["Host"])
if is_test_cdn:
url_host = self._cdn
elif is_cdn:
if self._cdn:
# print(u"当前请求cdn为{}".format(self._cdn))
url_host = self._cdn
else:
url_host = urls["Host"]
else:
url_host = urls["Host"]
http = urls.get("httpType") or "https"
for i in range(re_try):
try:
# sleep(urls["s_time"]) if "s_time" in urls else sleep(0.001)
sleep(s_time)
try:
requests.packages.urllib3.disable_warnings()
except:
pass
response = self._s.request(method=method,
timeout=5,
proxies=self._proxies,
url=http + "://" + url_host + req_url,
data=data,
allow_redirects=allow_redirects,
verify=False,
**kwargs)
if response.status_code == 200 or response.status_code == 302:
if urls.get("not_decode", False):
return response.content
if response.content:
if is_logger:
logger.log(
u"出参:{0}".format(response.content.decode()))
if urls["is_json"]:
return json.loads(
response.content.decode() if isinstance(response.content, bytes) else response.content)
else:
return response.content.decode("utf8", "ignore") if isinstance(response.content,
bytes) else response.content
else:
print(f"url: {urls['req_url']}返回参数为空, 接口状态码: {response.status_code}")
logger.log(
u"url: {} 返回参数为空".format(urls["req_url"]))
if self.cdnList:
# 如果下单或者登陆出现cdn 302的情况立马切换cdn
url_host = self.cdnList.pop(random.randint(0, 4))
continue
else:
sleep(urls["re_time"])
except (requests.exceptions.Timeout, requests.exceptions.ReadTimeout, requests.exceptions.ConnectionError):
pass
except socket.error:
pass
return error_data

@ -1,7 +0,0 @@
bs4==0.0.1
requests==2.18.4
Pillow
wrapcache==1.0.8
ntplib==0.3.3
selenium==3.11.0
fake-useragent==0.1.11

@ -1,15 +0,0 @@
beautifulsoup4==4.5.3
bs4==0.0.1
requests==2.18.4
Pillow
wrapcache==1.0.8
ntplib==0.3.3
sklearn
opencv-python
keras==2.2.4
tensorflow==1.14.0
matplotlib>=3.0.2
numpy>=1.14.6
scipy>=1.1.0
selenium==3.11.0
fake-useragent==0.1.11

@ -1,31 +0,0 @@
# -*- coding=utf-8 -*-
import argparse
import sys
def parser_arguments(argv):
"""
不应该在这里定义先放在这里
:param argv:
:return:
"""
parser = argparse.ArgumentParser()
parser.add_argument("operate", type=str, help="r: 运行抢票程序, c: 过滤cdn, t: 测试邮箱和server酱server酱需要打开开关")
return parser.parse_args(argv)
if __name__ == '__main__':
args = parser_arguments(sys.argv[1:])
if args.operate == "r":
from init import select_ticket_info
select_ticket_info.select().main()
elif args.operate == "t":
from config.emailConf import sendEmail
from config.serverchanConf import sendServerChan
sendEmail(u"订票小助手测试一下")
sendServerChan("订票小助手测试一下")
elif args.operate == "c":
from agency.cdn_utils import filterCdn
filterCdn()

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 380 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 223 KiB

@ -1,115 +0,0 @@
# coding: utf-8
import TickerConfig
if TickerConfig.AUTO_CODE_TYPE == 2:
import base64
import os
import cv2
import numpy as np
from keras import models, backend
import tensorflow as tf
from verify import pretreatment
from verify.mlearn_for_image import preprocess_input
graph = tf.get_default_graph()
PATH = lambda p: os.path.abspath(
os.path.join(os.path.dirname(__file__), p)
)
TEXT_MODEL = ""
IMG_MODEL = ""
def get_text(img, offset=0):
text = pretreatment.get_text(img, offset)
text = cv2.cvtColor(text, cv2.COLOR_BGR2GRAY)
text = text / 255.0
h, w = text.shape
text.shape = (1, h, w, 1)
return text
def base64_to_image(base64_code):
# base64解码
img_data = base64.b64decode(base64_code)
# 转换为np数组
img_array = np.fromstring(img_data, np.uint8)
# 转换成opencv可用格式
img = cv2.imdecode(img_array, cv2.COLOR_RGB2BGR)
return img
class Verify:
def __init__(self):
self.textModel = ""
self.imgModel = ""
self.loadImgModel()
self.loadTextModel()
def loadTextModel(self):
if not self.textModel:
self.textModel = models.load_model(PATH('../model.v2.0.h5'))
else:
print("无需加载模型model.v2.0.h5")
def loadImgModel(self):
if not self.imgModel:
self.imgModel = models.load_model(PATH('../12306.image.model.h5'))
def verify(self, fn):
verify_titles = ['打字机', '调色板', '跑步机', '毛线', '老虎', '安全帽', '沙包', '盘子', '本子', '药片', '双面胶', '龙舟', '红酒', '拖把', '卷尺',
'海苔', '红豆', '黑板', '热水袋', '烛台', '钟表', '路灯', '沙拉', '海报', '公交卡', '樱桃', '创可贴', '牌坊', '苍蝇拍', '高压锅',
'电线', '网球拍', '海鸥', '风铃', '订书机', '冰箱', '话梅', '排风机', '锅铲', '绿豆', '航母', '电子秤', '红枣', '金字塔', '鞭炮',
'菠萝', '开瓶器', '电饭煲', '仪表盘', '棉棒', '篮球', '狮子', '蚂蚁', '蜡烛', '茶盅', '印章', '茶几', '啤酒', '档案袋', '挂钟', '刺绣',
'铃铛', '护腕', '手掌印', '锦旗', '文具盒', '辣椒酱', '耳塞', '中国结', '蜥蜴', '剪纸', '漏斗', '', '蒸笼', '珊瑚', '雨靴', '薯条',
'蜜蜂', '日历', '口哨']
# 读取并预处理验证码
img = base64_to_image(fn)
text = get_text(img)
imgs = np.array(list(pretreatment._get_imgs(img)))
imgs = preprocess_input(imgs)
text_list = []
# 识别文字
self.loadTextModel()
global graph
with graph.as_default():
label = self.textModel.predict(text)
label = label.argmax()
text = verify_titles[label]
text_list.append(text)
# 获取下一个词
# 根据第一个词的长度来定位第二个词的位置
if len(text) == 1:
offset = 27
elif len(text) == 2:
offset = 47
else:
offset = 60
text = get_text(img, offset=offset)
if text.mean() < 0.95:
with graph.as_default():
label = self.textModel.predict(text)
label = label.argmax()
text = verify_titles[label]
text_list.append(text)
print("题目为{}".format(text_list))
# 加载图片分类器
self.loadImgModel()
with graph.as_default():
labels = self.imgModel.predict(imgs)
labels = labels.argmax(axis=1)
results = []
for pos, label in enumerate(labels):
l = verify_titles[label]
print(pos + 1, l)
if l in text_list:
results.append(str(pos + 1))
return results
if __name__ == '__main__':
pass
# verify("verify-img1.jpeg")

@ -1,94 +0,0 @@
# coding: utf-8
import TickerConfig
if TickerConfig.AUTO_CODE_TYPE == 2:
import sys
import cv2
import numpy as np
from keras import models
from keras import layers
from keras import optimizers
from keras.applications import VGG16
from keras.callbacks import ReduceLROnPlateau
from keras.preprocessing.image import ImageDataGenerator
def preprocess_input(x):
x = x.astype('float32')
# 我是用cv2来读取的图片其已经是BGR格式了
mean = [103.939, 116.779, 123.68]
x -= mean
return x
def load_data():
# 这是统计学专家提供的训练集
data = np.load('captcha.npz')
train_x, train_y = data['images'], data['labels']
train_x = preprocess_input(train_x)
# 由于是统计得来的信息,所以在此给定可信度
sample_weight = train_y.max(axis=1) / np.sqrt(train_y.sum(axis=1))
sample_weight /= sample_weight.mean()
train_y = train_y.argmax(axis=1)
# 这是人工提供的验证集
data = np.load('captcha.test.npz')
test_x, test_y = data['images'], data['labels']
test_x = preprocess_input(test_x)
return (train_x, train_y, sample_weight), (test_x, test_y)
def learn():
(train_x, train_y, sample_weight), (test_x, test_y) = load_data()
datagen = ImageDataGenerator(horizontal_flip=True,
vertical_flip=True)
train_generator = datagen.flow(train_x, train_y, sample_weight=sample_weight)
base = VGG16(weights='imagenet', include_top=False, input_shape=(None, None, 3))
for layer in base.layers[:-4]:
layer.trainable = False
model = models.Sequential([
base,
layers.BatchNormalization(),
layers.Conv2D(64, (3, 3), activation='relu', padding='same'),
layers.GlobalAveragePooling2D(),
layers.BatchNormalization(),
layers.Dense(64, activation='relu'),
layers.BatchNormalization(),
layers.Dropout(0.20),
layers.Dense(80, activation='softmax')
])
model.compile(optimizer=optimizers.RMSprop(lr=1e-5),
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.summary()
reduce_lr = ReduceLROnPlateau(verbose=1)
model.fit_generator(train_generator, epochs=400,
steps_per_epoch=100,
validation_data=(test_x[:800], test_y[:800]),
callbacks=[reduce_lr])
result = model.evaluate(test_x, test_y)
print(result)
model.save('12306.image.model.h5', include_optimizer=False)
def predict(imgs):
imgs = preprocess_input(imgs)
model = models.load_model('12306.image.model.h5')
labels = model.predict(imgs)
return labels
def _predict(fn):
imgs = cv2.imread(fn)
imgs = cv2.resize(imgs, (67, 67))
imgs.shape = (-1, 67, 67, 3)
labels = predict(imgs)
print(labels.max(axis=1))
print(labels.argmax(axis=1))
if __name__ == '__main__':
if len(sys.argv) >= 2:
_predict(sys.argv[1])
else:
learn()

@ -1,102 +0,0 @@
#! env python
# coding: utf-8
# 功能:对图像进行预处理,将文字部分单独提取出来
# 并存放到ocr目录下
# 文件名为原验证码文件的文件名
import TickerConfig
if TickerConfig.AUTO_CODE_TYPE == 2:
import hashlib
import os
import pathlib
import cv2
import numpy as np
import requests
import scipy.fftpack
PATH = 'imgs'
def download_image():
# 抓取验证码
# 存放到指定path下
# 文件名为图像的MD5
url = 'https://kyfw.12306.cn/otn/passcodeNew/getPassCodeNew?module=login&rand=sjrand'
r = requests.get(url)
fn = hashlib.md5(r.content).hexdigest()
with open(f'{PATH}/{fn}.jpg', 'wb') as fp:
fp.write(r.content)
def download_images():
pathlib.Path(PATH).mkdir(exist_ok=True)
for idx in range(40000):
download_image()
print(idx)
def get_text(img, offset=0):
# 得到图像中的文本部分
return img[3:22, 120 + offset:177 + offset]
def avhash(im):
im = cv2.resize(im, (8, 8), interpolation=cv2.INTER_CUBIC)
avg = im.mean()
im = im > avg
im = np.packbits(im)
return im
def phash(im):
im = cv2.resize(im, (32, 32), interpolation=cv2.INTER_CUBIC)
im = scipy.fftpack.dct(scipy.fftpack.dct(im, axis=0), axis=1)
im = im[:8, :8]
med = np.median(im)
im = im > med
im = np.packbits(im)
return im
def _get_imgs(img):
interval = 5
length = 67
for x in range(40, img.shape[0] - length, interval + length):
for y in range(interval, img.shape[1] - length, interval + length):
yield img[x:x + length, y:y + length]
def get_imgs(img):
imgs = []
for img in _get_imgs(img):
imgs.append(phash(img))
return imgs
def pretreat():
if not os.path.isdir(PATH):
download_images()
texts, imgs = [], []
for img in os.listdir(PATH):
img = os.path.join(PATH, img)
img = cv2.imread(img, cv2.IMREAD_GRAYSCALE)
texts.append(get_text(img))
imgs.append(get_imgs(img))
return texts, imgs
def load_data(path='data.npz'):
if not os.path.isfile(path):
texts, imgs = pretreat()
np.savez(path, texts=texts, images=imgs)
f = np.load(path)
return f['texts'], f['images']
if __name__ == '__main__':
texts, imgs = load_data()
print(texts.shape)
print(imgs.shape)
imgs = imgs.reshape(-1, 8)
print(np.unique(imgs, axis=0).shape)

@ -1,679 +0,0 @@
/******************************************************************************
* FileName : CatchScreenDlg.cpp
* Author : Unknown
* Mender : sudami
* Time : 2007/09/09
*
* Comment :
*
******************************************************************************/
#include "stdafx.h"
#include "Screenshot.h"
#include "CatchScreenDlg.h"
#include <GdiPlus.h>
using namespace Gdiplus;
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// CCatchScreenDlg dialog
CCatchScreenDlg::CCatchScreenDlg(CWnd* pParent /*=NULL*/)
: CDialog(CCatchScreenDlg::IDD, pParent)
{
m_bLBtnDown = FALSE;
//初始化像皮筋类,新增的resizeMiddle 类型
m_rectTracker.m_nStyle = CMyTracker::resizeMiddle | CMyTracker::solidLine;
m_rectTracker.m_rect.SetRect(-1, -2, -3, -4);
//设置矩形颜色
m_rectTracker.SetRectColor(RGB(10, 100, 130));
m_hCursor = AfxGetApp()->LoadCursor(IDC_CURSOR1);
m_bDraw = FALSE;
m_bFirstDraw = FALSE;
m_bQuit = FALSE;
m_bNeedShowMsg = FALSE;
m_startPt = 0;
//获取屏幕分辩率
m_xScreen = GetSystemMetrics(SM_CXSCREEN);
m_yScreen = GetSystemMetrics(SM_CYSCREEN);
//截取屏幕到位图中
CRect rect(0, 0, m_xScreen, m_yScreen);
m_hBitmap = CopyScreenToBitmap(&rect);
m_pBitmap = CBitmap::FromHandle(m_hBitmap);
//初始化刷新窗口区域 m_rgn
m_rgn.CreateRectRgn(0, 0, 50, 50);
}
void CCatchScreenDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT1, m_tipEdit);
}
BEGIN_MESSAGE_MAP(CCatchScreenDlg, CDialog)
ON_WM_PAINT()
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_LBUTTONDBLCLK()
ON_WM_ERASEBKGND()
ON_WM_SETCURSOR()
ON_WM_RBUTTONUP()
ON_WM_CTLCOLOR()
ON_WM_RBUTTONDOWN()
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CCatchScreenDlg message handlers
BOOL CCatchScreenDlg::OnInitDialog()
{
CDialog::OnInitDialog();
//把对化框设置成全屏顶层窗口
SetWindowPos(&wndTopMost, 0, 0, m_xScreen, m_yScreen, SWP_SHOWWINDOW);
//移动操作提示窗口
CRect rect;
m_tipEdit.GetWindowRect(&rect);
m_tipEdit.MoveWindow(10, 10, rect.Width(), rect.Height());
m_toolBar.CreateToolBar(m_hWnd);
m_toolBar.RemoveChildStyle();
::MoveWindow(m_toolBar.GetHWND(),300,300,230,30,FALSE);
UpdateTipString();
SetEidtWndText();
((CScreenshotApp *)AfxGetApp())->m_hwndDlg = AfxGetMainWnd()->GetSafeHwnd();
return TRUE;
}
void CCatchScreenDlg::OnPaint()
{
// 如果窗口是最小化状态
if (IsIconic())
{
CPaintDC dc(this);
SendMessage(WM_ICONERASEBKGND, (WPARAM)dc.GetSafeHdc(), 0);
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
}
else // 如果窗口正常显示
{
CPaintDC dc(this);
CDC dcCompatible;
dcCompatible.CreateCompatibleDC(&dc);
RECT rect;
::GetClientRect(m_hWnd, &rect);
HBITMAP hBitmap = ::CreateCompatibleBitmap(dc.m_hDC,rect.right-rect.left,rect.bottom-rect.top);
::SelectObject(dcCompatible.m_hDC,hBitmap);
HBRUSH s_hBitmapBrush = CreatePatternBrush(m_hBitmap);
::FillRect(dcCompatible.m_hDC,&rect,s_hBitmapBrush);
//显示截取矩形大小信息
if (m_bNeedShowMsg && m_bFirstDraw)
{
CRect rect = m_rectTracker.m_rect;
DrawMessage(rect, &dcCompatible);
}
//画出像皮筋矩形
if (m_bFirstDraw)
{
m_rectTracker.Draw(&dcCompatible);
}
Gdiplus::Graphics graphics(dcCompatible);
HRGN hgn1 = CreateRectRgn(m_rectTracker.m_rect.left,m_rectTracker.m_rect.top,
m_rectTracker.m_rect.right,m_rectTracker.m_rect.bottom);
Region region1(hgn1);
HRGN hgn2 = CreateRectRgn(rect.left,rect.top,
rect.right,rect.bottom);
Region region2(hgn2);
region2.Exclude(&region1);
SolidBrush solidBrush(Color(100, 128, 128, 128));
graphics.FillRegion(&solidBrush,&region2);
DeleteObject(hgn1);
DeleteObject(hgn2);
dc.BitBlt(0,0,rect.right, rect.bottom,&dcCompatible,0,0,SRCCOPY);
DeleteObject(hBitmap);
DeleteObject(s_hBitmapBrush);
//CDialog::OnPaint();
}
}
void CCatchScreenDlg::OnCancel()
{
if (m_bFirstDraw)
{
//取消已画矩形变量
m_bFirstDraw = FALSE;
m_bDraw = FALSE;
m_rectTracker.m_rect.SetRect(-1, -1, -1, -1);
InvalidateRgnWindow();
}
else
{
CDialog::OnCancel();
}
}
void CCatchScreenDlg::OnMouseMove(UINT nFlags, CPoint point)
{
if(m_bLBtnDown)
m_toolBar.HideToolBar();
else
m_toolBar.ShowToolBar();
if (m_bDraw)
{
//动态调整矩形大小,并刷新画出
m_rectTracker.m_rect.SetRect(m_startPt.x + 4, m_startPt.y + 4, point.x, point.y);
InvalidateRgnWindow();
}
//弥补调整大小和位置时,接收不到MouseMove消息
CRect rect;
m_tipEdit.GetWindowRect(&rect);
if (rect.PtInRect(point))
m_tipEdit.SendMessage(WM_MOUSEMOVE);
UpdateMousePointRGBString();
SetEidtWndText();
CDialog::OnMouseMove(nFlags, point);
}
void CCatchScreenDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
m_bLBtnDown = TRUE;
int nHitTest;
nHitTest = m_rectTracker.HitTest(point);
//判断击中位置
if (nHitTest < 0)
{
if (!m_bFirstDraw)
{
//第一次画矩形
m_startPt = point;
m_bDraw = TRUE;
m_bFirstDraw = TRUE;
//设置当鼠标按下时最小的矩形大小
m_rectTracker.m_rect.SetRect(point.x, point.y, point.x + 4, point.y + 4);
//保证当鼠标当下时立刻显示信息
if (m_bFirstDraw)
m_bNeedShowMsg = TRUE;
UpdateTipString();
SetEidtWndText();
InvalidateRgnWindow();
}
}
else
{
//保证当鼠标当下时立刻显示信息
m_bNeedShowMsg = TRUE;
if (m_bFirstDraw)
{
//调束大小时,Track会自动调整矩形大小,在些期间,消息归CRectTracker内部处理
m_rectTracker.Track(this, point, TRUE);
InvalidateRgnWindow();
}
}
CDialog::OnLButtonDown(nFlags, point);
}
void CCatchScreenDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
m_bLBtnDown = FALSE;
m_bNeedShowMsg = FALSE;
m_bDraw = FALSE;
UpdateTipString();
SetEidtWndText();
m_toolBar.SetShowPlace(m_rectTracker.m_rect.right,m_rectTracker.m_rect.bottom);
InvalidateRgnWindow();
CDialog::OnLButtonUp(nFlags, point);
}
void CCatchScreenDlg::OnLButtonDblClk(UINT nFlags, CPoint point)
{
int nHitTest;
nHitTest = m_rectTracker.HitTest(point);
//如果在是矩形内部双击
if (nHitTest == 8)
{
//保存位图到粘贴板中,bSave 为TRUE,
CopyScreenToBitmap(m_rectTracker.m_rect, TRUE);
PostQuitMessage(0);
}
CDialog::OnLButtonDblClk(nFlags, point);
}
void CCatchScreenDlg::OnRButtonDown(UINT nFlags, CPoint point)
{
m_toolBar.HideToolBar();
//InvalidateRgnWindow();
CDialog::OnRButtonDown(nFlags, point);
}
void CCatchScreenDlg::OnRButtonUp(UINT nFlags, CPoint point)
{
m_bLBtnDown = FALSE;
if (m_bFirstDraw)
{
//如果已经截取矩则清除截取矩形
m_bFirstDraw = FALSE;
//清除矩形大小
m_rectTracker.m_rect.SetRect(-1, -1, -1, -1);
UpdateTipString();
SetEidtWndText();
InvalidateRgnWindow();
}
else
{
//关闭程序
PostQuitMessage(0);
}
CDialog::OnRButtonUp(nFlags, point);
}
HBRUSH CCatchScreenDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
//设置操作提示窗口文本颜色
if (pWnd->GetDlgCtrlID() == IDC_EDIT1)
{
pDC->SetTextColor(RGB(247,76,128));
}
return hbr;
}
BOOL CCatchScreenDlg::OnEraseBkgnd(CDC* pDC)
{
return FALSE;
//用整个桌面填充全屏对话框背景
BITMAP bmp;
m_pBitmap->GetBitmap(&bmp);
CDC dcCompatible;
dcCompatible.CreateCompatibleDC(pDC);
dcCompatible.SelectObject(m_pBitmap);
CRect rect;
GetClientRect(&rect);
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &dcCompatible, 0, 0, SRCCOPY);
return TRUE;
}
BOOL CCatchScreenDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
//设置改变截取矩形大小时光标
if (pWnd == this &&m_rectTracker.SetCursor(this, nHitTest)
&& !m_bDraw &&m_bFirstDraw) //此处判断保截取时当标始中为彩色光标
{
return TRUE;
}
//设置彩色光标
SetCursor(m_hCursor);
return TRUE;
}
// 拷贝屏幕, 这段源码源自CSDN
// lpRect 代表选定区域
HBITMAP CCatchScreenDlg::CopyScreenToBitmap(LPRECT lpRect, BOOL bSave)
{
HDC hScrDC, hMemDC;
// 屏幕和内存设备描述表
HBITMAP hBitmap, hOldBitmap;
// 位图句柄
int nX, nY, nX2, nY2;
// 选定区域坐标
int nWidth, nHeight;
// 确保选定区域不为空矩形
if (IsRectEmpty(lpRect))
return NULL;
//为屏幕创建设备描述表
hScrDC = CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
//为屏幕设备描述表创建兼容的内存设备描述表
hMemDC = CreateCompatibleDC(hScrDC);
// 获得选定区域坐标
nX = lpRect->left;
nY = lpRect->top;
nX2 = lpRect->right;
nY2 = lpRect->bottom;
//确保选定区域是可见的
if (nX < 0)
nX = 0;
if (nY < 0)
nY = 0;
if (nX2 > m_xScreen)
nX2 = m_xScreen;
if (nY2 > m_yScreen)
nY2 = m_yScreen;
nWidth = nX2 - nX;
nHeight = nY2 - nY;
// 创建一个与屏幕设备描述表兼容的位图
hBitmap = CreateCompatibleBitmap
(hScrDC, nWidth, nHeight);
// 把新位图选到内存设备描述表中
hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
// 把屏幕设备描述表拷贝到内存设备描述表中
if (bSave)
{
//创建兼容DC,当bSave为中时把开始保存的全屏位图,按截取矩形大小保存
CDC dcCompatible;
dcCompatible.CreateCompatibleDC(CDC::FromHandle(hMemDC));
dcCompatible.SelectObject(m_pBitmap);
BitBlt(hMemDC, 0, 0, nWidth, nHeight,
dcCompatible, nX, nY, SRCCOPY);
}
else
{
BitBlt(hMemDC, 0, 0, nWidth, nHeight,
hScrDC, nX, nY, SRCCOPY);
}
hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);
//得到屏幕位图的句柄
//清除
DeleteDC(hScrDC);
DeleteDC(hMemDC);
if (bSave)
{
if (OpenClipboard())
{
//清空剪贴板
EmptyClipboard();
//把屏幕内容粘贴到剪贴板上,
//hBitmap 为刚才的屏幕位图句柄
SetClipboardData(CF_BITMAP, hBitmap);
//关闭剪贴板
CloseClipboard();
}
}
// 返回位图句柄
return hBitmap;
}
// 显示操作提示信息
void CCatchScreenDlg::UpdateTipString()
{
CString strTemp;
if (!m_bDraw && !m_bFirstDraw)
{
strTemp = _T("\r\n\r\n·按下鼠标左键不放选择截取\r\n\r\n·ESC键、鼠标右键退出");
}
else
if (m_bDraw && m_bFirstDraw)
{
strTemp = _T("\r\n\r\n·松开鼠标左键确定截取范围\r\n\r\n·ESC键退出");
}
else if (!m_bDraw && m_bFirstDraw)
{
CString sudami(_T("\r\n\r\n·矩形内双击鼠标左键保存\r\n\r\n·点击鼠标右键重新选择"));
strTemp = _T("\r\n\r\n·鼠标在矩形边缘调整大小");
strTemp += sudami;
}
m_strEditTip = strTemp;
}
// 显示截取矩形信息
void CCatchScreenDlg::DrawMessage(CRect &inRect, CDC * pDC)
{
//截取矩形大小信息离鼠标间隔
const int space = 3;
//设置字体颜色大小
CPoint pt;
CPen pen(PS_SOLID, 1, RGB(47, 79, 79));
CPen *pOldPen;
pOldPen = pDC->SelectObject(&pen);
//pDC->SetTextColor(RGB(147,147,147));
CFont font;
CFont * pOldFont;
font.CreatePointFont(90, _T("宋体"));
pOldFont = pDC->SelectObject(&font);
//得到字体宽度和高度
GetCursorPos(&pt);
int OldBkMode;
OldBkMode = pDC->SetBkMode(TRANSPARENT);
TEXTMETRIC tm;
int charHeight;
CSize size;
int lineLength;
pDC->GetTextMetrics(&tm);
charHeight = tm.tmHeight + tm.tmExternalLeading;
size = pDC->GetTextExtent(_T("顶点位置 "), _tcslen(_T("顶点位置 ")));
lineLength = size.cx;
//初始化矩形, 以保证写下六行文字
CRect rect(pt.x + space, pt.y - charHeight * 6 - space, pt.x + lineLength + space, pt.y - space);
//创建临时矩形
CRect rectTemp;
//当矩形到达桌面边缘时调整方向和大小
if ((pt.x + rect.Width()) >= m_xScreen)
{
//桌面上方显示不下矩形
rectTemp = rect;
rectTemp.left = rect.left - rect.Width() - space * 2;
rectTemp.right = rect.right - rect.Width() - space * 2;;
rect = rectTemp;
}
if ((pt.y - rect.Height()) <= 0)
{
//桌面右方显示不下矩形
rectTemp = rect;
rectTemp.top = rect.top + rect.Height() + space * 2;;
rectTemp.bottom = rect.bottom + rect.Height() + space * 2;;
rect = rectTemp;
}
//创建空画刷画矩形
CBrush * pOldBrush;
pOldBrush = pDC->SelectObject(CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH)));
pDC->Rectangle(rect);
rect.top += 2;
//在矩形中显示文字
CRect outRect(rect.left, rect.top, rect.left + lineLength, rect.top + charHeight);
CString string(_T("顶点位置"));
pDC->DrawText(string, outRect, DT_CENTER);
outRect.SetRect(rect.left, rect.top + charHeight, rect.left + lineLength, charHeight + rect.top + charHeight);
string.Format(_T("(%d,%d)"), inRect.left, inRect.top);
pDC->DrawText(string, outRect, DT_CENTER);
outRect.SetRect(rect.left, rect.top + charHeight * 2, rect.left + lineLength, charHeight + rect.top + charHeight * 2);
string = _T("矩形大小");
pDC->DrawText(string, outRect, DT_CENTER);
outRect.SetRect(rect.left, rect.top + charHeight * 3, rect.left + lineLength, charHeight + rect.top + charHeight * 3);
string.Format(_T("(%d,%d)"), inRect.Width(), inRect.Height());
pDC->DrawText(string, outRect, DT_CENTER);
outRect.SetRect(rect.left, rect.top + charHeight * 4, rect.left + lineLength, charHeight + rect.top + charHeight * 4);
string = _T("光标坐标");
pDC->DrawText(string, outRect, DT_CENTER);
outRect.SetRect(rect.left, rect.top + charHeight * 5, rect.left + lineLength, charHeight + rect.top + charHeight * 5);
string.Format(_T("(%d,%d)"), pt.x, pt.y);
pDC->DrawText(string, outRect, DT_CENTER);
pDC->SetBkMode(OldBkMode);
pDC->SelectObject(pOldFont);
pDC->SelectObject(pOldBrush);
pDC->SelectObject(pOldPen);
}
// 刷新局部窗口
void CCatchScreenDlg::InvalidateRgnWindow()
{
//获取当全屏对话框窗口大小
CRect rect1;
GetWindowRect(rect1);
//获取编辑框窗口大小
CRect rect2;
m_tipEdit.GetWindowRect(rect2);
CRgn rgn1, rgn2;
rgn1.CreateRectRgnIndirect(rect1);
rgn2.CreateRectRgnIndirect(rect2);
//获取更新区域,就是除了编辑框窗口不更新
//m_rgn.CombineRgn(&rgn1, &rgn2, RGN_DIFF);
// 添加ToolBar不刷新
CRect rect3;
::GetWindowRect(m_toolBar.GetHWND(),&rect3);
CRgn rgn3;
rgn3.CreateRectRgnIndirect(rect3);
CRgn rgnTemp;
rgnTemp.CreateRectRgn(0, 0, 50, 50);
rgnTemp.CombineRgn(&rgn1, &rgn2, RGN_DIFF);
m_rgn.CombineRgn(&rgnTemp, &rgn3, RGN_DIFF);
InvalidateRgn(&m_rgn);
}
void CCatchScreenDlg::UpdateMousePointRGBString()
{
static CString strOld("");
CPoint pt;
GetCursorPos(&pt);
COLORREF color;
CClientDC dc(this);
color = dc.GetPixel(pt);
BYTE rValue, gValue, bValue;
rValue = GetRValue(color);
gValue = GetGValue(color);
bValue = GetGValue(color);
//按格式排放字符串
CString string;
string.Format(_T("\r\n\r\n·当前像素RGB(%d,%d,%d)"), rValue, gValue, bValue);
//如果当前颜色没变则不刷新RGB值,以免窗口有更多闪烁
if (strOld != string)
{
m_strRgb = string;
}
strOld = string;
}
void CCatchScreenDlg::SetEidtWndText()
{
m_tipEdit.SetWindowText(this->GetEditText());
}
CString CCatchScreenDlg::GetEditText()
{
CString str;
str.Append(m_strRgb);
str.Append(m_strEditTip);
return str;
}
BOOL CCatchScreenDlg::OnCommand(WPARAM wParam, LPARAM lParam)
{
bool bHandle = true;
HWND hWnd = m_toolBar.GetHWND();
if(lParam == (LPARAM)m_toolBar.GetHWND())
{
int wmId = LOWORD(wParam);
switch(wmId)
{
case MyToolBar_ID:
AfxMessageBox(_T("矩形"));
break;
case MyToolBar_ID+1:
AfxMessageBox(_T("圆形"));
break;
case MyToolBar_ID +2:
AfxMessageBox(_T("画笔"));
break;
case MyToolBar_ID +3:
AfxMessageBox(_T("马赛克"));
break;
case MyToolBar_ID +4:
AfxMessageBox(_T("文字"));
break;
case MyToolBar_ID +5:
AfxMessageBox(_T("撤销"));
break;
case MyToolBar_ID +6:
CopyScreenToBitmap(m_rectTracker.m_rect, TRUE);
PostQuitMessage(0);
break;
case MyToolBar_ID +7:
PostQuitMessage(0);
break;
case MyToolBar_ID +8:
CopyScreenToBitmap(m_rectTracker.m_rect, TRUE);
PostQuitMessage(0);
break;
default:
bHandle = false;
break;
}
::SetFocus(hWnd);
}
if (bHandle == false)
{
return CDialog::OnCommand(wParam,lParam);
}
}
////////////////////////////////// END OF FILE ///////////////////////////////////////

@ -1,90 +0,0 @@
#if !defined(AFX_CATCHSCREENDLG_H__536FDBC8_7DB2_4BEF_8943_70DBE8AD845F__INCLUDED_)
#define AFX_CATCHSCREENDLG_H__536FDBC8_7DB2_4BEF_8943_70DBE8AD845F__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif
//--------------------------------------------------------------------------
#include "Resource.h"
#include "MyEdit.h"
#ifndef MYTRACKER_
#include "MyTracker.h"
#endif
#include "MyToolBar.h"
//--------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
class CCatchScreenDlg : public CDialog
{
public:
CCatchScreenDlg(CWnd* pParent = NULL);
enum { IDD = IDD_DIALOGFORIMG };
CMyEdit m_tipEdit;
CMyToolBar m_toolBar;
public:
int m_xScreen;
int m_yScreen;
BOOL m_bLBtnDown;
BOOL m_bNeedShowMsg; // 显示截取矩形大小信息
BOOL m_bDraw; // 是否为截取状态
BOOL m_bFirstDraw; // 是否为首次截取
BOOL m_bQuit; // 是否为退出
CPoint m_startPt; // 截取矩形左上角位置
CMyTracker m_rectTracker; // 像皮筋类
CBrush m_brush;
HCURSOR m_hCursor; // 光标
CBitmap* m_pBitmap; // Edit关联控件的背景位图
HBITMAP m_hBitmap;
CRgn m_rgn; // 背景擦除区域
public:
HBITMAP CopyScreenToBitmap(LPRECT lpRect,BOOL bSave=FALSE); /* 拷贝桌面到位图 */
void UpdateTipString(); //显示操作提示信息
void DrawMessage(CRect &inRect,CDC * pDC); //显示截取矩形信息
void InvalidateRgnWindow(); //重画窗口
void UpdateMousePointRGBString();
CString m_strRgb;
CString m_strEditTip;
void SetEidtWndText();
CString GetEditText();
protected:
virtual void DoDataExchange(CDataExchange* pDX);
virtual BOOL OnInitDialog();
virtual void OnCancel();
afx_msg void OnPaint();
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
DECLARE_MESSAGE_MAP()
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
};
///////////////////////////////////////////////////////////////////////////////////////////
#endif

@ -1,120 +0,0 @@
/******************************************************************************
* FileName : MyEdit.CPP
* Author : Unknown
* Mender : sudami
* Time : 2007/09/09
*
* Comment :
*--------------------------------------------------------
* .
* ,
*--------------------------------------------------------
******************************************************************************/
#include "stdafx.h"
#include "MyEdit.h"
#include "resource.h"
///////////////////////////////////////////////////////////////////////////////
// 构造函数、析构函数
//
CMyEdit::CMyEdit()
{
m_bMove=TRUE;
}
CMyEdit::~CMyEdit()
{
}
BEGIN_MESSAGE_MAP(CMyEdit, CEdit)
/* 2个小消息 */
ON_WM_CREATE()
ON_WM_PAINT()
ON_WM_SETFOCUS()
/* 3个大消息 */
ON_WM_MOUSEMOVE()
ON_WM_ERASEBKGND()
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//
int CMyEdit::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CEdit::OnCreate(lpCreateStruct) == -1)
return -1;
return 0;
}
void CMyEdit::OnPaint()
{
CPaintDC dc(this);
CDC dcCompatible;
dcCompatible.CreateCompatibleDC(&dc);
dcCompatible.SetBkMode(TRANSPARENT);
CBitmap bitmap;
bitmap.LoadBitmap(IDB_BITMAP_BK);
dcCompatible.SelectObject(&bitmap);
RECT rt = {5,5,0,0};
RECT rtClient = {0};
GetClientRect(&rtClient);
rt.right = rtClient.right;
rt.bottom = rtClient.bottom;
CString str;
GetWindowText(str);
CFont font;
CFont * pOldFont;
font.CreatePointFont(90, _T("宋体"));
pOldFont = dcCompatible.SelectObject(&font);
dcCompatible.DrawText(str,&rt,DT_LEFT);
dcCompatible.SelectObject(pOldFont);
CRect rect;
GetClientRect(&rect);
dc.BitBlt(0,0,rect.Width(),rect.Height(),&dcCompatible,0,0,SRCCOPY);
}
/////////////////////////////////////////////////////////////////////////////
// <响应 WM_MOUSEMOVE 消息>
// 和QQ的截图差不多的效果,只要鼠标挪到该控件区域,该区域就变换位置
//
void CMyEdit::OnMouseMove(UINT nFlags, CPoint point)
{
CEdit::OnMouseMove(nFlags, point);
CRect rect;
GetWindowRect(&rect);
int xScreen = GetSystemMetrics(SM_CXSCREEN);
if(m_bMove)
{
//移动到左上角
MoveWindow(10,10,rect.Width(),rect.Height());
m_bMove=FALSE;
}
else
{
//移动到右上角
MoveWindow(xScreen-180,10,rect.Width(),rect.Height());
m_bMove=TRUE;
}
}
/////////////////////////////////////////////////////////////////////////////
//
void CMyEdit::OnSetFocus(CWnd* pOldWnd)
{
CEdit::OnSetFocus(pOldWnd);
// 隐藏光标提示符
this->HideCaret();
}
BOOL CMyEdit::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}

@ -1,51 +0,0 @@
/*****************************************************************************
* FileName : MyEdit.h
* Author : Unknown
* Mender : sudami
* Time : 2007/09/09
*
* Comment :
*--------------------------------------------------------
* .
* ,
*--------------------------------------------------------
******************************************************************************/
#if !defined(AFX_MYEDIT_H__A34EEA6D_E8FC_4D15_B03C_BAA42FDF6FCB__INCLUDED_)
#define AFX_MYEDIT_H__A34EEA6D_E8FC_4D15_B03C_BAA42FDF6FCB__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif
//-----------------------------------------------------------------------------
#include <afxwin.h>
//-----------------------------------------------------------------------------
class CMyEdit : public CEdit
{
public:
CMyEdit();
virtual ~CMyEdit();
BOOL m_bMove; // 类似"单刀双掷开关"
protected:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSetFocus(CWnd* pOldWnd);
afx_msg void OnPaint();
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
DECLARE_MESSAGE_MAP()
};
//////////////////////////////////////////////////////////////////////////////////
#endif

@ -1,148 +0,0 @@
#include "StdAfx.h"
#include "MyToolBar.h"
#include <GdiPlus.h>
#include "resource.h"
BOOL ImageFromIDResource(UINT nID, LPCTSTR sTR, Gdiplus::Bitmap * & pImg)
{
HINSTANCE hInst = AfxGetResourceHandle();
HRSRC hRsrc = ::FindResource (hInst,MAKEINTRESOURCE(nID),sTR); // type
if (!hRsrc)
return FALSE;
// load resource into memory
DWORD len = SizeofResource(hInst, hRsrc);
BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc);
if (!lpRsrc)
return FALSE;
// Allocate global memory on which to create stream
HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len);
BYTE* pmem = (BYTE*)GlobalLock(m_hMem);
memcpy(pmem,lpRsrc,len);
IStream* pstm;
CreateStreamOnHGlobal(m_hMem,FALSE,&pstm);
// load from stream
pImg=Gdiplus::Bitmap::FromStream(pstm);
// free/release stuff
GlobalUnlock(m_hMem);
pstm->Release();
FreeResource(lpRsrc);
return TRUE;
}
CMyToolBar::CMyToolBar()
{
m_hImageList = NULL;
m_hWnd_toolbar = 0;
m_hWndParent = 0;
}
CMyToolBar::~CMyToolBar(void)
{
ImageList_Destroy(m_hImageList);
}
BOOL CMyToolBar::CreateToolBar(HWND hWndParent)
{
if (m_hImageList)
return FALSE;
m_hWndParent = hWndParent;
m_hImageList= ImageList_Create(18,18,ILC_COLOR32,1,1);
Gdiplus::Bitmap * pImage = NULL;
for(int i=0;i< 9;i++)
{
ImageFromIDResource(IDB_RECTANGLE + i,_T("PNG"),pImage);
HBITMAP pHbitmap=0;;
if(pImage)
{
pImage->GetHBITMAP(Gdiplus::Color(0xff,0xff,0xff,0xff),&pHbitmap);
ImageList_Add(m_hImageList,pHbitmap,NULL);
delete pImage;
pImage = NULL;
}
}
m_hWnd_toolbar = ::CreateWindowEx(0,TOOLBARCLASSNAME,0,WS_CHILD | WS_VISIBLE|WS_BORDER ,
0,0,0,0,hWndParent,NULL,GetModuleHandle(NULL),NULL);
if (m_hWnd_toolbar == NULL)
return FALSE;
::SendMessage(m_hWnd_toolbar,TB_SETIMAGELIST, 0, (LPARAM) m_hImageList);
::SendMessage(m_hWnd_toolbar,TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
::SendMessage(m_hWnd_toolbar,
(UINT) TB_SETBITMAPSIZE,(WPARAM) 0,//not used, must be zero
(LPARAM) MAKELONG (18, 18)// = (LPARAM) MAKELONG (dxBitmap, dyBitmap)
);
//TCHAR tooltips[16][30]={_T("AAAA"),_T("BBBB"),_T("CCCC"),_T("DDDD")};
for(int i = 0; i < 9; i++)
{
TBBUTTON tbbutton;
// 换行
int wrapnow = 0;
//if (i % 2 == 1)
// wrapnow = TBSTATE_WRAP;
ZeroMemory(&tbbutton, sizeof(TBBUTTON));
//tbbutton.iString = (INT_PTR) tooltips[i];
tbbutton.fsStyle = TBSTYLE_CHECKGROUP; // 单选属性
tbbutton.fsState = TBSTATE_ENABLED | wrapnow;
tbbutton.idCommand = MyToolBar_ID + i; // 定义控件的id
tbbutton.iBitmap = i;
::SendMessage(m_hWnd_toolbar,TB_ADDBUTTONS, 1, (LPARAM) &tbbutton);
}
::SendMessage(m_hWnd_toolbar, TB_AUTOSIZE, 0, 0);
return TRUE;
}
HWND CMyToolBar::GetHWND()
{
return m_hWnd_toolbar;
}
void CMyToolBar::AddChildStyle()
{
DWORD dwStyle = GetWindowLong(m_hWnd_toolbar, GWL_STYLE);
dwStyle &= WS_CHILD;
SetWindowLong(m_hWnd_toolbar,GWL_STYLE,dwStyle);
}
void CMyToolBar::RemoveChildStyle()
{
DWORD dwStyle = GetWindowLong(m_hWnd_toolbar, GWL_STYLE);
dwStyle &= ~WS_CHILD;
SetWindowLong(m_hWnd_toolbar,GWL_STYLE,dwStyle);
}
void CMyToolBar::ShowToolBar()
{
::ShowWindow(m_hWnd_toolbar,SW_SHOW);
}
void CMyToolBar::HideToolBar()
{
::ShowWindow(m_hWnd_toolbar,SW_HIDE);
}
void CMyToolBar::SetAtCurMousePlase()
{
RECT rtWin = {0};
::GetWindowRect(m_hWnd_toolbar,&rtWin);
POINT pt = {0};
::GetCursorPos(&pt);
this->SetShowPlace(pt.x,pt.y);
}
void CMyToolBar::SetShowPlace(int nCurPointX,int nCurPointY)
{
RECT rtWin = {0};
::GetWindowRect(m_hWnd_toolbar,&rtWin);
::SetWindowPos(m_hWnd_toolbar,HWND_TOP,nCurPointX - (rtWin.right-rtWin.left),nCurPointY + 2,0,0,SWP_NOSIZE|SWP_SHOWWINDOW);
}

@ -1,24 +0,0 @@
#pragma once
#define MyToolBar_ID 600
class CMyToolBar
{
public:
CMyToolBar();
~CMyToolBar(void);
BOOL CreateToolBar(HWND hWndParent);
void AddChildStyle();
void RemoveChildStyle();
void ShowToolBar();
void HideToolBar();
void SetAtCurMousePlase();
void SetShowPlace(int nCurPointX,int nCurPointY);
HWND GetHWND();
private:
HIMAGELIST m_hImageList;
HWND m_hWndParent;
HWND m_hWnd_toolbar;
};

@ -1,839 +0,0 @@
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
#include "stdafx.h"
#include "MyTracker.h"
#include "Resource.h"
#include "CatchScreenDlg.h"
/////////////////////////////////////////////////////////////////////////////
// CMyTracker global state
// various GDI objects we need to draw
AFX_STATIC_DATA HCURSOR _afxCursors[10] = { 0,};
AFX_STATIC_DATA HBRUSH _afxHatchBrush = 0;
AFX_STATIC_DATA HPEN _afxBlackDottedPen = 0;
AFX_STATIC_DATA HPEN _afxBlackSolidPen = 0;
AFX_STATIC_DATA int _afxHandleSize = 0;
void AFX_CDECL AfxTrackerTerm()
{
AfxDeleteObject((HGDIOBJ*)&_afxHatchBrush);
AfxDeleteObject((HGDIOBJ*)&_afxBlackDottedPen);
}
char _afxTrackerTerm = (char)atexit(&AfxTrackerTerm);
// the struct below is used to determine the qualities of a particular handle
struct AFX_HANDLEINFO
{
size_t nOffsetX; // offset within RECT for X coordinate
size_t nOffsetY; // offset within RECT for Y coordinate
int nCenterX; // adjust X by Width()/2 * this number
int nCenterY; // adjust Y by Height()/2 * this number
int nHandleX; // adjust X by handle size * this number
int nHandleY; // adjust Y by handle size * this number
int nInvertX; // handle converts to this when X inverted
int nInvertY; // handle converts to this when Y inverted
};
// this array describes all 8 handles (clock-wise)
AFX_STATIC_DATA const AFX_HANDLEINFO _afxHandleInfo[] =
{
// corner handles (top-left, top-right, bottom-right, bottom-left
{ offsetof(RECT, left), offsetof(RECT, top), 0, 0, 0, 0, 1, 3 },
{ offsetof(RECT, right), offsetof(RECT, top), 0, 0, -1, 0, 0, 2 },
{ offsetof(RECT, right), offsetof(RECT, bottom), 0, 0, -1, -1, 3, 1 },
{ offsetof(RECT, left), offsetof(RECT, bottom), 0, 0, 0, -1, 2, 0 },
// side handles (top, right, bottom, left)
{ offsetof(RECT, left), offsetof(RECT, top), 1, 0, 0, 0, 4, 6 },
{ offsetof(RECT, right), offsetof(RECT, top), 0, 1, -1, 0, 7, 5 },
{ offsetof(RECT, left), offsetof(RECT, bottom), 1, 0, 0, -1, 6, 4 },
{ offsetof(RECT, left), offsetof(RECT, top), 0, 1, 0, 0, 5, 7 }
};
// the struct below gives us information on the layout of a RECT struct and
// the relationship between its members
struct AFX_RECTINFO
{
size_t nOffsetAcross; // offset of opposite point (ie. left->right)
int nSignAcross; // sign relative to that point (ie. add/subtract)
};
// this array is indexed by the offset of the RECT member / sizeof(int)
AFX_STATIC_DATA const AFX_RECTINFO _afxRectInfo[] =
{
{ offsetof(RECT, right), +1 },
{ offsetof(RECT, bottom), +1 },
{ offsetof(RECT, left), -1 },
{ offsetof(RECT, top), -1 },
};
/////////////////////////////////////////////////////////////////////////////
// CMyTracker intitialization
CMyTracker::CMyTracker(LPCRECT lpSrcRect, UINT nStyle)
{
ASSERT(AfxIsValidAddress(lpSrcRect, sizeof(RECT), FALSE));
Construct();
m_rect.CopyRect(lpSrcRect);
m_nStyle = nStyle;
}
CMyTracker::CMyTracker()
{
Construct();
}
void CMyTracker::Construct()
{
// do one-time initialization if necessary
//********************************************************
m_rectColor=RGB(0,0,0);
//********************************************************
AfxLockGlobals(CRIT_RECTTRACKER);
static BOOL bInitialized;
if (!bInitialized)
{
// sanity checks for assumptions we make in the code
ASSERT(sizeof(((RECT*)NULL)->left) == sizeof(int));
ASSERT(offsetof(RECT, top) > offsetof(RECT, left));
ASSERT(offsetof(RECT, right) > offsetof(RECT, top));
ASSERT(offsetof(RECT, bottom) > offsetof(RECT, right));
if (_afxHatchBrush == NULL)
{
// create the hatch pattern + bitmap
WORD hatchPattern[8];
WORD wPattern = 0x1111;
for (int i = 0; i < 4; i++)
{
hatchPattern[i] = wPattern;
hatchPattern[i+4] = wPattern;
wPattern <<= 1;
}
HBITMAP hatchBitmap = CreateBitmap(8, 8, 1, 1, &hatchPattern);
if (hatchBitmap == NULL)
{
AfxUnlockGlobals(CRIT_RECTTRACKER);
AfxThrowResourceException();
}
// create black hatched brush
_afxHatchBrush = CreatePatternBrush(hatchBitmap);
DeleteObject(hatchBitmap);
if (_afxHatchBrush == NULL)
{
AfxUnlockGlobals(CRIT_RECTTRACKER);
AfxThrowResourceException();
}
}
//CreatePen for DottedLine and SolidLine
CreatePen();
// Note: all track cursors must live in same module
HINSTANCE hInst = AfxFindResourceHandle(
MAKEINTRESOURCE(AFX_IDC_TRACK4WAY), RT_GROUP_CURSOR);
// initialize the cursor array
_afxCursors[0] = ::LoadCursor(hInst, MAKEINTRESOURCE(AFX_IDC_TRACKNWSE));
_afxCursors[1] = ::LoadCursor(hInst, MAKEINTRESOURCE(AFX_IDC_TRACKNESW));
_afxCursors[2] = _afxCursors[0];
_afxCursors[3] = _afxCursors[1];
_afxCursors[4] = ::LoadCursor(hInst, MAKEINTRESOURCE(AFX_IDC_TRACKNS));
_afxCursors[5] = ::LoadCursor(hInst, MAKEINTRESOURCE(AFX_IDC_TRACKWE));
_afxCursors[6] = _afxCursors[4];
_afxCursors[7] = _afxCursors[5];
_afxCursors[8] = ::LoadCursor(hInst, MAKEINTRESOURCE(AFX_IDC_TRACK4WAY));
_afxCursors[9] = ::LoadCursor(hInst, MAKEINTRESOURCE(AFX_IDC_MOVE4WAY));
// get default handle size from Windows profile setting
static const TCHAR szWindows[] = _T("windows");
static const TCHAR szInplaceBorderWidth[] =
_T("oleinplaceborderwidth");
_afxHandleSize = GetProfileInt(szWindows, szInplaceBorderWidth, 4);
bInitialized = TRUE;
}
AfxUnlockGlobals(CRIT_RECTTRACKER);
m_nStyle = 0;
m_nHandleSize = _afxHandleSize;
m_sizeMin.cy = m_sizeMin.cx = m_nHandleSize*2;
m_rectLast.SetRectEmpty();
m_sizeLast.cx = m_sizeLast.cy = 0;
m_bErase = FALSE;
m_bFinalErase = FALSE;
}
CMyTracker::~CMyTracker()
{
}
/////////////////////////////////////////////////////////////////////////////
// CMyTracker operations
void CMyTracker::Draw(CDC* pDC) const
{
// set initial DC state
VERIFY(pDC->SaveDC() != 0);
pDC->SetMapMode(MM_TEXT);
pDC->SetViewportOrg(0, 0);
pDC->SetWindowOrg(0, 0);
// get normalized rectangle
CRect rect = m_rect;
rect.NormalizeRect();
CPen* pOldPen = NULL;
CBrush* pOldBrush = NULL;
CGdiObject* pTemp;
int nOldROP;
// draw lines
if ((m_nStyle & (dottedLine|solidLine)) != 0)
{
if (m_nStyle & dottedLine)
{
//改变当前矩形颜色
pOldPen = pDC->SelectObject(CPen::FromHandle(_afxBlackDottedPen));
}
else
{
//改变当前矩形颜色
//pOldPen = (CPen*)pDC->SelectStockObject(BLACK_PEN); //BLACK_PEN
pOldPen = pDC->SelectObject(CPen::FromHandle(_afxBlackSolidPen));
}
pOldBrush = (CBrush*)pDC->SelectStockObject(NULL_BRUSH);
nOldROP = pDC->SetROP2(R2_COPYPEN);
rect.InflateRect(+1, +1); // borders are one pixel outside
pDC->Rectangle(rect.left, rect.top, rect.right, rect.bottom);
pDC->SetROP2(nOldROP);
}
// if hatchBrush is going to be used, need to unrealize it
if ((m_nStyle & (hatchInside|hatchedBorder)) != 0)
UnrealizeObject(_afxHatchBrush);
// hatch inside
if ((m_nStyle & hatchInside) != 0)
{
pTemp = pDC->SelectStockObject(NULL_PEN);
if (pOldPen == NULL)
pOldPen = (CPen*)pTemp;
pTemp = pDC->SelectObject(CBrush::FromHandle(_afxHatchBrush));
if (pOldBrush == NULL)
pOldBrush = (CBrush*)pTemp;
pDC->SetBkMode(TRANSPARENT);
nOldROP = pDC->SetROP2(R2_MASKNOTPEN);
pDC->Rectangle(rect.left+1, rect.top+1, rect.right, rect.bottom);
pDC->SetROP2(nOldROP);
}
// draw hatched border
if ((m_nStyle & hatchedBorder) != 0)
{
pTemp = pDC->SelectObject(CBrush::FromHandle(_afxHatchBrush));
if (pOldBrush == NULL)
pOldBrush = (CBrush*)pTemp;
pDC->SetBkMode(OPAQUE);
CRect rectTrue;
GetTrueRect(&rectTrue);
pDC->PatBlt(rectTrue.left, rectTrue.top, rectTrue.Width(),
rect.top-rectTrue.top, 0x000F0001 /* Pn */);
pDC->PatBlt(rectTrue.left, rect.bottom,
rectTrue.Width(), rectTrue.bottom-rect.bottom, 0x000F0001 /* Pn */);
pDC->PatBlt(rectTrue.left, rect.top, rect.left-rectTrue.left,
rect.Height(), 0x000F0001 /* Pn */);
pDC->PatBlt(rect.right, rect.top, rectTrue.right-rect.right,
rect.Height(), 0x000F0001 /* Pn */);
}
// draw resize handles
if ((m_nStyle & (resizeInside|resizeOutside)) != 0)
{
UINT mask = GetHandleMask();
for (int i = 0; i < 8; ++i)
{
if (mask & (1<<i))
{
GetHandleRect((TrackerHit)i, &rect);
//改变当前调整手柄矩形颜色,也就是那八个点
pDC->FillSolidRect(rect, m_rectColor);
}
}
}
// cleanup pDC state
if (pOldPen != NULL)
pDC->SelectObject(pOldPen);
if (pOldBrush != NULL)
pDC->SelectObject(pOldBrush);
VERIFY(pDC->RestoreDC(-1));
}
BOOL CMyTracker::SetCursor(CWnd* pWnd, UINT nHitTest) const
{
// trackers should only be in client area
if (nHitTest != HTCLIENT)
return FALSE;
// convert cursor position to client co-ordinates
CPoint point;
GetCursorPos(&point);
pWnd->ScreenToClient(&point);
// do hittest and normalize hit
int nHandle = HitTestHandles(point);
if (nHandle < 0)
return FALSE;
// need to normalize the hittest such that we get proper cursors
nHandle = NormalizeHit(nHandle);
// handle special case of hitting area between handles
// (logically the same -- handled as a move -- but different cursor)
if (nHandle == hitMiddle && !m_rect.PtInRect(point))
{
// only for trackers with hatchedBorder (ie. in-place resizing)
if (m_nStyle & hatchedBorder)
nHandle = (TrackerHit)9;
}
//ASSERT(nHandle < _countof(_afxCursors));
::SetCursor(_afxCursors[nHandle]);
return TRUE;
}
int CMyTracker::HitTest(CPoint point) const
{
TrackerHit hitResult = hitNothing;
CRect rectTrue;
GetTrueRect(&rectTrue);
ASSERT(rectTrue.left <= rectTrue.right);
ASSERT(rectTrue.top <= rectTrue.bottom);
if (rectTrue.PtInRect(point))
{
if ((m_nStyle & (resizeInside|resizeOutside)) != 0)
hitResult = (TrackerHit)HitTestHandles(point);
else
hitResult = hitMiddle;
}
return hitResult;
}
int CMyTracker::NormalizeHit(int nHandle) const
{
ASSERT(nHandle <= 8 && nHandle >= -1);
if (nHandle == hitMiddle || nHandle == hitNothing)
return nHandle;
const AFX_HANDLEINFO* pHandleInfo = &_afxHandleInfo[nHandle];
if (m_rect.Width() < 0)
{
nHandle = (TrackerHit)pHandleInfo->nInvertX;
pHandleInfo = &_afxHandleInfo[nHandle];
}
if (m_rect.Height() < 0)
nHandle = (TrackerHit)pHandleInfo->nInvertY;
return nHandle;
}
BOOL CMyTracker::Track(CWnd* pWnd, CPoint point, BOOL bAllowInvert,
CWnd* pWndClipTo)
{
// perform hit testing on the handles
int nHandle = HitTestHandles(point);
if (nHandle < 0)
{
// didn't hit a handle, so just return FALSE
return FALSE;
}
// otherwise, call helper function to do the tracking
m_bAllowInvert = bAllowInvert;
return TrackHandle(nHandle, pWnd, point, pWndClipTo);
}
BOOL CMyTracker::TrackRubberBand(CWnd* pWnd, CPoint point, BOOL bAllowInvert)
{
// simply call helper function to track from bottom right handle
m_bAllowInvert = bAllowInvert;
m_rect.SetRect(point.x, point.y, point.x, point.y);
return TrackHandle(hitBottomRight, pWnd, point, NULL);
}
void CMyTracker::DrawTrackerRect(
LPCRECT lpRect, CWnd* pWndClipTo, CDC* pDC, CWnd* pWnd)
{
// first, normalize the rectangle for drawing
/*CRect rect = *lpRect;
rect.NormalizeRect();
// convert to client coordinates
if (pWndClipTo != NULL)
{
pWnd->ClientToScreen(&rect);
pWndClipTo->ScreenToClient(&rect);
}
CSize size(0, 0);
if (!m_bFinalErase)
{
// otherwise, size depends on the style
if (m_nStyle & hatchedBorder)
{
size.cx = size.cy = max(1, GetHandleSize(rect)-1);
rect.InflateRect(size);
}
else
{
size.cx = CX_BORDER;
size.cy = CY_BORDER;
}
}
// and draw it
if (m_bFinalErase || !m_bErase)
{
pDC->DrawDragRect(rect, size, m_rectLast, m_sizeLast);
}
// remember last rectangles
m_rectLast = rect;
m_sizeLast = size;
*/
//此函数是画调整大小和位置时画虚线
//由于本程序不需要,如果要正常使作的话把上面注示去掉就行了!
((CCatchScreenDlg *)pWnd)->InvalidateRgnWindow();
}
void CMyTracker::AdjustRect(int nHandle, LPRECT)
{
if (nHandle == hitMiddle)
return;
// convert the handle into locations within m_rect
int *px, *py;
GetModifyPointers(nHandle, &px, &py, NULL, NULL);
// enforce minimum width
int nNewWidth = m_rect.Width();
int nAbsWidth = m_bAllowInvert ? abs(nNewWidth) : nNewWidth;
if (px != NULL && nAbsWidth < m_sizeMin.cx)
{
nNewWidth = nAbsWidth != 0 ? nNewWidth / nAbsWidth : 1;
//ASSERT((int*)px - (int*)&m_rect < _countof(_afxRectInfo));
const AFX_RECTINFO* pRectInfo = &_afxRectInfo[(int*)px - (int*)&m_rect];
*px = *(int*)((BYTE*)&m_rect + pRectInfo->nOffsetAcross) +
nNewWidth * m_sizeMin.cx * -pRectInfo->nSignAcross;
}
// enforce minimum height
int nNewHeight = m_rect.Height();
int nAbsHeight = m_bAllowInvert ? abs(nNewHeight) : nNewHeight;
if (py != NULL && nAbsHeight < m_sizeMin.cy)
{
nNewHeight = nAbsHeight != 0 ? nNewHeight / nAbsHeight : 1;
//ASSERT((int*)py - (int*)&m_rect < _countof(_afxRectInfo));
const AFX_RECTINFO* pRectInfo = &_afxRectInfo[(int*)py - (int*)&m_rect];
*py = *(int*)((BYTE*)&m_rect + pRectInfo->nOffsetAcross) +
nNewHeight * m_sizeMin.cy * -pRectInfo->nSignAcross;
}
}
void CMyTracker::GetTrueRect(LPRECT lpTrueRect) const
{
ASSERT(AfxIsValidAddress(lpTrueRect, sizeof(RECT)));
CRect rect = m_rect;
rect.NormalizeRect();
int nInflateBy = 0;
if ((m_nStyle & (resizeOutside|hatchedBorder)) != 0)
nInflateBy += GetHandleSize() - 1;
if ((m_nStyle & (solidLine|dottedLine)) != 0)
++nInflateBy;
rect.InflateRect(nInflateBy, nInflateBy);
*lpTrueRect = rect;
}
void CMyTracker::OnChangedRect(const CRect& /*rectOld*/)
{
// no default implementation, useful for derived classes
}
/////////////////////////////////////////////////////////////////////////////
// CMyTracker implementation helpers
void CMyTracker::GetHandleRect(int nHandle, CRect* pHandleRect) const
{
ASSERT(nHandle < 8);
// get normalized rectangle of the tracker
CRect rectT = m_rect;
rectT.NormalizeRect();
if ((m_nStyle & (solidLine|dottedLine)) != 0)
rectT.InflateRect(+1, +1);
// since the rectangle itself was normalized, we also have to invert the
// resize handles.
nHandle = NormalizeHit(nHandle);
// handle case of resize handles outside the tracker
int size = GetHandleSize();
if(m_nStyle & resizeOutside)
{
if(1000000 & m_nStyle)
{
rectT.InflateRect(size-size/2-1, size-size/2-1);
}
else
{
rectT.InflateRect(size-1, size-1);
}
}
// calculate position of the resize handle
int nWidth = rectT.Width();
int nHeight = rectT.Height();
CRect rect;
const AFX_HANDLEINFO* pHandleInfo = &_afxHandleInfo[nHandle];
rect.left = *(int*)((BYTE*)&rectT + pHandleInfo->nOffsetX);
rect.top = *(int*)((BYTE*)&rectT + pHandleInfo->nOffsetY);
rect.left += size * pHandleInfo->nHandleX;
rect.top += size * pHandleInfo->nHandleY;
rect.left += pHandleInfo->nCenterX * (nWidth - size) / 2;
rect.top += pHandleInfo->nCenterY * (nHeight - size) / 2;
rect.right = rect.left + size;
rect.bottom = rect.top + size;
*pHandleRect = rect;
}
int CMyTracker::GetHandleSize(LPCRECT lpRect) const
{
if (lpRect == NULL)
lpRect = &m_rect;
int size = m_nHandleSize;
if (!(m_nStyle & resizeOutside))
{
// make sure size is small enough for the size of the rect
int sizeMax = min(abs(lpRect->right - lpRect->left),
abs(lpRect->bottom - lpRect->top));
if (size * 2 > sizeMax)
size = sizeMax / 2;
}
return size;
}
int CMyTracker::HitTestHandles(CPoint point) const
{
CRect rect;
UINT mask = GetHandleMask();
// see if hit anywhere inside the tracker
GetTrueRect(&rect);
if (!rect.PtInRect(point))
return hitNothing; // totally missed
// see if we hit a handle
for (int i = 0; i < 8; ++i)
{
if (mask & (1<<i))
{
GetHandleRect((TrackerHit)i, &rect);
if (rect.PtInRect(point))
return (TrackerHit)i;
}
}
// last of all, check for non-hit outside of object, between resize handles
if ((m_nStyle & hatchedBorder) == 0)
{
CRect rect = m_rect;
rect.NormalizeRect();
if ((m_nStyle & dottedLine|solidLine) != 0)
rect.InflateRect(+1, +1);
if (!rect.PtInRect(point))
return hitNothing; // must have been between resize handles
}
return hitMiddle; // no handle hit, but hit object (or object border)
}
BOOL CMyTracker::TrackHandle(int nHandle, CWnd* pWnd, CPoint point,
CWnd* pWndClipTo)
{
ASSERT(nHandle >= 0);
ASSERT(nHandle <= 8); // handle 8 is inside the rect
// don't handle if capture already set
if (::GetCapture() != NULL)
return FALSE;
AfxLockTempMaps(); // protect maps while looping
ASSERT(!m_bFinalErase);
// save original width & height in pixels
int nWidth = m_rect.Width();
int nHeight = m_rect.Height();
// set capture to the window which received this message
pWnd->SetCapture();
ASSERT(pWnd == CWnd::GetCapture());
pWnd->UpdateWindow();
if (pWndClipTo != NULL)
pWndClipTo->UpdateWindow();
CRect rectSave = m_rect;
// find out what x/y coords we are supposed to modify
int *px, *py;
int xDiff, yDiff;
GetModifyPointers(nHandle, &px, &py, &xDiff, &yDiff);
xDiff = point.x - xDiff;
yDiff = point.y - yDiff;
// get DC for drawing
CDC* pDrawDC;
if (pWndClipTo != NULL)
{
// clip to arbitrary window by using adjusted Window DC
pDrawDC = pWndClipTo->GetDCEx(NULL, DCX_CACHE);
}
else
{
// otherwise, just use normal DC
pDrawDC = pWnd->GetDC();
}
ASSERT_VALID(pDrawDC);
CRect rectOld;
BOOL bMoved = FALSE;
// get messages until capture lost or cancelled/accepted
for (;;)
{
MSG msg;
VERIFY(::GetMessage(&msg, NULL, 0, 0));
if (CWnd::GetCapture() != pWnd)
break;
//增加的,把消息派送给窗口
DispatchMessage(&msg);
switch (msg.message)
{
// handle movement/accept messages
case WM_LBUTTONUP:
case WM_MOUSEMOVE:
rectOld = m_rect;
// handle resize cases (and part of move)
if (px != NULL)
*px = (int)(short)LOWORD(msg.lParam) - xDiff;
if (py != NULL)
*py = (int)(short)HIWORD(msg.lParam) - yDiff;
// handle move case
if (nHandle == hitMiddle)
{
m_rect.right = m_rect.left + nWidth;
m_rect.bottom = m_rect.top + nHeight;
}
// allow caller to adjust the rectangle if necessary
AdjustRect(nHandle, &m_rect);
// only redraw and callback if the rect actually changed!
m_bFinalErase = (msg.message == WM_LBUTTONUP);
if (!rectOld.EqualRect(&m_rect) || m_bFinalErase)
{
if (bMoved)
{
m_bErase = TRUE;
DrawTrackerRect(&rectOld, pWndClipTo, pDrawDC, pWnd);
}
OnChangedRect(rectOld);
if (msg.message != WM_LBUTTONUP)
{
bMoved = TRUE;
}
}
if (m_bFinalErase)
goto ExitLoop;
if (!rectOld.EqualRect(&m_rect))
{
m_bErase = FALSE;
DrawTrackerRect(&m_rect, pWndClipTo, pDrawDC, pWnd);
}
break;
// handle cancel messages
case WM_KEYDOWN:
if (msg.wParam != VK_ESCAPE)
break;
case WM_RBUTTONDOWN:
if (bMoved)
{
m_bErase = m_bFinalErase = TRUE;
//DrawTrackerRect(&m_rect, pWndClipTo, pDrawDC, pWnd);
}
m_rect = rectSave;
goto ExitLoop;
// just dispatch rest of the messages
default:
DispatchMessage(&msg);
break;
}
}
ExitLoop:
if (pWndClipTo != NULL)
pWndClipTo->ReleaseDC(pDrawDC);
else
pWnd->ReleaseDC(pDrawDC);
ReleaseCapture();
AfxUnlockTempMaps(FALSE);
// restore rect in case bMoved is still FALSE
if (!bMoved)
m_rect = rectSave;
m_bFinalErase = FALSE;
m_bErase = FALSE;
// return TRUE only if rect has changed
return !rectSave.EqualRect(&m_rect);
}
void CMyTracker::GetModifyPointers(
int nHandle, int** ppx, int** ppy, int* px, int* py)
{
ASSERT(nHandle >= 0);
ASSERT(nHandle <= 8);
if (nHandle == hitMiddle)
nHandle = hitTopLeft; // same as hitting top-left
*ppx = NULL;
*ppy = NULL;
// fill in the part of the rect that this handle modifies
// (Note: handles that map to themselves along a given axis when that
// axis is inverted don't modify the value on that axis)
const AFX_HANDLEINFO* pHandleInfo = &_afxHandleInfo[nHandle];
if (pHandleInfo->nInvertX != nHandle)
{
*ppx = (int*)((BYTE*)&m_rect + pHandleInfo->nOffsetX);
if (px != NULL)
*px = **ppx;
}
else
{
// middle handle on X axis
if (px != NULL)
*px = m_rect.left + abs(m_rect.Width()) / 2;
}
if (pHandleInfo->nInvertY != nHandle)
{
*ppy = (int*)((BYTE*)&m_rect + pHandleInfo->nOffsetY);
if (py != NULL)
*py = **ppy;
}
else
{
// middle handle on Y axis
if (py != NULL)
*py = m_rect.top + abs(m_rect.Height()) / 2;
}
}
UINT CMyTracker::GetHandleMask() const
{
UINT mask = 0x0F; // always have 4 corner handles
int size = m_nHandleSize*3;
if (abs(m_rect.Width()) - size > 4)
mask |= 0x50;
if (abs(m_rect.Height()) - size > 4)
mask |= 0xA0;
return mask;
}
////////////////////增加的函数/////////////////////////////////////////////////////////////
void CMyTracker::SetRectColor(COLORREF rectColor)
{
m_rectColor=rectColor;
CreatePen();
}
void CMyTracker::CreatePen()
{
//if (_afxBlackDottedPen == NULL)
{
// create black dotted pen
_afxBlackDottedPen = ::CreatePen(PS_DOT, 0, m_rectColor);
if (_afxBlackDottedPen == NULL)
{
AfxUnlockGlobals(CRIT_RECTTRACKER);
AfxThrowResourceException();
}
}
//if (_afxBlackSolidPen == NULL)
{
// create black dotted pen
_afxBlackSolidPen = ::CreatePen(PS_SOLID, 0, m_rectColor);
if (_afxBlackSolidPen == NULL)
{
AfxUnlockGlobals(CRIT_RECTTRACKER);
AfxThrowResourceException();
}
}
}
void CMyTracker::SetResizeCursor(UINT nID_N_S,UINT nID_W_E,UINT nID_NW_SE,UINT nID_NE_SW,UINT nIDMiddle)
{
//////////////////////////////////////////////////////////////////////////////////
// N
// NW -----------|------------NE
// | |
// | |
// W | | E
// | Middle |
// | |
// | |
// SW-----------|------------SE
// S
////////////////////////////////////////////////////////////////////////////////////
_afxCursors[0] = AfxGetApp()->LoadCursor(nID_NW_SE); //nw
_afxCursors[1] = AfxGetApp()->LoadCursor(nID_NE_SW); //ne
_afxCursors[2] = _afxCursors[0]; //se
_afxCursors[3] = _afxCursors[1]; //sw
_afxCursors[4] = AfxGetApp()->LoadCursor(nID_N_S); //n
_afxCursors[5] = AfxGetApp()->LoadCursor(nID_W_E); //w
_afxCursors[6] = _afxCursors[4]; //s
_afxCursors[7] = _afxCursors[5]; //e
_afxCursors[8] = AfxGetApp()->LoadCursor(nIDMiddle); //m
// _afxCursors[9] = ::LoadCursor(hInst, MAKEINTRESOURCE(AFX_IDC_MOVE4WAY));
}

@ -1,102 +0,0 @@
/////////////////////////////////////////////////////////////////////////////
// CMyTracker - simple rectangular tracking rectangle w/resize handles
/////////////////////////////////////////////////////////////////////////
// Copy from MFC CRectTracker class
// Add Some member function
// Modify some place
////////////////////////////////////////////////////////////////////////
#define MYTRACKER_
#define CX_BORDER 1
#define CY_BORDER 1
#define CRIT_RECTTRACKER 5
void AFXAPI AfxLockGlobals(int nLockType);
void AFXAPI AfxUnlockGlobals(int nLockType);
void AFXAPI AfxDeleteObject(HGDIOBJ* pObject);
class CMyTracker
{
public:
// Constructors
CMyTracker();
CMyTracker(LPCRECT lpSrcRect, UINT nStyle);
// Style Flags
enum StyleFlags
{
solidLine = 1, dottedLine = 2, hatchedBorder = 4,
resizeInside = 8, resizeOutside = 16, hatchInside = 32,
resizeMiddle =80 //设置中间
};
// Hit-Test codes
enum TrackerHit
{
hitNothing = -1,
hitTopLeft = 0, hitTopRight = 1, hitBottomRight = 2, hitBottomLeft = 3,
hitTop = 4, hitRight = 5, hitBottom = 6, hitLeft = 7, hitMiddle = 8
};
// Attributes
UINT m_nStyle; // current state
CRect m_rect; // current position (always in pixels)
CSize m_sizeMin; // minimum X and Y size during track operation
int m_nHandleSize; // size of resize handles (default from WIN.INI)
// Operations
void Draw(CDC* pDC) const;
void GetTrueRect(LPRECT lpTrueRect) const;
BOOL SetCursor(CWnd* pWnd, UINT nHitTest) const;
BOOL Track(CWnd* pWnd, CPoint point, BOOL bAllowInvert =TRUE,
CWnd* pWndClipTo = NULL);
BOOL TrackRubberBand(CWnd* pWnd, CPoint point, BOOL bAllowInvert = TRUE);
int HitTest(CPoint point) const;
int NormalizeHit(int nHandle) const;
// Overridables
virtual void DrawTrackerRect(LPCRECT lpRect, CWnd* pWndClipTo,
CDC* pDC, CWnd* pWnd);
virtual void AdjustRect(int nHandle, LPRECT lpRect);
virtual void OnChangedRect(const CRect& rectOld);
virtual UINT GetHandleMask() const;
// Implementation
public:
virtual ~CMyTracker();
public:
//***********************************************************
//设置调整光标
void SetResizeCursor(UINT nID_N_S,UINT nID_W_E,UINT nID_NW_SE,
UINT nID_NE_SW,UINT nIDMiddle);
//创建军画刷,内部调用
void CreatePen();
//设置矩形颜色
void SetRectColor(COLORREF rectColor);
//**************************************************************
//**************************************************************
//当前矩形颜色
COLORREF m_rectColor;
//**************************************************************
BOOL m_bAllowInvert; // flag passed to Track or TrackRubberBand
CRect m_rectLast;
CSize m_sizeLast;
BOOL m_bErase; // TRUE if DrawTrackerRect is called for erasing
BOOL m_bFinalErase; // TRUE if DragTrackerRect called for final erase
// implementation helpers
int HitTestHandles(CPoint point) const;
void GetHandleRect(int nHandle, CRect* pHandleRect) const;
void GetModifyPointers(int nHandle, int**ppx, int**ppy, int* px, int*py);
virtual int GetHandleSize(LPCRECT lpRect = NULL) const;
BOOL TrackHandle(int nHandle, CWnd* pWnd, CPoint point, CWnd* pWndClipTo);
void Construct();
};
//////////////////////////////////////// END OF FILE /////////////////////////////////////////////////////////

File diff suppressed because it is too large Load Diff

@ -1,117 +0,0 @@
/*
Copyright (C) 2004 Jacquelin POTIER <jacquelin.potier@free.fr>
Dynamic aspect ratio code Copyright (C) 2004 Jacquelin POTIER <jacquelin.potier@free.fr>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//-----------------------------------------------------------------------------
// Object: class helper for popupmenu control
//-----------------------------------------------------------------------------
#pragma once
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501 // for xp os
#endif
#include <windows.h>
#pragma warning (push)
#pragma warning(disable : 4005)// for '_stprintf' : macro redefinition in tchar.h
#include <TCHAR.h>
#pragma warning (pop)
#include <vector>
#include <commctrl.h>
#pragma comment (lib,"comctl32.lib")
class CPopUpMenu
{
public:
typedef void (*pfMessageCallback)(WPARAM wParam, LPARAM lParam,PVOID UserParam);
CPopUpMenu();
CPopUpMenu(CPopUpMenu* ParentPopUpMenu);
~CPopUpMenu();
HMENU GetControlHandle();
CPopUpMenu* GetParentPopUpMenu();
UINT Add(TCHAR* Name);
UINT Add(TCHAR* Name,UINT Index);
UINT Add(TCHAR* Name,HICON hIcon);
UINT Add(TCHAR* Name,HICON hIcon,UINT Index);
UINT Add(TCHAR* Name,int IdIcon,HINSTANCE hInstance);
UINT Add(TCHAR* Name,int IdIcon,HINSTANCE hInstance,UINT Index);
UINT Add(TCHAR* Name,int IdIcon,HINSTANCE hInstance,int Width,int Height,UINT Index);
UINT AddSeparator();
UINT AddSeparator(UINT Index);
UINT AddSubMenu(TCHAR* SubMenuName,CPopUpMenu* SubMenu,UINT Index);
UINT AddSubMenu(TCHAR* SubMenuName,CPopUpMenu* SubMenu);
UINT AddSubMenu(TCHAR* SubMenuName,CPopUpMenu* SubMenu,int IdIcon,HINSTANCE hInstance,UINT Index);
UINT AddSubMenu(TCHAR* SubMenuName,CPopUpMenu* SubMenu,int IdIcon,HINSTANCE hInstance);
UINT AddSubMenu(TCHAR* SubMenuName,CPopUpMenu* SubMenu,HICON hIcon,UINT Index);
UINT AddSubMenu(TCHAR* SubMenuName,CPopUpMenu* SubMenu,HICON hIcon);
void SetCheckedState(UINT MenuID,BOOL bChecked);
BOOL IsChecked(UINT MenuID);
void SetEnabledState(UINT MenuID,BOOL bEnabled);
BOOL IsEnabled(UINT MenuID);
BOOL SetText(UINT MenuID,TCHAR* pszText);
BOOL SetIcon(UINT MenuID,int IdIcon,HINSTANCE hInstance);
BOOL SetIcon(UINT MenuID,int IdIcon,HINSTANCE hInstance,int Width,int Height);
BOOL SetIcon(UINT MenuID,HICON hIcon);
int GetText(UINT MenuID,TCHAR* pszText,int pszTextMaxSize);
CPopUpMenu* GetSubMenu(UINT MenuID);
void Remove(UINT MenuID);
int GetItemCount();
int GetID(UINT MenuIndex);
int GetIndex(UINT MenuId);
UINT Show(int x,int y, HWND hOwner);
UINT Show(int x,int y, HWND hOwner,BOOL PositionRelativeToOwner);
UINT Show(int x,int y, HWND hOwner,BOOL PositionRelativeToOwner,BOOL ShowUpper);
UINT GetNextMenuId();
UINT GetMaxMenuId();
BOOL ReplaceMenuId(UINT OldMenuID,UINT NewMenuID);
BOOL SetMouseRightButtonUpCallback(pfMessageCallback Callback,PVOID UserParam);
BOOL SetMenuSelectCallback(pfMessageCallback Callback,PVOID UserParam);
BOOL bAllowIconsEffects;
private:
CPopUpMenu* ParentPopUpMenu;
HMENU hPopUpMenu;
int CurrentMenuId;
BOOL bThemingEnabledForVistaOrNewer;
std::vector<HBITMAP> ListLoadedBitmapToFree;
pfMessageCallback MouseRightButtonUpCallback;
PVOID MouseRightButtonUpUserParam;
pfMessageCallback MenuSelectCallback;
PVOID MenuSelectUserParam;
void CommonConstructor();
void SetMenuItemBitmapInfo(MENUITEMINFO* pMenuItem,HICON hIcon);
BOOL IsSubMenu(HMENU hMenu,HMENU hSubMenu);
BOOL OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis);
BOOL OnDrawItem(HWND hwnd, LPDRAWITEMSTRUCT lpdis);
void OnMouseRightButtonUp(WPARAM wParam, LPARAM lParam);
void OnMenuSelect(WPARAM wParam, LPARAM lParam);
void FreeItemMemory(UINT MenuID);
void FreeItemBitmap(UINT MenuID);
static LRESULT CALLBACK SubClassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,UINT_PTR uIdSubclass,DWORD_PTR dwRefData);
};

@ -1,73 +0,0 @@
================================================================================
MICROSOFT 基础类库: Screenshot 项目概述
===============================================================================
应用程序向导已为您创建了这个 Screenshot 应用程序。此应用程序不仅演示 Microsoft 基础类的基本使用方法,还可作为您编写应用程序的起点。
本文件概要介绍组成 Screenshot 应用程序的每个文件的内容。
Screenshot.vcproj
这是使用应用程序向导生成的 VC++ 项目的主项目文件。
它包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
Screenshot.h
这是应用程序的主要头文件。它包括其他项目特定的头文件(包括 Resource.h),并声明 CScreenshotApp 应用程序类。
Screenshot.cpp
这是包含应用程序类 CScreenshotApp 的主要应用程序源文件。
Screenshot.rc
这是程序使用的所有 Microsoft Windows 资源的列表。它包括 RES 子目录中存储的图标、位图和光标。此文件可以直接在 Microsoft Visual C++ 中进行编辑。项目资源位于 2052 中。
res\Screenshot.ico
这是用作应用程序图标的图标文件。此图标包括在主要资源文件 Screenshot.rc 中。
res\Screenshot.rc2
此文件包含不在 Microsoft Visual C++ 中进行编辑的资源。您应该将不可由资源编辑器编辑的所有资源放在此文件中。
/////////////////////////////////////////////////////////////////////////////
应用程序向导创建一个对话框类:
ScreenshotDlg.hScreenshotDlg.cpp - 对话框
这些文件包含 CScreenshotDlg 类。该类定义应用程序主对话框的行为。该对话框的模板位于 Screenshot.rc 中,该文件可以在 Microsoft Visual C++ 中进行编辑。
/////////////////////////////////////////////////////////////////////////////
其他功能:
ActiveX 控件
应用程序包括对使用 ActiveX 控件的支持。
打印及打印预览支持
应用程序向导已通过从 MFC 库调用 CView 类中的成员函数,生成了用于处理打印、打印设置和打印预览命令的代码。
/////////////////////////////////////////////////////////////////////////////
其他标准文件:
StdAfx.hStdAfx.cpp
这些文件用于生成名为 Screenshot.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
Resource.h
这是标准头文件,它定义新的资源 ID。
Microsoft Visual C++ 读取并更新此文件。
Screenshot.manifest
应用程序清单文件供 Windows XP 用来描述应用程序
对特定版本并行程序集的依赖性。加载程序使用此
信息从程序集缓存加载适当的程序集或
从应用程序加载私有信息。应用程序清单可能为了重新分发而作为
与应用程序可执行文件安装在相同文件夹中的外部 .manifest 文件包括,
也可能以资源的形式包括在该可执行文件中。
/////////////////////////////////////////////////////////////////////////////
其他注释:
应用程序向导使用“TODO:”指示应添加或自定义的源代码部分。
如果应用程序在共享的 DLL 中使用 MFC则需要重新发布这些 MFC DLL如果应用程序所用的语言与操作系统的当前区域设置不同则还需要重新发布对应的本地化资源 MFC90XXX.DLL。有关这两个主题的更多信息请参见 MSDN 文档中有关 Redistributing Visual C++ applications (重新发布 Visual C++ 应用程序)的章节。
/////////////////////////////////////////////////////////////////////////////

Binary file not shown.

@ -1,174 +0,0 @@
// Screenshot.cpp : 定义应用程序的类行为。
//
#include "stdafx.h"
#include "Screenshot.h"
#include "ScreenshotDlg.h"
#include "CatchScreenDlg.h"
#include <GdiPlus.h>
using namespace Gdiplus;
#pragma comment(lib,"GdiPlus.lib")
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#define SHIFTED 0x8000
// CScreenshotApp
BEGIN_MESSAGE_MAP(CScreenshotApp, CWinApp)
ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()
// CScreenshotApp 构造
CScreenshotApp::CScreenshotApp()
{
// TODO: 在此处添加构造代码,
// 将所有重要的初始化放置在 InitInstance 中
}
// 唯一的一个 CScreenshotApp 对象
CScreenshotApp theApp;
// CScreenshotApp 初始化
BOOL CScreenshotApp::InitInstance()
{
// 如果一个运行在 Windows XP 上的应用程序清单指定要
// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
//则需要 InitCommonControlsEx()。否则,将无法创建窗口。
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// 将它设置为包括所有要在应用程序中使用的
// 公共控件类。
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinApp::InitInstance();
GdiplusStartupInput input;
GdiplusStartup(&m_gdiplusToken,&input,NULL);
AfxEnableControlContainer();
// 标准初始化
// 如果未使用这些功能并希望减小
// 最终可执行文件的大小,则应移除下列
// 不需要的特定初始化例程
// 更改用于存储设置的注册表项
// TODO: 应适当修改该字符串,
// 例如修改为公司或组织名
SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
CScreenshotDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: 在此放置处理何时用
// “确定”来关闭对话框的代码
}
else if (nResponse == IDCANCEL)
{
// TODO: 在此放置处理何时用
// “取消”来关闭对话框的代码
}
// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
// 而不是启动应用程序的消息泵。
return FALSE;
}
BOOL CScreenshotApp::ProcessMessageFilter(int code, LPMSG lpMsg)
{
if(m_hwndDlg != NULL)
{
// 如果消息是从对话框发出的或者其子控件发出的,就进行处理
if((lpMsg->hwnd == m_hwndDlg) || ::IsChild(m_hwndDlg, lpMsg->hwnd))
{
// 如果消息是WM_KEYDOWN,用方向键调整位置
if(lpMsg->message == WM_KEYDOWN)
{
CRect rect(0,0,0,0);
CCatchScreenDlg * pDlg=(CCatchScreenDlg *)AfxGetMainWnd();
rect = pDlg->m_rectTracker.m_rect;
if(pDlg->m_bFirstDraw)
{
//如果Shift键按下则方向键调整大小
BOOL bIsShiftDown = FALSE;
if (GetKeyState(VK_SHIFT) & SHIFTED)
bIsShiftDown = TRUE;
////////////////////////////////////////////////////
switch(lpMsg->wParam)
{
case VK_UP:
//如果按下Shift,则只调整一边
if(!bIsShiftDown)
rect.top-=1;
rect.bottom-=1;
pDlg->m_rectTracker.m_rect = rect;
pDlg->InvalidateRgnWindow();
break;
case VK_DOWN:
rect.top+=1;
if(!bIsShiftDown)
rect.bottom+=1;
pDlg->m_rectTracker.m_rect=rect;
pDlg->InvalidateRgnWindow();
break;
case VK_LEFT:
if(!bIsShiftDown)
rect.left-=1;
rect.right-=1;
pDlg->m_rectTracker.m_rect=rect;
pDlg->InvalidateRgnWindow();
break;
case VK_RIGHT:
rect.left+=1;
if(!bIsShiftDown)
rect.right+=1;
pDlg->m_rectTracker.m_rect=rect;
pDlg->InvalidateRgnWindow();
break;
}
}
}
}
}
return CWinApp::ProcessMessageFilter(code, lpMsg);
}
int CScreenshotApp::ExitInstance()
{
GdiplusShutdown(m_gdiplusToken);
return CWinApp::ExitInstance();
}

@ -1,38 +0,0 @@
// Screenshot.h : PROJECT_NAME 应用程序的主头文件
//
#pragma once
#ifndef __AFXWIN_H__
#error "在包含此文件之前包含“stdafx.h”以生成 PCH 文件"
#endif
#include "resource.h" // 主符号
// CScreenshotApp:
// 有关此类的实现,请参阅 Screenshot.cpp
//
class CScreenshotApp : public CWinApp
{
public:
CScreenshotApp();
// 重写
public:
virtual BOOL InitInstance();
HWND m_hwndDlg;
virtual BOOL ProcessMessageFilter(int code, LPMSG lpMsg);
// 实现
DECLARE_MESSAGE_MAP()
private:
ULONG_PTR m_gdiplusToken;
public:
virtual int ExitInstance();
};
extern CScreenshotApp theApp;

@ -1,217 +0,0 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#ifndef APSTUDIO_INVOKED
#include "targetver.h"
#endif
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Chinese (P.R.C.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
#ifdef _WIN32
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#pragma code_page(936)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#ifndef APSTUDIO_INVOKED\r\n"
"#include ""targetver.h""\r\n"
"#endif\r\n"
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"#define _AFX_NO_SPLITTER_RESOURCES\r\n"
"#define _AFX_NO_OLE_RESOURCES\r\n"
"#define _AFX_NO_TRACKER_RESOURCES\r\n"
"#define _AFX_NO_PROPERTY_RESOURCES\r\n"
"\r\n"
"#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)\r\n"
"LANGUAGE 4, 2\r\n"
"#pragma code_page(936)\r\n"
"#include ""res\\Screenshot.rc2"" // 非 Microsoft Visual C++ 编辑的资源\r\n"
"#include ""l.CHS\\afxres.rc"" // 标准组件\r\n"
"#endif\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDR_MAINFRAME ICON "res\\Screenshot.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_SCREENSHOT_DIALOG DIALOGEX 0, 0, 181, 59
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW
CAPTION "Screenshot"
FONT 9, "MS Shell Dlg", 0, 0, 0x1
BEGIN
PUSHBUTTON "截图",IDC_BTN_START,65,22,50,14
END
IDD_DIALOGFORIMG DIALOGEX 0, 0, 169, 140
STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP
EXSTYLE WS_EX_TRANSPARENT
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
EDITTEXT IDC_EDIT1,14,20,137,93,ES_MULTILINE | ES_READONLY | NOT WS_BORDER
END
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,1
PRODUCTVERSION 1,0,0,1
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080403a8"
BEGIN
VALUE "CompanyName", "TODO: <公司名>"
VALUE "FileDescription", "TODO: <文件说明>"
VALUE "FileVersion", "1.0.0.1"
VALUE "InternalName", "Screenshot.exe"
VALUE "LegalCopyright", "TODO: (C) <公司名>。保留所有权利。"
VALUE "OriginalFilename", "Screenshot.exe"
VALUE "ProductName", "TODO: <产品名>"
VALUE "ProductVersion", "1.0.0.1"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x804, 936
END
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_SCREENSHOT_DIALOG, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 174
TOPMARGIN, 7
BOTTOMMARGIN, 52
END
IDD_DIALOGFORIMG, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 162
TOPMARGIN, 7
BOTTOMMARGIN, 133
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//
IDB_BITMAP_BK BITMAP "res\\brackground.bmp"
/////////////////////////////////////////////////////////////////////////////
//
// PNG
//
IDB_ARROW PNG "res\\Arrow.png"
IDB_RECTANGLE PNG "res\\Rectangle.png"
IDB_CIRCLE PNG "res\\Circle.png"
IDB_BRUSH PNG "res\\Brush.PNG"
IDB_MOSAIC PNG "res\\Mosaic.png"
IDB_TEXT PNG "res\\Text.png"
IDB_UNDO PNG "res\\Undo.png"
IDB_SAVE PNG "res\\Save.png"
IDB_EXIT PNG "res\\Exit.png"
IDB_FINISH PNG "res\\Finish.png"
/////////////////////////////////////////////////////////////////////////////
//
// Cursor
//
IDC_CURSOR1 CURSOR "res\\arrow_m.cur"
#endif // Chinese (P.R.C.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
#define _AFX_NO_SPLITTER_RESOURCES
#define _AFX_NO_OLE_RESOURCES
#define _AFX_NO_TRACKER_RESOURCES
#define _AFX_NO_PROPERTY_RESOURCES
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE 4, 2
#pragma code_page(936)
#include "res\Screenshot.rc2" // 非 Microsoft Visual C++ 编辑的资源
#include "l.CHS\afxres.rc" // 标准组件
#endif
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

@ -1,368 +0,0 @@
<?xml version="1.0" encoding="gb2312"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="Screenshot"
ProjectGUID="{24E39ACB-AB81-485D-8D36-749B3F5EC1E8}"
RootNamespace="Screenshot"
Keyword="MFCProj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
UseOfMFC="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="false"
ValidateParameters="true"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="2052"
AdditionalIncludeDirectories="$(IntDir)"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
UseOfMFC="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="false"
ValidateParameters="true"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG"
MinimalRebuild="false"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="2"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="2052"
AdditionalIncludeDirectories="$(IntDir)"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\CatchScreenDlg.cpp"
>
</File>
<File
RelativePath=".\MyEdit.cpp"
>
</File>
<File
RelativePath=".\MyToolBar.cpp"
>
</File>
<File
RelativePath=".\MyTracker.cpp"
>
</File>
<File
RelativePath=".\PopUpMenu.cpp"
>
</File>
<File
RelativePath=".\Screenshot.cpp"
>
</File>
<File
RelativePath=".\ScreenshotDlg.cpp"
>
</File>
<File
RelativePath=".\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\CatchScreenDlg.h"
>
</File>
<File
RelativePath=".\MyEdit.h"
>
</File>
<File
RelativePath=".\MyToolBar.h"
>
</File>
<File
RelativePath=".\MyTracker.h"
>
</File>
<File
RelativePath=".\PopUpMenu.h"
>
</File>
<File
RelativePath=".\Resource.h"
>
</File>
<File
RelativePath=".\Screenshot.h"
>
</File>
<File
RelativePath=".\ScreenshotDlg.h"
>
</File>
<File
RelativePath=".\stdafx.h"
>
</File>
<File
RelativePath=".\targetver.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
<File
RelativePath=".\res\Arrow.ico"
>
</File>
<File
RelativePath=".\res\Arrow.png"
>
</File>
<File
RelativePath=".\res\arrow_m.cur"
>
</File>
<File
RelativePath=".\res\brackground.bmp"
>
</File>
<File
RelativePath=".\res\Brush.PNG"
>
</File>
<File
RelativePath=".\res\Circle.png"
>
</File>
<File
RelativePath=".\res\Exit.png"
>
</File>
<File
RelativePath=".\res\Finish.png"
>
</File>
<File
RelativePath=".\res\Mosaic.png"
>
</File>
<File
RelativePath=".\res\Rectangle.png"
>
</File>
<File
RelativePath=".\res\Save.png"
>
</File>
<File
RelativePath=".\res\Screenshot.ico"
>
</File>
<File
RelativePath=".\Screenshot.rc"
>
</File>
<File
RelativePath=".\res\Screenshot.rc2"
>
</File>
<File
RelativePath=".\res\Text.png"
>
</File>
<File
RelativePath=".\res\toolbar1.bmp"
>
</File>
<File
RelativePath=".\res\Undo.png"
>
</File>
</Filter>
<File
RelativePath=".\ReadMe.txt"
>
</File>
</Files>
<Globals>
<Global
Name="RESOURCE_FILE"
Value="Screenshot.rc"
/>
</Globals>
</VisualStudioProject>

@ -1,169 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{24E39ACB-AB81-485D-8D36-749B3F5EC1E8}</ProjectGuid>
<RootNamespace>Screenshot</RootNamespace>
<Keyword>MFCProj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v120_xp</PlatformToolset>
<UseOfMfc>Dynamic</UseOfMfc>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v120_xp</PlatformToolset>
<UseOfMfc>Dynamic</UseOfMfc>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>15.0.27924.0</_ProjectFileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
<IntDir>$(Configuration)\</IntDir>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
<IntDir>$(Configuration)\</IntDir>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Midl>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>false</MkTypLibCompatible>
<ValidateAllParameters>true</ValidateAllParameters>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0804</Culture>
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Midl>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>false</MkTypLibCompatible>
<ValidateAllParameters>true</ValidateAllParameters>
</Midl>
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x0804</Culture>
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="CatchScreenDlg.cpp" />
<ClCompile Include="MyEdit.cpp" />
<ClCompile Include="MyToolBar.cpp" />
<ClCompile Include="MyTracker.cpp" />
<ClCompile Include="PopUpMenu.cpp" />
<ClCompile Include="Screenshot.cpp" />
<ClCompile Include="ScreenshotDlg.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="Toolbar.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="CatchScreenDlg.h" />
<ClInclude Include="MyEdit.h" />
<ClInclude Include="MyToolBar.h" />
<ClInclude Include="MyTracker.h" />
<ClInclude Include="PopUpMenu.h" />
<ClInclude Include="Resource.h" />
<ClInclude Include="Screenshot.h" />
<ClInclude Include="ScreenshotDlg.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="Toolbar.h" />
</ItemGroup>
<ItemGroup>
<None Include="ReadMe.txt" />
<None Include="res\Arrow.ico" />
<None Include="res\Arrow.png" />
<None Include="res\arrow_m.cur" />
<None Include="res\brackground.bmp" />
<None Include="res\Brush.PNG" />
<None Include="res\Circle.png" />
<None Include="res\Exit.png" />
<None Include="res\Finish.png" />
<None Include="res\Mosaic.png" />
<None Include="res\Rectangle.png" />
<None Include="res\Save.png" />
<None Include="res\Screenshot.ico" />
<None Include="res\Screenshot.rc2" />
<None Include="res\Text.png" />
<None Include="res\toolbar1.bmp" />
<None Include="res\Undo.png" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Screenshot.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<ProjectExtensions>
<VisualStudio>
<UserProperties RESOURCE_FILE="Screenshot.rc" />
</VisualStudio>
</ProjectExtensions>
</Project>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save