【小型系统】简单的刷票系统(突破IP限制进行投票)
【小型系統(tǒng)】簡單的刷票系統(tǒng)(突破IP限制進行投票)
一、前言
相信大家平時肯定會收到朋友發(fā)來的鏈接,打開一看,哦,需要投票。投完票后彈出一個頁面(恭喜您,您已經(jīng)投票成功),再次點擊的時候發(fā)現(xiàn),啊哈,您的IP(***.***.***.***)已經(jīng)投過票了,不能重復投票。這時候,我們可能會想,能不能突破ip地址的限制進行刷票呢?有了這樣的想法,那就去做吧,下面我將介紹我這個簡單的刷票系統(tǒng),僅供有需求的園友們參考。
二、系統(tǒng)設計
系統(tǒng)主要實現(xiàn)的是突破IP限制進行刷票,其中,由IP采集模塊負責從互聯(lián)網(wǎng)上爬取代理IP,放入阻塞隊列,該任務會定期執(zhí)行。之后由投票模塊從阻塞隊列中獲取IP,并進行設置,然后進行投票。系統(tǒng)流程圖如下:
三、系統(tǒng)技術
系統(tǒng)使用HttpClient + JSoup + 多線程來完成刷票,HttpClient用于進行投票,JSoup用于解析頁面,多線程技術用于分離任務,使得分工更加明確。使用到了生產(chǎn)者消費者模式,該模式直接使用BlockingQueue來實現(xiàn)。
四、系統(tǒng)介紹
系統(tǒng)主要分為三個模塊:
① IP采集模塊
② 投票模塊
③ IP信息模塊
其中,IP采集模塊主要是從互聯(lián)網(wǎng)爬取IP代理信息,并將該信息放入阻塞隊列,這樣就可以偽造IP,進行多次投票。
其中,投票模塊從IP采集模塊放入阻塞隊列取出IP信息,并設置代理,找到投票入口地址,然后進行投票操作。
其中,IP信息模塊主要是對爬取的IP信息進行了封裝,方便其他模塊進行操作。
4.1 IP采集模塊
IP采集模塊流程圖如下
幾點說明:
1.系統(tǒng)使用的代理IP站點URL為http://www.kuaidaili.com/,www.xicidaili.com。
2.提取IP信息為提取單條IP信息,并判斷歷史IP表是否已經(jīng)存在,若存在,表示之前已經(jīng)加入過此IP信息,則直接丟棄,反之,則加入隊列并加入歷史IP表。
3.此任務會定期開啟,如一個小時爬取一次代理IP。
4.2 投票模塊
投票模塊流程圖如下
幾點說明:
1.投票網(wǎng)站http://www.hnxdf.com/vote/,我們選取的第一位進行投票,分析出投票的入口為http://www.hnxdf.com/vote/iRadio_vote.asp?VoTeid=215。
2.根據(jù)IP采集模塊放入隊列的IP信息進行設置,然后進行投票。
4.3 IP信息模塊
此模塊主要對從網(wǎng)站爬取的IP信息進行了封裝,方便其他模塊進行操作。
五、系統(tǒng)代碼框架
系統(tǒng)的整個代碼框架如下
其中,bean包的IpInfo封裝了爬取的IP信息。
其中,entrance包的Vote為系統(tǒng)的入口。
其中,thread包的IPCollectTask為爬取代理IP任務,VoteThread為進行投票線程。
六、系統(tǒng)代碼
1.IpInfo.java
package com.hust.grid.leesf.bean;public class IpInfo {public IpInfo(String ipAddress, int port, String location,String anonymousType, String type, String confirmTime) {this(ipAddress, port, location, anonymousType, type, confirmTime, null,null);}public IpInfo(String ipAddress, int port, String location,String anonymousType, String type, String confirmTime,String getPostSupport, String responseSpeed) {this.ipAddress = ipAddress;this.port = port;this.location = location;this.anonymousType = anonymousType;this.type = type;this.confirmTime = confirmTime;this.getPostSupport = getPostSupport;this.responseSpeed = responseSpeed;}public String getIpAddress() {return ipAddress;}public void setIpAddress(String ipAddress) {this.ipAddress = ipAddress;}public int getPort() {return port;}public void setPort(int port) {this.port = port;}public String getLocation() {return location;}public void setLocation(String location) {this.location = location;}public String getAnonymousType() {return anonymousType;}public void setAnonymousType(String anonymousType) {this.anonymousType = anonymousType;}public String getType() {return type;}public void setType(String type) {this.type = type;}public String getConfirmTime() {return confirmTime;}public void setConfirmTime(String confirmTime) {this.confirmTime = confirmTime;}public String getGetPostSupport() {return getPostSupport;}public void setGetPostSupport(String getPostSupport) {this.getPostSupport = getPostSupport;}public String getResponseSpeed() {return responseSpeed;}public void setResponseSpeed(String responseSpeed) {this.responseSpeed = responseSpeed;}@Overridepublic boolean equals(Object anthor) {if (this == anthor) {return true;}if (anthor == null || getClass() != anthor.getClass()) {return false;}IpInfo ipInfo = (IpInfo) anthor;return (this.ipAddress.equals(ipInfo.ipAddress)&& this.port == ipInfo.port&& this.location.equals(ipInfo.location)&& this.anonymousType.equals(ipInfo.anonymousType)&& this.type.equals(ipInfo.type) && this.confirmTime.equals(ipInfo.confirmTime))&& this.getPostSupport.equals(ipInfo.getPostSupport)&& this.responseSpeed.equals(ipInfo.responseSpeed);}@Overridepublic int hashCode() {int hash = 5;hash = 89 * hash+ (this.ipAddress != null ? this.ipAddress.hashCode() : 0);hash = 89 * hash + this.port;hash = 89 * hash+ (this.location != null ? this.location.hashCode() : 0);hash = 89* hash+ (this.anonymousType != null ? this.anonymousType.hashCode(): 0);hash = 89 * hash + (this.type != null ? this.type.hashCode() : 0);hash = 89 * hash+ (this.confirmTime != null ? this.confirmTime.hashCode() : 0);hash = 89* hash+ (this.getPostSupport != null ? this.getPostSupport.hashCode(): 0);hash = 89* hash+ (this.responseSpeed != null ? this.responseSpeed.hashCode(): 0);return hash;}@Overridepublic String toString() {return "ipAddress = " + ipAddress + ", port = " + port + ", localtion = "+ location + ", anonymousType = " + anonymousType + ", type = " + type + ", confirmTime = " + confirmTime + ", getPostSupport = "+ getPostSupport + ", responseSpeed = " + responseSpeed;} private String ipAddress;private int port;private String location;private String anonymousType;private String type;private String confirmTime;private String getPostSupport;private String responseSpeed; }2.Vote.java
package com.hust.grid.leesf.entrance;import java.util.Timer; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue;import com.hust.grid.leesf.bean.IpInfo; import com.hust.grid.leesf.thread.IPCollectTask; import com.hust.grid.leesf.thread.VoteThread;public class Vote {private BlockingQueue<IpInfo> ipInfoQueue;private IPCollectTask ipCollectTask;private VoteThread voteThread;public Vote() {ipInfoQueue = new LinkedBlockingQueue<IpInfo>();ipCollectTask = new IPCollectTask(ipInfoQueue);voteThread = new VoteThread(ipInfoQueue);}public void vote() {Timer timer = new Timer();long delay = 0;long period = 1000 * 60 * 60;// 每一個小時采集一次ip timer.scheduleAtFixedRate(ipCollectTask, delay, period);// 開啟投票任務 voteThread.start();}public static void main(String[] args) {Vote vote = new Vote();vote.vote();} }3.IPCollectTask.java
package com.hust.grid.leesf.thread;import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.TimerTask; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue;import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements;import com.hust.grid.leesf.bean.IpInfo;public class IPCollectTask extends TimerTask {private BlockingQueue<IpInfo> ipInfoQueue; // 連接生產(chǎn)者與消費者的阻塞隊列private List<IpInfo> historyIpLists; // 記錄已經(jīng)獲取的ip信息public IPCollectTask(BlockingQueue<IpInfo> ipInfoQueue) {this.ipInfoQueue = ipInfoQueue;this.historyIpLists = new ArrayList<IpInfo>();}/*** 獲取www.xicidaili.com的ip地址信息*/public void getXiCiDaiLiIpLists() {String url = "http://www.xicidaili.com/";String host = "www.xicidaili.com";Document doc = getDocumentByUrl(url, host);// 解析頁面的ip信息 parseXiCiDaiLiIpLists(doc);}/*** 解析頁面的ip信息* * @param doc*/public void parseXiCiDaiLiIpLists(Document doc) {Elements eleLists = doc.getElementsByTag("tbody");Element tbody = eleLists.get(0); // 獲取tbodyElements trLists = tbody.children();Element ele = null;for (int i = 0; i < trLists.size(); i++) {if ((i % 22 == 0) || (i % 22 == 1)) { // 去掉不符合條件的項continue;}ele = trLists.get(i);Elements childrenList = ele.children();String ipAddress = childrenList.get(1).text();int port = Integer.parseInt(childrenList.get(2).text());String location = childrenList.get(3).text();String anonymousType = childrenList.get(4).text();String type = childrenList.get(5).text();String confirmTime = childrenList.get(6).text();IpInfo ipInfo = new IpInfo(ipAddress, port, location,anonymousType, type, confirmTime);putIpInfo(ipInfo);}}/*** 將ip信息放入隊列和歷史記錄中* * @param ipInfo*/private void putIpInfo(IpInfo ipInfo) {if (!historyIpLists.contains(ipInfo)) { // 若歷史記錄中不包含ip信息,則加入隊列中// 加入到阻塞隊列中,用作生產(chǎn)者try {ipInfoQueue.put(ipInfo);} catch (InterruptedException e) {// TODO Auto-generated catch block e.printStackTrace();}// 加入歷史記錄中 historyIpLists.add(ipInfo);}}/*** 根據(jù)網(wǎng)頁Document解析出ip地址信息* * @param doc*/private void parseKuaiDaiLiIpLists(Document doc) {Elements eleLists = doc.getElementsByTag("tbody");Element tbody = eleLists.get(0); // 獲取tbodyElements trLists = tbody.children(); // 獲取十條ip記錄for (Element tr : trLists) { // 遍歷trElements tdElements = tr.children(); // tr中的td包含了具體的信息String ipAddress = tdElements.get(0).text();int port = Integer.parseInt(tdElements.get(1).text());String anonymousType = tdElements.get(2).text();String type = tdElements.get(3).text();String getPostSupport = tdElements.get(4).text();String location = tdElements.get(5).text();String responseSpeed = tdElements.get(6).text();String confirmTime = tdElements.get(7).text();IpInfo ipInfo = new IpInfo(ipAddress, port, location,anonymousType, type, confirmTime, getPostSupport,responseSpeed);putIpInfo(ipInfo);}}/*** 根據(jù)提供的url和host來獲取頁面信息* * @param url* @param host* @return*/private Document getDocumentByUrl(String url, String host) {Document doc = null;try {doc = Jsoup.connect(url).header("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0").header("Host", host).timeout(5000).get();} catch (IOException e) {e.printStackTrace();}return doc;}/*** 獲取http://www.kuaidaili.com/free/的ip*/private void getKuaiDaiLiFreeIpLists() {// 第一次訪問,需解析總共多少頁String baseUrl = "http://www.kuaidaili.com/free/inha/";String host = "www.kuaidaili.com";Document doc = getDocumentByUrl(baseUrl, host);// 解析ip信息 parseKuaiDaiLiIpLists(doc);Element listNav = doc.getElementById("listnav");// 獲取listnav下的li列表Elements liLists = listNav.children().get(0).children();// 獲取含有多少頁的子元素Element pageNumberEle = liLists.get(liLists.size() - 2);// 解析有多少頁int pageNumber = Integer.parseInt(pageNumberEle.text());// 拼接成其他頁的訪問地址for (int index = 1; index <= pageNumber; index++) {baseUrl = baseUrl + index;doc = getDocumentByUrl(baseUrl, host);parseKuaiDaiLiIpLists(doc);// 休眠一秒fallSleep(1);}}/*** 獲取www.kuaidaili.com/proxylist/的ip*/private void getKuaiDaiLiIpLists() {int start = 1;String baseUrl = "http://www.kuaidaili.com/proxylist/";String host = "www.kuaidaili.com";while (start <= 10) { // 爬取10頁String url = baseUrl + start + "/";Document doc = getDocumentByUrl(url, host);// 解析ip信息 parseKuaiDaiLiIpLists(doc);start++;// 休眠一秒fallSleep(1);}}/*** 進行休眠*/private void fallSleep(long seconds) {try {Thread.sleep(seconds * 1000);} catch (InterruptedException e) {e.printStackTrace();}}@Overridepublic void run() {// getKuaiDaiLiFreeIpLists();System.out.println("IPCollect task is running");getKuaiDaiLiIpLists();getXiCiDaiLiIpLists();}public BlockingQueue<IpInfo> getIpInfoQueue() {return ipInfoQueue;}public static void main(String[] args) {BlockingQueue<IpInfo> queue = new LinkedBlockingQueue<IpInfo>();IPCollectTask task = new IPCollectTask(queue);Thread thread = new Thread(task);thread.start();try {Thread.sleep(30 * 1000);} catch (InterruptedException e) {// TODO Auto-generated catch block e.printStackTrace();}System.out.println("queue size is " + queue.size());try {while (!queue.isEmpty()) {System.out.println(queue.take());}} catch (InterruptedException e) {e.printStackTrace();}System.out.println("historyList size is " + task.historyIpLists.size());} }4.VoteThread.java
package com.hust.grid.leesf.thread;import java.io.IOException; import java.util.concurrent.BlockingQueue;import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.conn.params.ConnRoutePNames; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.util.EntityUtils;import com.hust.grid.leesf.bean.IpInfo;public class VoteThread extends Thread {private BlockingQueue<IpInfo> ipInfoQueue;public VoteThread(BlockingQueue<IpInfo> ipInfoQueue) {this.ipInfoQueue = ipInfoQueue;}@Overridepublic void run() {HttpClient client = new DefaultHttpClient();HttpParams params = client.getParams();HttpConnectionParams.setConnectionTimeout(params, 10000);HttpConnectionParams.setSoTimeout(params, 15000);HttpResponse response = null;HttpGet get = null;HttpEntity entity = null;HttpHost proxy = null;while (true) {IpInfo ipInfo = null;try {ipInfo = ipInfoQueue.take();} catch (InterruptedException e1) {// TODO Auto-generated catch block e1.printStackTrace();}proxy = new HttpHost(ipInfo.getIpAddress(), ipInfo.getPort());client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,proxy);get = new HttpGet("http://www.hnxdf.com/vote/iRadio_vote.asp?VoTeid=215");get.addHeader("Host", "www.hnxdf.com");get.addHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0");try {response = client.execute(get);entity = response.getEntity();byte[] bytes = EntityUtils.toByteArray(entity);// 對響應內(nèi)容編碼格式進行轉化,統(tǒng)一成utf-8格式String temp = new String(bytes, "gbk");byte[] contentData = temp.getBytes("utf-8");System.out.println(new String(contentData));System.out.println("-----------------------------------");} catch (ClientProtocolException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}} }七、系統(tǒng)總結
此系統(tǒng)很簡單,想清楚思路之后很快就能夠寫出代碼,系統(tǒng)運行時,由于代理IP站點提供的免費IP質(zhì)量不是太高,有效的IP地址還是很少,所有效果不是特別理想,此系統(tǒng)功能也很簡單,但是各位園友可以在此基礎上去發(fā)揮自己的想象力,定制屬于自己的投票系統(tǒng)。
八、總結
至此,整個系統(tǒng)分析就已經(jīng)完成了,其中,圖也畫得不是太規(guī)范,還請各位園友海涵。也謝謝各位園友觀看。
ps:整個工程(包含必要的jar文件)已經(jīng)上傳到GitHub上,歡迎各位園友訪問:https://github.com/leesf/TicketBrushSystem
總結
以上是生活随笔為你收集整理的【小型系统】简单的刷票系统(突破IP限制进行投票)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 百度冰桶算法4.5更新:发力打击恶劣广告
- 下一篇: Akka学习笔记:Actors介绍