简单的刷票系统(突破IP限制进行投票)

前言  

  相信大家平时肯定会收到朋友发来的链接,打开一看,哦,需要投票。投完票后弹出一个页面(恭喜您,您已经投票成功),再次点击的时候发现,啊哈,您的IP(***.***.***.***)已经投过票了,不能重复投票。这时候,我们可能会想,能不能突破ip地址的限制进行刷票呢?有了这样的想法,那就去做吧,下面我将介绍我这个简单的刷票系统,仅供有需求的园友们参考。

1.系统设计

  系统主要实现的是突破IP限制进行刷票,其中,由IP采集模块负责从互联网上爬取代理IP,放入阻塞队列,该任务会定期执行。之后由投票模块从阻塞队列中获取IP,并进行设置,然后进行投票。系统流程图如下:

  

  

2.系统技术

  系统使用HttpClient + JSoup + 多线程来完成刷票,HttpClient用于进行投票,JSoup用于解析页面,多线程技术用于分离任务,使得分工更加明确。使用到了生产者消费者模式,该模式直接使用BlockingQueue来实现。

3、系统介绍

  系统主要分为三个模块:

    ①.IP采集模块

    ②.投票模块

    ③.IP信息模块

  其中,IP采集模块主要是从互联网爬取IP代理信息,并将该信息放入阻塞队列,这样就可以伪造IP,进行多次投票。

  其中,投票模块从IP采集模块放入阻塞队列取出IP信息,并设置代理,找到投票入口地址,然后进行投票操作。

  其中,IP信息模块主要是对爬取的IP信息进行了封装,方便其他模块进行操作。

  3.1.IP采集模块

    IP采集模块流程图如下

    

    几点说明:

      1.系统使用的代理IP站点URL为http://www.kuaidaili.com/,www.xicidaili.com。

      2.提取IP信息为提取单条IP信息,并判断历史IP表是否已经存在,若存在,表示之前已经加入过此IP信息,则直接丢弃,反之,则加入队列并加入历史IP表。

      3.此任务会定期开启,如一个小时爬取一次代理IP。

  3.2.投票模块

    投票模块流程图如下

      

    几点说明:

      1.投票网站http://www.hnxdf.com/vote/,我们选取的第一位进行投票,分析出投票的入口为http://www.hnxdf.com/vote/iRadio_vote.asp?VoTeid=215。

      2.根据IP采集模块放入队列的IP信息进行设置,然后进行投票。

  3.3.IP信息模块

    此模块主要对从网站爬取的IP信息进行了封装,方便其他模块进行操作。

4、系统代码框架

  系统的整个代码框架如下

  

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

  其中,entrance包的Vote为系统的入口。

  其中,thread包的IPCollectTask为爬取代理IP任务,VoteThread为进行投票线程。

5.系统代码

  1.IpInfo.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();
    }
}

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

6.系统总结

  此系统很简单,想清楚思路之后很快就能够写出代码,系统运行时,由于代理IP站点提供的免费IP质量不是太高,有效的IP地址还是很少,所有效果不是特别理想,此系统功能也很简单,但是各位园友可以在此基础上去发挥自己的想象力,定制属于自己的投票系统。

结束语

  至此,整个系统分析就已经完成了,其中,图也画得不是太规范,还请各位园友海涵。也谢谢各位园友观看。

  ps:整个工程(包含必要的jar文件)已经上传到GitHub上,欢迎各位园友访问:https://github.com/leesf/TicketBrushSystem

  

时间: 2024-10-29 22:39:36

简单的刷票系统(突破IP限制进行投票)的相关文章

关于投票系统刷票方式原理(突破ip限制刷票PHP版)

先说一点:其实不算是突破ip限制,因为事实上,这个限制是在服务器端的,客户端在牛逼,也突破不了..只是可以一直刷多次票罢了 一个朋友突然发了一个网站,让我帮她投投票..我这人一项比较好说话,就帮她投了.顺便分析了这个网站,发现这个网站的投票系统有ip限制,但是投票是一个ajax请求.那么办法就出来了. 很多投票PC网站都是依靠限制ip,来限制投票人数.那么我用curl伪造IP,那么就可以轻易制造多个IP进行投票. 下面贴上PHP代码: 由于对方是GET AJAX请求,我这里就贴上GET方法,PO

