簡單的定時刷票小程式
這周小夥伴突然讓我幫他寫一個刷票小程式,作為剛入門的小菜鳥表示有點壓力,不過在瞭解了情況後發現還是可以實現的.
通過分析投票網站的流程後,發現並不需要批量註冊,只需要不記名的選擇支援的人物進行投票提交.
於是,我的初步思路是分析頁面的請求地址和請求引數,然後通過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 例項呢?
<span style="font-size:14px;"><span style="font-size:14px;">URL localURL = new URL("http://xxxxxxxx/sbhr/sbhr.php"); URLConnection connection = localURL.openConnection(); HttpURLConnection httpURLConnection = (HttpURLConnection)connection;</span></span>
如果要使用 URL 連線進行輸出,則需要設定將 DoOutput 標誌設定為 true;如果不打算使用,則設定為 false。預設值為 false。
<span style="font-size:14px;"><span style="font-size:14px;"> 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()));</span></span>
然後建立連線:(這裡connect()函式實際上是建立了一個與服務端的tcp連線(第一次握手),還沒有傳送請求,而且此時會根據上述配置生成http請求頭,所以必須在connect()函式呼叫之前配置好屬性)
<span style="font-size:14px;"><span style="font-size:14px;">httpURLConnection.connect();
</span></span>
然後是http正文:(正文的內容是通過outputStream流寫入的, 實際上outputStream不是一個網路流,充其量是個字串流,往裡面寫入的東西不會立即傳送到網路,而是存在於記憶體緩衝區中,待outputStream流關閉時,根據輸入的內容生成http正文。 至此,http請求的東西已經全部準備就緒,這裡getOutputStream()會隱含呼叫connect()函式,所以上面的程式碼可以省略)
<span style="font-size:14px;"><span style="font-size:14px;"> outputStream = httpURLConnection.getOutputStream();
outputStreamWriter = new OutputStreamWriter(outputStream);
<span style="font-family:Comic Sans MS;"> </span>outputStreamWriter.write(parameterData.toString()); //寫入引數
<span style="font-family:Comic Sans MS;"> </span>outputStreamWriter.flush();</span></span>
傳送請求:(getInputStream()函式隱含了傳送http請求,並且獲取服務端的響應)
<span style="font-size:14px;"><span style="font-size:14px;">inputStream = httpURLConnection.getInputStream();</span></span>
最後別忘了關閉輸入輸出流:
<span style="font-size:14px;"><span style="font-size:14px;"> outputStream.close();
inputStream.close();</span></span>
至此一次http請求全部發送完成。
接下來就是通過編寫定時器來呼叫上述函式程式碼。
首先上述函式的類需要繼承自TimerTask,實現run()方法.然後建立計時器定時呼叫。
<span style="font-size:14px;"><span style="font-size:14px;"> Timer timer = new Timer();
HttpPostRequest task = new HttpPostRequest();
//程式執行後立刻執行任務,每隔3s執行一次
timer.schedule(task, 0, 3*1000); </span></span>
經過測試可以實現投票功能。在跑了一個小時後,發現ip被禁止了.猜測是服務端限定了每個ip地址的投票數。那麼這個時候就需要更改ip地址。
初步想法:使用代理間接地進行投票。於是在網上搜索了免費代理,然後進行配置.(瞭解了urlconnection過程後自然明白代理段程式碼應該是放到connect()函式之前配置).
<span style="font-size:14px;"><span style="font-size:14px;"> System.setProperty("http.proxySet", "true");
System.setProperty("http.proxyHost","202.119.25.70");
System.setProperty("http.proxyPort","9999");
</span></span>
這裡笨小蔥(就是菜鳥我啦)是手工進行的更改ip。
初步設想:可以通過抓取代理網頁的資料,生成代理資訊的陣列,然後根據服務端返回的資訊,如果返回ip已禁止,那麼就獲取網路代理資訊,更換代理ip.
具體實現等笨小蔥過幾天研究下爬蟲技術再更新程式碼.
附上原始碼:
<span style="font-size:14px;"><span style="font-size:14px;">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();
}
}
}
}
}
</span></span>
<span style="font-size:14px;"><span style="font-size:14px;">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);
}
}</span></span>
ps:由於是笨小蔥工作一年後開始第一篇部落格,雖然程式簡單,但是笨小蔥還是有點小激動。若是有什麼不對的地方希望各位大拿提出來(要是語氣溫柔點就更好了),以後會每週更新一篇部落格。