没有准考证号我是如何暴力查询英语六级成绩的
8月22日上午9时,CET6级成绩开始查询了。然而,忘记自己准考证号的也不在少数,而我,非常幸运,成为其中一员。仔细想了想,自己的准考证号是不太可能找回来了。
- 下载CET6准考证的网站关了,虽然Chrome还保存着账号密码,但没用
- 准考证本来拍照保存了的,但因为刷机手机图片也丢失了
- CET6准考证的打印PDF不知道还在不在电脑上,用Everything搜索*.pdf,没有发现在6月17日(那天CET6考试)左右的可疑文件
- 考场号及座位号完全忘记,另外考场内好像也没熟人
- 网上的99宿舍这次没用了,无法找回准考证号,只能获取前10位
- 截止当日,说好的支付宝免准考证号查询成绩并没有来
显然,正常渠道,我是不太可能获取到自己的准考证号了。要等到学校下发6级的成绩单或者班级的成绩单,我估计没半个月是见不到成绩了,甚至更久!
与其等那么久,不如想想有什么办法。
准考证的前10位,毫无疑问,我们知道。那么需要解决的也就是后面的5位了。即使是暴力猜测,也不过10000次。
CET6成绩查询的网站是http://cet.neea.edu.cn/cet/,查询流程很简单,输入准考证号、姓名、验证码即可。
通过抓包,我们获取了如下几个API:
1. 获取验证码图片URL API
HTTP方式 |
URL |
---|---|
GET |
http://cache.neea.edu.cn/Imgs.do?ik={准考证号}&t=0.6002525141319914 |
返回的内容:
result.imgs("http://cet.neea.edu.cn/imgs/b3d0c1b6987e4295b01e30ccaceed725.png");
通过正则表达式,提取出图片URL即可。
提示:调用该api记得发送GET请求时需要加上相应的cookie。
2. 提交查询API
HTTP方式 |
URL |
---|---|
POST |
http://cache.neea.edu.cn/cet/query |
提交的内容:
data=CET6_171_DANGCI%2C准考证号%2C姓名&v=验证码
解码一下:
data:CET6_171_DANGCI,准考证号,姓名v:6wbn
提示:该api提交记得带上相应的cookie
现在,CET暴力查询的整体思路,体现在如下几个模块:
A. 图片获取模块 1. 获取随机的准考证号 2. 获取相应的图片文件 大概获取200张左右图片,之后进行人工图片标记 B. 机器学习模块 1. 标记好下载的验证码图片 2. 图片灰度化、二值化、图片切割 3. 图片转特征矩阵,准备好特征向量与分类标签 4. SVM分类算法进行分类 C. 暴力查询模块 1. 根据输入的前10为准考证号,暴力破解后5为准考证号(考场号3位 + 座位号2位) 2. 指定准考证号ID获取指定验证码图片 3. 图片输入机器学习模块,获取验证码值 4. 提交验证码进行查询,获取相应的结果:验证码错误/无结果/非上述两者,查询成功
难点在于如何对验证码进行识别。
- 我们先下载好200张左右的验证码图片
通过第一个API接口,编码文件如下所示:
get_images.py
运行上述文件,我们获得了足够多的图片,然后需要做的是手工对图片进行重命名,文件名为验证码的值。
2. 标记好图片之后,我们再写一个python文件将图片进行切割,将切割后的图片放置在以标签命名的文件夹下。
classify_images.py
运行好后,图片文件就自动分好类了。
3.有了分好类的图片,我们需要做的是将图片转换为相应的特征矩阵和对应的分类标签。我们写一个learn_images.py完成这个任务。
learn_images.py
运行该文件,我们可以对标记好的图片文件进行预测,在predict_images下的文件,然后会打印出预测值与正确的标记值。
4.为了方便使用,我们写了一个api接口文件,方便后续的直接调用。
validate_api.py
有了上述的各大文件,我们就可以进行整合工作了。
5.最后的暴力破解模块
force_query.py
使用只需要修改id变量为你中的准考证号前10位数字,并将name变量改为你自己的名字,程序就可以一步步向正确的准考证号逼近了。
程序停止了有2种情况:
1. 报错了 2. 查到了
报错了后,将开始的range(1, 10001)改下,为报错结束最后验证的值,节约下次查询的时间。
运气好,大概10分钟内就可以得到了。当我查询到了6级分数,我已做好了下一次6级报名的准备,祝你们好运!附上我的一张成功截图:
由于时间原因,程序写得仓促,还有较多的较大的改进空间,例如可以改为多线程或者协程加快查询速率,单线程毕竟太慢了。
不过,估计这东西出来感觉离和谐也不远了。两点原因:
- 对服务器会造成点压力
- 只需要知道某个人的姓名与他所在的大学就可以查询到他相应的分数
对了,我还想所说的是,这个网站的验证码设计真的很人性化,你运行一下附件中的count_word.py就知道了!
有些代码,文章中并没有贴上来,如utils.py文件,因为和要叙述的关联性不强。另外,文章可能有些细节没有照顾到,结合附件的源代码,你就明白了。
- Quartz.net官方开发指南 第十一课: 高级(企业级)属性
- Quartz.net官方开发指南 第十二课:Quartz 的其他特性
- Protocol Buffers的应用
- WordPress 显示数据库查询次数、查询时间及内存占用的代码
- WCF服务在高负载下可能会变慢
- WordPress 后台管理菜单名称重命名的方法
- 从Akismet 黑名单中洗白的方法
- 移除除管理员之外的其他用户的WordPress 更新升级提示
- 为 WordPress 后台管理菜单自定义排序
- WordPress 添加个性化的博客宠物(妹纸篇)
- WordPress 添加个性化的博客宠物(汉纸篇)
- WordPress 退出(登出)的时候跳转到首页
- WordPress免插件仅代码实现面包屑导航
- 开源的作业调度框架 - Quartz.NET
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android编程实现使用handler在子线程中更新UI示例
- Android编程实现图片放大缩小功能ZoomControls控件用法实例
- 详解Android MacAddress 适配心得
- Android编程使用GestureDetector实现简单手势监听与处理的方法
- 【MySQL】通过SQL_Thread快速恢复binlog
- 渗透系列之flask框架开启debug模式漏洞分析
- Android之ImageSwitcher的实例详解
- Android中HTTP请求中文乱码解决办法
- Android编程之播放器MediaPlayer实现均衡器效果示例
- Android studio点击跳转WebView详解
- Android webveiw 出现栈错误解决办法
- Android开发之实现手势滑动的功能
- Android编程实现带有单选按钮和复选按钮的dialog功能示例
- Android中Retrofit 2.0直接使用JSON进行数据交互
- Android自定义Drawable实现圆形和圆角