在投票系统方法的原则刷票(突破ip限制刷票PHP版)

让我谈一点:事实上,没有一个突破ip限制,因为实际上,,这项限制server结束,client牛逼,不能突破..只要是能够始终重复刷票罢了 一个朋友突然来了个网站,让我帮她投票..我是一个更好的人说话,为了帮助她投.顺便说一下分析本网站,有ip限制,可是投票是一个ajax请求.那么办法就出来了. 非常多投票PC站点都是依靠限制ip,来限制投票人数.那么我用curl伪造IP,那么就能够轻易制造多个IP进行投票. 以下贴上PHP代码: 因为对方是GET AJAX请求,我这里就贴上GET方法,POST

定制简单的Linux系统

制作思路: 新加一块硬盘,设置两个分区,一个存/boot,一个存/,创建文件系统并格式化.要注意,现在我们家的硬盘是要可以拔下来安装到其他机器上使用的,否则就没有意义了.试验中的硬盘sdb当换到其他机器上就是我们熟悉的sda了. 简单的Linux系统应该包括:内核文件,grub,bash,再加些常用工具就可以了. 准备工作: 添加工具和命令可以通过脚本来实现,所以我们先准备一个可以复制命令并安装的脚本. #!/bin/bash #----------------------------- #Fi

取出系统的IP地址

取出系统的IP地址 取出IP地址首先需要在文件中定位到有IP地址的那一行,所以我们先定位: 1.使用sed定位:  [[email protected] ~]# ifconfig eth0 | sed -n '2p'       inet addr:10.0.0.200  Bcast:10.0.0.255  Mask:255.255.255.0 2.使用awk定位: [[email protected] ~]# ifconfig eth0 | awk 'NR==2'       inet add

linux内核分析 第三周 构造一个简单的Linux系统MenuOS

一.计算机的三个法宝 存储程序计算机,函数调用堆栈,中断二.操作系统的两把剑:1.中断上下文的切换,保存现场和恢复现场2.进程上下文的切换. 三.linux内核源代码的分析: ·arch/目录保存支持多种CPU类型的源代码,重点是x86·init目录:含有main.c,内核启动相关的代码基本都在init目录下·ipc目录:进程间的通信·kernel目录:有Linux内核的核心代码.四.构造一个简单的Linux系统 使用实验楼的虚拟机打开shell 1.cd LinuxKernel/2.qemu

作业3:构造一个简单的Linux系统MenuOS 20135115臧文君

构造一个简单的Linux系统MenuOS 注:作者:臧文君,原创作品转载请注明出处,<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.Linux内核源代码介绍 1.根目录 arch/x86目录下的代码是我们重点关注的,arch中包括支持不同CPU的源代码. init目录下包含内核启动相关的代码,如main.c(start_kernel函数相当于普通C程序的main函数,是Linux内核初始化的起点). ipc

Linux内核设计第三周——构造一个简单的Linux系统

Linux内核设计第三周 ——构造一个简单的Linux系统 一.知识点总结 计算机三个法宝: 存储程序计算机 函数调用堆栈 中断 操作系统两把宝剑: 中断上下文的切换 进程上下文的切换 linux内核源代码分析 arch/目录保存支持多种CPU类型的源代码 其中的关键目录包括:Documentation.drivers.firewall.fs(文件系统).include init目录:含有main.c,内核启动相关的代码基本都在init目录下 start_kernal()函数为启动函数,初始化内

最简单的统计appche站点IP访问量的shell脚本

经常需要根据IP地址统计apache站点访问量,最基本的脚本. 根据IP访问量降序排列: #!/bin/bash #Script_name: access_count acc_log=/usr/local/apache2/logs/access_log /bin/awk '{print $1}' $acc_log  | sort | uniq -c | sort -nr 执行效果: [[email protected] ~]# sh access_count   94989 192.168.10

c#简单写售票系统

代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 售票系统 { class Program { static void Main(string[] args) { Console.Title = "售票系统"; string[,] zuo = new string[9, 4]; for (int i = 0; i < 9; i++)