【小型系統】簡單的刷票系統(突破IP限制進行投票)

1、前言  html

  相信你們平時確定會收到朋友發來的連接,打開一看,哦,須要投票。投完票後彈出一個頁面(恭喜您,您已經投票成功),再次點擊的時候發現,啊哈,您的IP(***.***.***.***)已經投過票了,不能重複投票。這時候,咱們可能會想,能不能突破ip地址的限制進行刷票呢?有了這樣的想法,那就去作吧,下面我將介紹我這個簡單的刷票系統,僅供有需求的園友們參考。java

2、系統設計node

  系統主要實現的是突破IP限制進行刷票,其中,由IP採集模塊負責從互聯網上爬取代理IP,放入阻塞隊列,該任務會按期執行。以後由投票模塊從阻塞隊列中獲取IP,並進行設置,而後進行投票。系統流程圖以下:git

3、系統技術github

  系統使用HttpClient + JSoup + 多線程來完成刷票,HttpClient用於進行投票,JSoup用於解析頁面,多線程技術用於分離任務,使得分工更加明確。使用到了生產者消費者模式,該模式直接使用BlockingQueue來實現。apache

4、系統介紹多線程

  系統主要分爲三個模塊:框架

  ① IP採集模塊ide

  ② 投票模塊網站

  ③ IP信息模塊

  其中,IP採集模塊主要是從互聯網爬取IP代理信息,並將該信息放入阻塞隊列,這樣就能夠僞造IP,進行屢次投票。

  其中,投票模塊從IP採集模塊放入阻塞隊列取出IP信息,並設置代理,找到投票入口地址,而後進行投票操做。

  其中,IP信息模塊主要是對爬取的IP信息進行了封裝,方便其餘模塊進行操做。

  4.1 IP採集模塊

  IP採集模塊流程圖以下

  幾點說明:

  1.系統使用的代理IP站點URL爲http://www.kuaidaili.com/,www.xicidaili.com。

  2.提取IP信息爲提取單條IP信息,並判斷歷史IP表是否已經存在,若存在,表示以前已經加入過此IP信息,則直接丟棄,反之,則加入隊列並加入歷史IP表。

  3.此任務會按期開啓,如一個小時爬取一次代理IP。

  4.2 投票模塊

  投票模塊流程圖以下

  幾點說明:

  1.投票網站http://www.hnxdf.com/vote/,咱們選取的第一位進行投票,分析出投票的入口爲http://www.hnxdf.com/vote/iRadio_vote.asp?VoTeid=215。

  2.根據IP採集模塊放入隊列的IP信息進行設置,而後進行投票。

  4.3 IP信息模塊

  此模塊主要對從網站爬取的IP信息進行了封裝,方便其餘模塊進行操做。

5、系統代碼框架

  系統的整個代碼框架以下

  其中,bean包的IpInfo封裝了爬取的IP信息。

  其中,entrance包的Vote爲系統的入口。

  其中,thread包的IPCollectTask爲爬取代理IP任務,VoteThread爲進行投票線程。

6、系統代碼

  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;
    }

    @Override
    public 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);
    }

    @Override
    public 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;
    }
    
    @Override
    public 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; // 鏈接生產者與消費者的阻塞隊列
    private List<IpInfo> historyIpLists; // 記錄已經獲取的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); // 獲取tbody
        Elements 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信息,則加入隊列中
            // 加入到阻塞隊列中,用做生產者
            try {
                ipInfoQueue.put(ipInfo);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            // 加入歷史記錄中
            historyIpLists.add(ipInfo);
        }
    }

    /**
     * 根據網頁Document解析出ip地址信息
     * 
     * @param doc
     */
    private void parseKuaiDaiLiIpLists(Document doc) {
        Elements eleLists = doc.getElementsByTag("tbody");
        Element tbody = eleLists.get(0); // 獲取tbody
        Elements trLists = tbody.children(); // 獲取十條ip記錄
        for (Element tr : trLists) { // 遍歷tr
            Elements 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);
        }
    }

    /**
     * 根據提供的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();
        }
    }

    @Override
    public 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;
    }

    @Override
    public 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);
                // 對響應內容編碼格式進行轉化,統一成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();
            }
        }
    }
}
複製代碼

7、系統總結

  此係統很簡單,想清楚思路以後很快就可以寫出代碼,系統運行時,因爲代理IP站點提供的免費IP質量不是過高,有效的IP地址仍是不多,全部效果不是特別理想,此係統功能也很簡單,可是各位園友能夠在此基礎上去發揮本身的想象力,定製屬於本身的投票系統。

8、總結

  至此,整個系統分析就已經完成了,其中,圖也畫得不是太規範,還請各位園友海涵。也謝謝各位園友觀看。

  ps:整個工程(包含必要的jar文件)已經上傳到GitHub上,歡迎各位園友訪問:https://github.com/leesf/TicketBrushSystem

 

https://www.cnblogs.com/leesf456/p/5170212.html

相關文章
相關標籤/搜索