发布时间:2025-12-09 11:51:36 浏览次数:1
现在生活中离不开各类的比赛,然而,各个比赛离不开投票,我们会清一色有时候找到我们的朋友在朋友圈发—帮宝贝投一票,帮某某老师,学生投一票。又或许你自己参加比赛,你在为你自己拉票。
作为一名程序员,你是否想为自己的生活开一点G呢?熟悉网络请求的我们,应该从问题根源分析问题。对于一个投票的网站。大致分为两类:
既然原理已经剖析完成,那么剩下的就是设计程序的问题了,对于一个点击投票的事件,它的实质就是一次http(post)请求,然后后台对数据进行更改。那么我们就可以对这个操作流程进行抓包,分析这个请求是那种类型,需要那些参数。然后根据这个请求模拟写出请求。
然而最重要的就是ip代理,你要用代理的ip去访问那个接口,让对方以为是你代理的那个ip再对他访问,所以你需要维护一个代理ip池。对于代理ip池,并不是什么高大上的东西,准确的来说就是一个集合中包含一些可用的ip,能够供我使用。市面上也有很多出售代理ip,也不贵。我用的是蘑菇代理。
碰巧,最近参加的一个比赛就有拉票环节,如果人为手动拉票的话效率地下,并且你肯定也不会愿意天天去舔人家求情。那就自己分析一波!
找到url和几个参数,就可以准备程序了。模拟请求了
因为这是多次请求,所以要考虑性能的问题和效率问题。不能让异常漫天飞,中断,ip白白浪费,或者苦苦等待吧。对于代理ip,各家卖的虽然有些差异但是大体相同。大致均为卖数量,然后每个ip从开始被用后能够维持几分钟的使用。并且有的ip是不能用的,有的是高延迟的,这些在写程序的时候都要过滤掉。这里面就要考虑下这个程序额设计。
import requestsimport randomimport timeimport threadingfrom queue import Queuedef loadip():##从代理ip中获取ip 一次若干扩充到queue中 url2 = 'http://piping.mogumiao.com/proxy/api/get_ip_al?appKey=f16367295e284173ae450f&count=20&expiryDate=0&format=1&newLine=2' req = requests.get(url2) date = req.json() if(date['code'])!='3001': ipdate2 = date['msg'] for va in ipdate2: que.put(va)class downspider(threading.Thread):##线程类 def __init__(self, threadname, que): threading.Thread.__init__(self) self.threadname = threadname self.que = que def run(self): print('start thread' + self.threadname) while True: try: toupiaospider(que,self.threadname)##投票函数 except Exception as e: print(e,'888') breakdef getproxies():#获取ip 拼接成需要的代理格式 b=que.get() d = '%s:%s' % (b['ip'], b['port']) global proxies proxies['http'] = d return proxiesdef toupiaospider(que,threadname): if (que.qsize() < 15): # 拓展ip池 loadip() proxies2=getproxies() for i in range(0,5): try: #formData['times']=i req = requests.post(url, headers=header, data=formData, proxies=proxies2, timeout=1.5) res = req.json() if res['res']==2001 or req.status_code!=200: continue print(threadname,proxies2['http'],res,que.qsize()) except Exception as e: print('errror',e)if __name__ == '__main__': proxies = {'http': ''} stadus = 0 que = Queue() threads=[]#线程 url='http://yunxin.163.com/api/vote/update' header = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'} formData = { 'Referer':'http://yunxin.163.com/promotion/minichallenge/gallery?from=groupmessage&isappinstalled=0', 'id':'17', 'times':'1', 'activity':'minichallenge1' } proxies = {'http': '182.247.92.99:21136', } loadip() time.sleep(5) ##线程数组 ->启动 ——>等待join threadList = ['thread-1','thread-2','thread-3','thread-4','thread-4','thread-5'] for j in threadList: thread = downspider(j, que) thread.start() threads.append(thread) for t in threads: t.join()结果
在java中比较棘手的就是java自身对json和http请求的处理不太方便,需要借助第三方jar,并且一些操作稍显的繁琐。
首先java要弄清几点:
针对上面的问题。写了个demo测试进行预备,对于获取ip的api,大致这种格式
首先你要下载fastjson和jsoup的jar包。或者加入maven依赖。(可在maven官网下jar包)
<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup --> <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.12.1</version> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.58</version> </dependency>然后写个demo跑一下
package com.bigsai;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONArray;import com.alibaba.fastjson.JSONObject;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class test2 { static int va=1; public static void main(String[] args) { String ti="{"code":"0","msg":[{"port":"40034","ip":"114.237.64.247"},{"port":"33257","ip":"223.240.210.250"},{"port":"39618","ip":"113.101.255.11"},{"port":"43151","ip":"183.135.106.62"},{"port":"41795","ip":"182.108.44.227"}]}"; JSONObject jsonObject= JSON.parseObject(ti); String code=(String) jsonObject.get("code"); JSONArray jsonArray=jsonObject.getJSONArray("msg"); for(Object te:jsonArray) { JSONObject team=(JSONObject) te; String ip=team.getString("ip"); int port=team.getInteger("port"); System.out.println(team+" "+ip+" "+port); } ExecutorService ex= Executors.newFixedThreadPool(10); for(int i=0;i<200;i++) { threadtest threadtest=new threadtest(); ex.execute(threadtest); } ex.shutdown(); } static synchronized void addva()//去掉注释试试 { va++; try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" "+va); } static class threadtest implements Runnable{ @Override public void run() { addva(); } }}观察结果。打印,这些边角问题你就明白了。就可以设计java程序了。
package com.bigsai;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONArray;import com.alibaba.fastjson.JSONObject;import org.jsoup.Connection;import org.jsoup.Jsoup;import org.jsoup.nodes.Document;import java.io.IOException;import java.net.InetSocketAddress;import java.net.Proxy;import java.util.ArrayDeque;import java.util.HashMap;import java.util.Map;import java.util.Queue;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class wangyi { //改成你自己的token已经被我改了 static String ipurl="http://piping.mogumiao.com/proxy/api/get_ip_al?appKey=f16367295e284173ae3&count=20&expiryDate=0&format=1&newLine=2"; /** * java的多线程和python略有不同,但也可以改成相似的 * py是5个线程每个线程死循环任务,而java用线程池每个线程一个任务,只不过new了很多对象 * @param args */ static Queue<proxynode> q1; public static void main(String[] args) { q1=new ArrayDeque();//队列存放结构体 ip和port ExecutorService ex= Executors.newFixedThreadPool(10); for(int i=0;i<200;i++) { try { Proxy proxy=getproxies(q1);//获得代理ip vote vote=new vote(proxy); ex.execute(vote); } catch (Exception e) {e.printStackTrace();} } ex.shutdown(); } static synchronized Proxy getproxies(Queue<proxynode> q1) throws IOException//上锁获得代理,因为ip只用一次,也可使用自带的线程安全队列 { if(q1.size()<15)//扩充ip池 { String jsonva=Jsoup.connect(ipurl).timeout(2500).get().text(); JSONObject jsonObject= JSON.parseObject(jsonva); String code=(String) jsonObject.get("code");//状态吗 if (code.equals("0")) {//正常返回接口 JSONArray jsonArray = jsonObject.getJSONArray("msg"); for (Object jsonobj: jsonArray) { JSONObject team = (JSONObject) jsonobj; String ip = team.getString("ip"); int port = team.getInteger("port"); proxynode node=new proxynode(ip,port); q1.add(node); } } else return null; } proxynode proxynode=q1.poll(); Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxynode.ip, proxynode.port)); return proxy; } static class proxynode//一个node储存ip和端口 { String ip; int port; proxynode(String ip,int port) { this.ip=ip; this.port=port; } } static class vote implements Runnable{ Proxy proxy; vote(Proxy proxy) { this.proxy=proxy; } public void dovote() throws IOException { //Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("host", 8888)); try { Connection connect = Jsoup.connect("http://yunxin.163.com/api/vote/update").timeout(2000); Map<String,String>date=new HashMap<String, String>(); date.put("id","17"); date.put("times","1"); date.put("activity","minichallenge1"); date.put("Referer","http://yunxin.163.com/promotion/minichallenge/gallery?from=groupmessage&isappinstalled=0"); date.put("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36"); connect.data(date); connect.ignoreContentType(true); connect.proxy(proxy); Document doc=connect.post(); System.out.println(Thread.currentThread().getName()+" "+proxy.address()+" "+doc.text()); } catch (Exception e) { System.out.println(e.toString()); } } public void run() { try { for(int i=0;i<5;i++) { dovote(); } } catch (IOException e) { e.printStackTrace(); } } }}结果
在写爬虫还是python方便和简单。因为py对json支持较好(字典),而java强对象类型语法要求较严。但是在多线程方面java肯定是秒杀py的。因为py的多线程是(假)多线程。想提高速度的可以研究多进程。
这类问题本质不难的,做过一次就很简单了。这只是其中一种案例。提供一些思想和解决思路。遇到不同的问题可能需要不同的结构,方式去解决,这就需要融汇贯通。
如果有错误,请大佬指正。