这周小伙伴突然让我帮他写一个刷票小程序,作为刚入门的小菜鸟表示有点压力,不过在了解了情况后发现还是可以实现的.
通过分析投票网站的流程后,发现并不需要批量注册,只需要不记名的选择支持的人物进行投票提交.
于是,我的初步思路是分析页面的请求地址和请求参数,然后通过java的java.net.URLConnection和定时器java.util.Timer。定时的向服务器发送http请求,从而达到机器投票功能。
由于之前没用过上述的2个java类,所以查阅jdk1.6手册了解了一下:
java.net.URLConnection:The abstract classURLConnection
is the superclass of all classes that represent a communications link between the application and a URL. Instances of this class can be used both to read from and to write to the resource referenced by the URL. (这个抽象类URLConnection是所有代表在应用和url之间的通信链接的类的父类。该类的实例能够用来向url所引用的资源读取和写入。)
java.net.HttpURLConnection:Each HttpURLConnection instance is used to make a single request but the underlying network connection to the HTTP server may be transparently shared by other instances. Calling the close() methods on the InputStream or OutputStream of an HttpURLConnection after a request may free network resources associated with this instance but has no effect on any shared persistent connection. Calling the disconnect() method may close the underlying socket if a persistent connection is otherwise idle at that time.(每个HttpURLConnection 实例用来创建单个请求,但是与http服务器的底层网络连接可以被其他的实例透明地共享。发送请求之后调用HttpURLConnection 的输入输出流的close()方法可以释放与这个实例相关的网络资源,但对于任何共享的持久连接没有影响。如果一个持久连接处于空闲状态,那么调用disconnect()方法可能会关闭底层套接字)
那么如何创建一个HttpURLConnection 实例呢?
URL localURL = new URL("http://xxxxxxxx/sbhr/sbhr.php");
URLConnection connection = localURL.openConnection();
HttpURLConnection httpURLConnection = (HttpURLConnection)connection;
如果要使用 URL 连接进行输出,则需要设置将 DoOutput 标志设置为 true;如果不打算使用,则设置为 false。默认值为 false。
httpURLConnection.setDoOutput(true);
其他的一些设置如下(可参考http请求头):
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setRequestProperty("Accept-Charset", "utf-8");
httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
httpURLConnection.setRequestProperty("Content-Length", String.valueOf(parameterData.length()));
然后建立连接:(这里connect()函数实际上是建立了一个与服务端的tcp连接(第一次握手),还没有发送请求,而且此时会根据上述配置生成http请求头,所以必须在connect()函数调用之前配置好属性)
httpURLConnection.connect();
然后是http正文:(正文的内容是通过outputStream流写入的, 实际上outputStream不是一个网络流,充其量是个字符串流,往里面写入的东西不会立即发送到网络,而是存在于内存缓冲区中,待outputStream流关闭时,根据输入的内容生成http正文。 至此,http请求的东西已经全部准备就绪,这里getOutputStream()会隐含调用connect()函数,所以上面的代码可以省略)
outputStream = httpURLConnection.getOutputStream();
outputStreamWriter = new OutputStreamWriter(outputStream);
outputStreamWriter.write(parameterData.toString()); //写入参数
outputStreamWriter.flush();
发送请求:(getInputStream()函数隐含了发送http请求,并且获取服务端的响应)
inputStream = httpURLConnection.getInputStream();
最后别忘了关闭输入输出流:
outputStream.close();
inputStream.close();
至此一次http请求全部发送完成。
接下来就是通过编写定时器来调用上述函数代码。
首先上述函数的类需要继承自TimerTask,实现run()方法.然后创建计时器定时调用。
Timer timer = new Timer();
HttpPostRequest task = new HttpPostRequest();
//程序运行后立刻执行任务,每隔3s执行一次
timer.schedule(task, 0, 3*1000);
经过测试可以实现投票功能。在跑了一个小时后,发现ip被禁止了.猜测是服务端限定了每个ip地址的投票数。那么这个时候就需要更改ip地址。
初步想法:使用代理间接地进行投票。于是在网上搜索了免费代理,然后进行配置.(了解了urlconnection过程后自然明白代理段代码应该是放到connect()函数之前配置).
System.setProperty("http.proxySet", "true");
System.setProperty("http.proxyHost","202.119.25.70");
System.setProperty("http.proxyPort","9999");
这里笨小葱(就是菜鸟我啦)是手工进行的更改ip。
初步设想:可以通过抓取代理网页的数据,生成代理信息的数组,然后根据服务端返回的信息,如果返回ip已禁止,那么就获取网络代理信息,更换代理ip.
具体实现等笨小葱过几天研究下爬虫技术再更新代码.
附上源码:
public class HttpPostRequest extends TimerTask{
public void run() {
String parameterDatas[] = {"sbhr_17167[]=3122283&sbhr_17167[]=3122316&sbhr_17167[]=3122306&sbhr_17167[]=3122297&sbhr_17167[]=3122295&sbhr_17166[]=3122298&sbhr_17165[]=3122299&sbhr_17164[]=3122303&sbhr_17163[]=3122305&sbhr_17163[]=3122282",
"sbhr_17167[]=3122283&sbhr_17167[]=3122316&sbhr_17167[]=3122290&sbhr_17167[]=3122288&sbhr_17166[]=3122277&sbhr_17165[]=3122299&sbhr_17164[]=3122303&sbhr_17163[]=3122305&sbhr_17163[]=3122282&sbhr_17163[]=3122279"};
String parameterData;
int rand=(int) (2*Math.random());
parameterData=parameterDatas[rand];
System.out.println(rand);
URL localURL;
OutputStream outputStream = null;
OutputStreamWriter outputStreamWriter = null;
InputStream inputStream = null;
InputStreamReader inputStreamReader = null;
BufferedReader reader = null;
StringBuffer resultBuffer = new StringBuffer();
String tempLine = null;
try {
System.setProperty("http.proxySet", "true");
System.setProperty("http.proxyHost","202.119.25.70");
System.setProperty("http.proxyPort","9999");
localURL = new URL("http://xxxxxxx/sbhr/sbhr.php");
URLConnection connection = localURL.openConnection();
HttpURLConnection httpURLConnection = (HttpURLConnection)connection;
httpURLConnection.setDoOutput(true);
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setRequestProperty("Accept-Charset", "utf-8");
httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
httpURLConnection.setRequestProperty("Content-Length", String.valueOf(parameterData.length()));
outputStream = httpURLConnection.getOutputStream();
outputStreamWriter = new OutputStreamWriter(outputStream);
outputStreamWriter.write(parameterData.toString());
outputStreamWriter.flush();
inputStream = httpURLConnection.getInputStream();
inputStreamReader = new InputStreamReader(inputStream,"utf-8");
reader = new BufferedReader(inputStreamReader);
while ((tempLine = reader.readLine()) != null) {
resultBuffer.append(tempLine);
}
System.out.println(resultBuffer);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (outputStreamWriter != null) {
try {
outputStreamWriter.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (inputStreamReader != null) {
try {
inputStreamReader.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
public class test {
private static void run() {
Timer timer = new Timer();
HttpPostRequest task = new HttpPostRequest();
//程序运行后立刻执行任务,每隔3s执行一次
timer.schedule(task, 0, 3*1000);
}
public static void main(String[] args) throws Exception {
run();
/* HttpPostRequest task = new HttpPostRequest();
task.run();*/
//timer.schedule(task,0,2*60*1000);
}
}
ps:由于是笨小葱工作一年后开始第一篇博客,虽然程序简单,但是笨小葱还是有点小激动。若是有什么不对的地方希望各位大拿提出来(要是语气温柔点就更好了),以后会每周更新一篇博客。