百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

网络投票刷票原理(python和java)

toyiye 2024-06-21 12:18 10 浏览 0 评论

你还在苦苦拉票吗?

  • 前言
  • 剖析投票原理
  • 处理思路
  • 具体实战
  • 主要流程
  • 具体细节python
  • 代码实例python
  • 具体细节java
  • 代码实现java
  • 总结

前言

现在生活中离不开各类的比赛,然而,各个比赛离不开投票,我们会清一色有时候找到我们的朋友在朋友圈发—帮宝贝投一票,帮某某老师,学生投一票。又或许你自己参加比赛,你在为你自己拉票。

剖析投票原理

作为一名程序员,你是否想为自己的生活开一点G呢?熟悉网络请求的我们,应该从问题根源分析问题。对于一个投票的网站。大致分为两类:

  • 登录类:
  • 这类网站是确实不太好操作,一般是每个账户每天能够刷若干票。因为账户的资源是有限的,我们很难通过获取大量的账户资源为我们服务。况且,一般的登录稍微大厂或者技术高点其中的js加密会比较复杂,对于普通人js水平不高很难行的通这条路。比如常见需要微信登录,qq登陆的网站投票,就很难开挂。
  • 非登录类:
  • 并不是所有网站都有腾讯的登录授权的,有很多他们自己的官网他们自己就是一个体系。这类网站普通人或许也感觉不到差异:投几票之后也不能投。然后纷纷找朋友帮忙投。剖析这类网站,既然没有登录机制,那么它就是根据ip机制进行鉴定。因为正常你的公网ip相对来说是稳定。所以正常一个用户只能投固定的几票。或许高级一点他会和浏览器信息结合鉴定,但这种还是比较少的。

处理思路

既然原理已经剖析完成,那么剩下的就是设计程序的问题了,对于一个点击投票的事件,它的实质就是一次http(post)请求,然后后台对数据进行更改。那么我们就可以对这个操作流程进行抓包,分析这个请求是那种类型,需要那些参数。然后根据这个请求模拟写出请求。

然而最重要的就是ip代理,你要用代理的ip去访问那个接口,让对方以为是你代理的那个ip再对他访问,所以你需要维护一个代理ip池。对于代理ip池,并不是什么高大上的东西,准确的来说就是一个集合中包含一些可用的ip,能够供我使用。市面上也有很多出售代理ip,也不贵。我用的是蘑菇代理。

具体实战

主要流程

碰巧,最近参加的一个比赛就有拉票环节,如果人为手动拉票的话效率地下,并且你肯定也不会愿意天天去舔人家求情。那就自己分析一波!

  • 首先,打开你在的网站(有的手机端,电脑端好抓包可调),谷歌或者其他浏览器F12抓包,点击network,xhr准备(肯定是ajax请求不用想)。

  • 分析这个请求的重要参数.(header)

  • 找到url和几个参数,就可以准备程序了。模拟请求了

具体细节python

因为这是多次请求,所以要考虑性能的问题和效率问题。不能让异常漫天飞,中断,ip白白浪费,或者苦苦等待吧。

对于代理ip,各家卖的虽然有些差异但是大体相同。大致均为卖数量,然后每个ip从开始被用后能够维持几分钟的使用。并且有的ip是不能用的,有的是高延迟的,这些在写程序的时候都要过滤掉。这里面就要考虑下这个程序额设计。

  1. 多线程:
  2. python虽然多线程有个全局锁大大的影响效率。但是对于io请求型多线程还是能有一定的提速的。因为io有大量的线程等待。多线程的模块大致为定义一个线程类,定义初始方法和run函数。然后在外面定义几个线程,让他们跑任务。
  3. ip处理和资源处理
  4. 正常的ip代理是一群ip随机抽取其中作为代理ip,进行爬取任务,然后ip失效从ip池中删除。而url的链接一般放到线程安全的全局容器中一个个抛出。ip放到list或者redis中进行维护,做好try catch异常即可。但是这个刷票只有一个url。并且一个ip只能用有限次数。所以换个思路,url不需要容器维护。而ip用队列维护最好,并且python的队列是线程安全的。所以整个程序的架构也就很清晰了。只需要用个queue解析ip获取的格式进行相应储存。然后被消费,当少于一定个数时,请求api获取ip进行填充。
  5. 在预处理方面,以前介绍过另一个蘑菇代理使用和ip池类似的问题,可以预先参考。

代码实例python

import requests
import random
import time
import threading
from queue import Queue
def 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')
 break
def getproxies():#获取ip 拼接成需要的代理格式
 b=que.get()
 d = '%s:%s' % (b['ip'], b['port'])
 global proxies
 proxies['http'] = d
 return proxies
def 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中比较棘手的就是java自身对json和http请求的处理不太方便,需要借助第三方jar,并且一些操作稍显的繁琐。

首先java要弄清几点:

  1. 代理方式:
  2. java主要有两种代理方式,一种是jdk全局代理,另一种是net包下的proxy代理。对于多线程程序并且ip只能用一次的当然是用net的proxy代理。
  3. 解析json
  4. 通过api获取ip,格式固定的,需要借助fastjson解析json串获取需要的信息。
  5. 线程安全问题。你可以用线程安全的blockqueue,当然其实你可以在操作队列的方法加上synchronized关键字也可以。你可以定义固定的线程每个线程任务多个。也可以用线程池定义多个线程类,每个线程完成一个任务。
  6. 网络请求虽然urlconnection可以实现,但是太繁琐,远比jsoup复杂。所以这里使用jsoup。

针对上面的问题。写了个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程序了。

代码实现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的多线程是(假)多线程。想提高速度的可以研究多进程。

这类问题本质不难的,做过一次就很简单了。这只是其中一种案例。提供一些思想和解决思路。遇到不同的问题可能需要不同的结构,方式去解决,这就需要融汇贯通。

如果有错误,请大佬指正。

如果喜欢,可以关注我(一直码农一直爽),一起分享学习资源。

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码