- 浏览: 224360 次
- 性别:
- 来自: 深圳
文章分类
- 全部博客 (212)
- 架构师-01-文档目录 (3)
- 架构师-02-组织 (7)
- 架构师-03-实施 (35)
- 架构师-04-监督 (14)
- 架构师-05-工具 (29)
- 架构师-09-引用文集 (63)
- 专题-01-微博应用 (5)
- 专题-02-GoogleEarth (1)
- 专题-03-运行维护 (9)
- 专题-04-经纪人营平 (3)
- 专题-05-RCP&RAP (5)
- 专题-06-框架PK (3)
- 专题-07-Android (13)
- 专题-08-UI (3)
- 专题-liferay6 (6)
- 专题-extjs4 (3)
- 专题-CXF (3)
- 专题-封闭网络的社会化 (0)
- 扯谈 (4)
- 外包 (9)
- 专题-C++ (4)
- 专题-09-BI (2)
- jquery&easyui (2)
- 专题-搜索引擎 (1)
最新评论
-
brighter:
oMapper.configure(Deserializati ...
jackson 抛出 bean 中没有定义字段的错误,只好用 gson -
PassFeed_free:
public Bitmap decode(ImageDecod ...
android universalimageloader 几点改进 -
PassFeed_free:
楼主你好, 请问这个库, 在大屏显示高清图片 ,listvie ...
android universalimageloader 几点改进 -
yonghong:
楼主只是揣测
JIRA4.1 升级到 JIRA5.1 -
abdxj:
"Could NOT parse license t ...
JIRA4.1 升级到 JIRA5.1
由于生活中需要对网站上的某张图片投票决定排名,无可避免地想起了做个自动投票机器人。
经过一天的尝试,三种方案:
(1)保存投票页面到本地,分析代码,直接用 js 和 ajax 循环提交,每次循环中间随机休眠几秒。一开始居然有效,不过好景不长,第二天就被网站改了页面,不能直接提交了。
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>
自动投票机器人一
</title>
<link rel="stylesheet" href="style.css" type="text/css" media="screen">
<script type="text/javascript">
var counters=0;
var xmlHttp;
function S_xmlhttprequest(){
if(window.ActiveXObject){
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
} else if(window.XMLHttpRequest){
xmlHttp = new XMLHttpRequest();
}
}
function vote(){
url =1;//id
S_xmlhttprequest();
xmlHttp.open("GET","http://www.xxxx.com/work/vote.php?id="+url+"&"+Math.random(),true);
xmlHttp.send(null);
alert(' 投票成功!\n 谢谢您的支持!');
counters++;
document.getElementById("counter").innerText=counters;
setTimeout("vote()",nextTime());
}
function Workspace_OnLoad() {
setTimeout("vote()",1000);
}
function nextTime(){
var vNum=1000;
vNum = Math.random();
vNum = Math.round(vNum*60000);
return vNum;
}
</script>
</head>
<body class="bgcolor" onload="Workspace_OnLoad();">
<div align="center">
<table class="bgjpg" align="center" border="0" cellpadding="0" cellspacing="0"
width="100%">
<tbody>
<tr height="10">
<td>
</td>
</tr>
<tr>
<td height="30">
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
(2)发现需要提交表单到服务器,而不是直接发送GET请求,并且有 cookie 检查校验码,尝试用 java 编程,好象没成功,但理论上可行。
- 获取校验码图片
- tesseract OCR 解析校验码图片
- 尝试提交模拟表单
- 需要的 jar 包和 Tesseract OCR在网上搜。
package A; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.httpclient.methods.PostMethod; import com.overseas.ocr.ImageFilter; import com.overseas.ocr.ImageIOHelper; import com.overseas.sys.InitEnv; import com.overseas.util.PicUtil; import net.sourceforge.tess4j.*; public class TesseractExample { public int success=0; public static void main(String[] args) { //File imageFile = new File("eurotext.tif"); //Tesseract instance = Tesseract.getInstance(); // JNA Interface Mapping // Tesseract1 instance = new Tesseract1(); // JNA Direct Mapping try { TesseractExample t =new TesseractExample(); t.doit() ; // String result = instance.doOCR(imageFile); // System.out.println(result); } catch (Exception e) { System.err.println(e.getMessage()); } } private void doit() { int counter =1000000; for(int i=0;i<counter;i++){ try{ Thread.sleep((int)(Math.random()*50000)); }catch(Exception e){ e.printStackTrace(); } String decodeText =decode(); System.out.println("Start excute..."+i+"====="+decodeText); if(decodeText==null || decodeText.trim().length()<4 ){ continue; //next times } decodeText =decodeText.trim(); if(decodeText.length()>4) decodeText =decodeText.substring(0,4); try{ int code =Integer.parseInt(decodeText); // submit vote vote(code); System.out.println("call vote..."+code); }catch(Exception e){ continue; } } } private void vote(int code) { HttpClient httpClient = new HttpClient(); String url = "http://www.xxxx.com/work/chick.php?id=1"; PostMethod postMethod = new PostMethod(url); // 填入各个表单域的值 NameValuePair[] data = { new NameValuePair("numtext", Integer.toString(code)), new NameValuePair("submit", "确认"), }; // 将表单的值放入postMethod中 postMethod.setRequestBody(data); // 执行postMethod int statusCode = 0; try { statusCode = httpClient.executeMethod(postMethod); } catch (HttpException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } // HttpClient对于要求接受后继服务的请求,象POST和PUT等不能自动处理转发 // 301或者302 if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY || statusCode == HttpStatus.SC_MOVED_TEMPORARILY) { // 从头中取出转向的地址 Header locationHeader = postMethod.getResponseHeader("location"); String location = null; if (locationHeader != null) { location = locationHeader.getValue(); System.out.println("The page was redirected to:" + location); } else { System.err.println("Location field value is null."); } return; } else { System.out.println(postMethod.getStatusLine()); String str = ""; try { str = postMethod.getResponseBodyAsString(); System.out.println("Success! ooooooooooooooooo"+success++); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("======================================================"); System.out.println(utf8Togb2312(str)); } postMethod.releaseConnection(); return ; } private String decode() { String url = "http://www.xxxx.com/work/che.php?"+Math.random(); InputStream instream = InitEnv.class.getResourceAsStream(InitEnv.CERTPATH); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); String protocol = "http"; byte[] b = null; try { if (url.startsWith("https")) { protocol = "https"; } PicUtil.getPic(protocol, url, 80, "", instream,outputStream); b = outputStream.toByteArray(); ImageFilter imageFilter = new ImageFilter(new ByteArrayInputStream(b)); outputStream.close(); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ImageIOHelper.createImage(imageFilter.changeGrey(), byteArrayOutputStream); File file = new File("C:\\temp\\ocr.tiff "); if (!file.exists()) { file.createNewFile(); } DataOutputStream to = new DataOutputStream(new FileOutputStream(file)); byteArrayOutputStream.writeTo(to); byteArrayOutputStream.close(); Tesseract instance = Tesseract.getInstance(); String result = instance.doOCR(file); return result; } catch (Exception e) { e.printStackTrace(); return null; } } private String utf8Togb2312(String str){ StringBuffer sb = new StringBuffer(); for(int i=0; i<str.length(); i++) { char c = str.charAt(i); switch (c) { case '+': sb.append(' '); break; case '%': try { sb.append((char)Integer.parseInt( str.substring(i+1,i+3),16)); } catch (NumberFormatException e) { throw new IllegalArgumentException(); } i += 2; break; default: sb.append(c); break; } } // Undo conversion to external encoding String result = sb.toString(); String res=null; try{ byte[] inputBytes = result.getBytes("8859_1"); res= new String(inputBytes,"UTF-8"); } catch(Exception e){} return res; } }
(3)既然前面两种方法都没办法成功,尝试用第三种方法吧,比较复杂,但理论上一定可用(做出来后才发现,投票时间已经结束,无法验证)
- greasemonkey
- ajax 取得图片
- 上传到图片解析服务器(需要搭建专门 OCR 解析服务器)
- 从解析服务器返回解析后的校验码
- 填充表单校验码,提交
// ==UserScript== // @name AutoVote // @namespace autovote // @include http://www.xxxx.com/work/workshow.php?id=1 // @include http://www.xxxx.com/work/index.php // @include http://www.xxxx.com/work/show.php // ==/UserScript== var VOTE_URL='http://www.xxxx.com/work/workshow.php?id=1'; var IMG_URL ='http://www.xxxx.com/work/che.php?'; var DECODE_SERVER_URL ='http://localhost/decode/image'; var MAX_COUNT =10; var counter =0; function start() { // 1. direct to vote page if(counter>MAX_COUNT) return; if(document.location.href!=VOTE_URL){ document.location.href =VOTE_URL; } document.getElementById('title').style.display="block"; // 2. get code from PLUS_VOTE_SERVER load_image(); // 3. full code value // 4. submit // 5. open new window // 6. close current windows } function load_image() { if(counter>MAX_COUNT) return; counter++; alert("2. get code from PLUS_VOTE_SERVER"); var imageSrc = IMG_URL+Math.random(1); GM_xmlhttpRequest({method: 'GET', url: imageSrc, overrideMimeType: 'text/plain; charset=x-user-defined', onload: function(response) { decode_image(response.responseText); } }); } function decode_image(data) { var textbox = document.getElementById('numtext'); textbox.value = 'working...'; upload(data); } function upload(data) { var darray=data_array(data); GM_xmlhttpRequest({ method: 'POST', headers:{'Content-type':'application/x-www-form-urlencoded'}, url: DECODE_SERVER_URL, data: 'data='+darray, onload: function(response) { submit_form(response.responseText); } }); } function submit_form(data) { if(data==-1){ load_image(); } var textbox = document.getElementById('numtext'); textbox.value = data; var form1 = document.forms[0]; //alert("submit ..."); form1.submit(); } function data_array(data) { var data_array = []; for (var i = 0; i < data.length; i++) data_array.push(data[i].charCodeAt(0) & 0xff); return data_array; } start();
import java.util.Map; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.text.SimpleDateFormat; import java.util.Date; import javaplus.base.BaseRestSpringController; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import net.sourceforge.tess4j.Tesseract; import net.sourceforge.tess4j.TesseractException; import org.springframework.beans.propertyeditors.CustomDateEditor; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.validation.BindingResult; import org.springframework.validation.Validator; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.webframework.page.Page; import org.webframework.web.scope.Flash; import java.util.*; import javaplus.base.*; import javaplus.util.*; import org.webframework.util.*; import org.webframework.web.util.*; import org.webframework.page.*; import org.webframework.page.impl.*; import com.company.project.model.*; import com.company.project.dao.*; import com.company.project.service.*; import com.company.project.vo.query.*; import com.overseas.ocr.ImageFilter; import com.overseas.ocr.ImageIOHelper; /** * @author mmm email:mmm(a)gmail.com * @version 1.0 * @since 1.0 */ @Controller @RequestMapping("/decode") public class DecodeImageController extends BaseRestSpringController<UserInfo,java.lang.Long>{ private UserInfoManager userInfoManager; private final String LIST_ACTION = "redirect:/userinfo"; /** * 增加setXXXX()方法,spring就可以通过autowire自动设置对象属性,注意大小写 **/ public void setUserInfoManager(UserInfoManager manager) { this.userInfoManager = manager; } /** binder用于bean属性的设置 */ @InitBinder public void initBinder(WebDataBinder binder) { binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true)); } /** * 增加了@ModelAttribute的方法可以在本controller方法调用前执行,可以存放一些共享变量,如枚举值,或是一些初始化操作 */ @ModelAttribute public void init(ModelMap model) { model.put("now", new java.sql.Timestamp(System.currentTimeMillis())); } @RequestMapping(value="/image",method=RequestMethod.POST) public String upload(HttpServletRequest request , @RequestParam("data") String data ) throws Exception { String code ="-1"; if(data==null || data=="") { return code; } System.out.println(data); File file =createTempFile(convert(data)); code =decode(file); return code; } private static byte[] convert(String s) { String[] split = s.split(","); byte[] c=new byte[split.length]; for(int i=0;i<split.length;i++) { c[i]=Byte.parseByte(split[i]); System.out.println(c[i]); } System.out.println(); return c; } private String decode(File file){ String decodeText; try { Tesseract instance = Tesseract.getInstance(); decodeText = instance.doOCR(file); if(decodeText==null || decodeText.trim().length()<4 ){ return null; } decodeText =decodeText.trim(); if(decodeText.length()>4) decodeText =decodeText.substring(0,4); return decodeText; } catch (TesseractException e) { e.printStackTrace(); return null; } } private File createTempFile(byte[] b){ try{ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ImageFilter imageFilter = new ImageFilter(new ByteArrayInputStream(b)); ImageIOHelper.createImage(imageFilter.changeGrey(),byteArrayOutputStream); File file = new File("C:\\temp\\ocr.tiff"); if (!file.exists()) { file.createNewFile(); } DataOutputStream to = new DataOutputStream(new FileOutputStream(file)); byteArrayOutputStream.writeTo(to); byteArrayOutputStream.close(); return file; }catch(Exception e){ e.printStackTrace(); return null; } } }
第三种方法在理论上可行,但要注意获取图片后,要分析代码,或许其中不仅仅是图片数据,还包含了解 cookie 的写入,需要具体对应每一个投票网站具体分析。
***然而始料未及的是写了许多代码,在调试的时候才突然发现,取得检验图片的数据格式中,末尾包含了明文的4位校验码,NND不知是程序员留的后门还是写入 cookie 需要,忽然发现自己就很失败,被狗血了。
从而说明分析获得的数据是多么重要了。
天不负苦心人,投票服务器又开了,是时候上场了,一台机器一小时刷了上万票,有需要即可多开几台机器,要多少票都是如此简单,果然不是一般的爽。(不敢刷太多,树大招风(:)
发表评论
-
集成Hibernate Search做全文检索
2014-05-03 15:42 534集成Hibernate Search做全文检索 原文来自 h ... -
Base64扩展,自定义字串和顺序
2012-12-06 11:10 1675Base64很标准,sun 的 jdk 包含了实现,JS ... -
避免跨域问题 ajax proxy
2012-12-04 09:31 810前端全是 AJAX 框架,其中用到一些动态 API 调用,动静 ... -
Arc-03-32 用户事件跟踪
2012-07-05 15:25 722参照 clickstream 项目,保存到数据库 1.实现原 ... -
CXF 结合jaxb返回json字符串时,当属性为数值型字符串时,没有双引号问题
2012-06-04 14:00 2090问题:CXF 结合jaxb返回json字符串时,当属性为数值型 ... -
Arc-03-30-Postgresql 数据导出到Sqlite
2012-05-15 09:39 0用了空间数据库 PostGis,所以用了 Postgresql ... -
extjs4 有用的资源链接
2012-05-12 01:07 645对 Ext 扩展的一些小总结 http://laodaoba ... -
Arc-03-29 CXF 实现 REST 方式上传文件
2012-04-09 00:46 3062CXF 实现 REST 方式上传文件 /** ... -
Arch-03-28 Jndi 配置 Mongodb jetty 实现
2012-03-06 15:20 1619使用 springdata mongodb,直接使用 spri ... -
Arc-03-27-FTP 服务和客户端小结
2012-01-29 18:08 764尽管局域网中传输文件有 n 多方法,samba,webdav, ... -
Arc-03-26-相册图片短码编码实现
2011-12-29 17:01 908应用中需要上传用户图片,不想数据库单独维护图片的信息,想直接从 ... -
Arch-03-25-JAVA异常列表
2011-12-20 09:37 909ClassCastException 类型转换异常类 ... -
Arch-03-24- Spring Security 应用
2011-11-08 17:47 1432Spring Security 用了几次,还没有在集群环境中使 ... -
Arch-03-23- ActiveMQ 实践
2011-10-28 15:03 819ActiveMQ 到了非用不可的地步了,学习一下吧。主要用途定 ... -
Arch-03-22- 编程实现多数据源,水平切分,异种数据源
2011-10-20 17:35 810在 Spring 的框架下,通过编程实现多数据源(JDBC), ... -
Arch-03-21- Spring 中调用 Guice 中的注入
2011-10-06 20:27 875当 spring 和 guice 共同存在一个项目中,且 sp ... -
Arch-03-20- Shindig 实践
2011-10-06 16:53 776之前已经抄录了几篇网文,初步了解 shindig 功能与特性, ... -
Arch-03-19- NoSQL实践
2011-09-26 10:27 1332虽然对新技术甚为谨慎,但目前大家所做的伪 sns 的 nosq ... -
Arch-03-18- 用 Mysql-proxy 搭建 MySQL 集群
2011-09-20 10:21 877对应上篇 pgpool2 搭建 postgresql 集群,因 ... -
Arch-03-17- 用 pgpool-II 搭建 PostgreSQL 集群
2011-09-19 10:00 3011(一)方案 尽管做数据库 postgresql 集群的方式 ...
相关推荐
Arch-Linux-Install-ScriptArch_Linux_安装脚本_Arch-Linux-Installer
Next Generation On Demand (NGOD) Asset Architecture Comcast-SP-NGOD-ASSET-ARCH-I03-100731 Issued July 31, 2010
"cacti-plugin-arch-2.0.tar.gz" 是一个针对Cacti的插件包,用于扩展Cacti的功能,提供更丰富的监控选项。此插件名为“Arch”,可能是对系统架构或性能分析相关的增强。 该压缩包文件的名称表明它是版本2.0,通常这...
基于android8.1源码平台中生成的jar,亲测可用!!!!
变系数ARCH-M模型是时间序列分析领域的重要研究对象,其核心在于通过截面似然估计来检验模型是否具有条件异方差性(ARCH效应)。首先,我们来探讨一下条件异方差性的概念,它是指在时间序列分析中,随机变量的条件...
文档《UPnP™ Device Architecture 1.1》是由UPnP论坛的贡献成员编写的,发布日期为2008年10月15日。该文档详细描述了UPnP设备架构的技术细节,包括网络发现、地址分配、设备广告和搜索等。文档中提到的UPnP设备架构...
OpenRISC是一种开源的指令集架构(ISA),它致力于提供一个简单、易于实现和使用的处理器核心,适用于广泛的嵌入式系统和应用程序。该文档是关于OpenRISC1000架构的手册,版本号为1.0,修订号为0,发布日期为2012年...
资源来自pypi官网。 资源全名:arch-4.9.1-cp36-cp36m-macosx_10_6_intel.whl
Next Generation On Demand (NGOD) Overall Architecture Comcast-SP-NGOD-GEN-ARCH-I03-100731 Issued July 31, 2010
标题中的"Python库 | arch-4.11-cp35-cp35m-win32.whl"指的是一个特定版本的Python库,名为“arch”,版本为4.11,适用于Python 3.5解释器(由"cp35"标识),且是针对32位Windows操作系统("win32")的。"cp35m"表示...
NULL 博文链接:https://cnmqw.iteye.com/blog/1243596
**arch-box** 是一个专为Arch Linux自动化构建的项目,旨在为不同的虚拟化和容器环境提供预配置的Arch Linux镜像。它支持多种提供程序,包括 **Vagrant** 和 **VirtualBox**,同时也可能适用于 **QEMU** 等其他虚拟...
拱安装脚本我试图自动化Arch Linux安装过程的一部分这主要供我自己使用。...从安装ISO获取脚本使用wget https://raw.githubusercontent.com/tpenders/arch-install-script/master/after-chroot.sh获取脚本,然后wget ...
python库。 资源全名:arch-4.8.0-cp27-cp27m-win32.whl
安装克隆这个仓库git clone https://github.com/jannispinter/arch-openwrt-buildroot.git构建 docker 镜像 cd arch-openwrt-buildrootdocker build -t= " arch-openwrt-buildroot:trunk " . 最后的点表示Dockerfile...
资源来自pypi官网。 资源全名:arch-4.17-cp39-cp39-manylinux1_x86_64.whl
我的Arch_Linux安装步骤和日志_Arch-Linux-install-log
arch-model-estimation_solution.ipynb
arch-snds100驱动程序是专为s3c44b0x处理器设计的一款核心驱动,用于管理和优化硬件资源的使用。s3c44b0x是一款由Samsung生产的微处理器,常用于嵌入式系统,如工业控制、移动设备和消费电子产品等。驱动程序在操作...