你还在苦苦拉票吗?

前言

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

剖析投票原理

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

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

处理思路

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

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

具体实战

主要流程

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

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

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

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

具体细节python

因为这是多次请求,所以要考虑性能的问题和效率问题。不能让异常漫天飞,中断,ip白白浪费,或者苦苦等待吧。 对于代理ip,各家卖的虽然有些差异但是大体相同。大致均为卖数量,然后每个ip从开始被用后能够维持几分钟的使用。并且有的ip是不能用的,有的是高延迟的,这些在写程序的时候都要过滤掉。这里面就要考虑下这个程序额设计。

  1. 多线程: python虽然多线程有个全局锁大大的影响效率。但是对于io请求型多线程还是能有一定的提速的。因为io有大量的线程等待。多线程的模块大致为定义一个线程类,定义初始方法和run函数。然后在外面定义几个线程,让他们跑任务。

  2. ip处理和资源处理 正常的ip代理是一群ip随机抽取其中作为代理ip,进行爬取任务,然后ip失效从ip池中删除。而url的链接一般放到线程安全的全局容器中一个个抛出。ip放到list或者redis中进行维护,做好try catch异常即可。但是这个刷票只有一个url。并且一个ip只能用有限次数。所以换个思路,url不需要容器维护。而ip用队列维护最好,并且python的队列是线程安全的。所以整个程序的架构也就很清晰了。只需要用个queue解析ip获取的格式进行相应储存。然后被消费,当少于一定个数时,请求api获取ip进行填充。

  3. 在预处理方面,以前介绍过另一个蘑菇代理使用和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 = threadnameself.que = quedef 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 proxiesproxies['http'] = dreturn proxies
def toupiaospider(que,threadname):if (que.qsize() < 15):  # 拓展ip池loadip()proxies2=getproxies()for i in range(0,5):try:#formData['times']=ireq = requests.post(url, headers=header, data=formData, proxies=proxies2, timeout=1.5)res = req.json()if res['res']==2001 or req.status_code!=200:continueprint(threadname,proxies2['http'],res,que.qsize())except Exception as e:print('errror',e)if __name__ == '__main__':proxies = {'http': ''}stadus = 0que = 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)##线程数组   ->启动 ——>等待jointhreadList = ['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. 代理方式: java主要有两种代理方式,一种是jdk全局代理,另一种是net包下的proxy代理。对于多线程程序并且ip只能用一次的当然是用net的proxy代理。
  2. 解析json 通过api获取ip,格式固定的,需要借助fastjson解析json串获取需要的信息。
  3. 线程安全问题。你可以用线程安全的blockqueue,当然其实你可以在操作队列的方法加上synchronized关键字也可以。你可以定义固定的线程每个线程任务多个。也可以用线程池定义多个线程类,每个线程完成一个任务。
  4. 网络请求虽然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{@Overridepublic 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和portExecutorService ex= Executors.newFixedThreadPool(10);for(int i=0;i<200;i++){try {Proxy proxy=getproxies(q1);//获得代理ipvote 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的多线程是(假)多线程。想提高速度的可以研究多进程。

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

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

github代码地址,欢迎star
欢迎关注我的个人公众号:bigsai

转载于:https://juejin.im/post/5d00bbaf6fb9a07f0a2dd90d

刷票小程序原理剖析(python和java)相关推荐

  1. 刷票小程序案例原理剖析(python和java)

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

  2. python语言小程序-微信小程序可以用Python语言编写吗?

    Q: 微信小程序可以用Python语言编写吗? A: 小程序一般开发HTML.CSS.JS,需要后台开发就需要PHP,MySQL等了.你说的这种语言开发小程序不好使.如果你不想学更多,建议你找一家专业 ...

  3. java寻优算法_模拟退火算法SA原理及python、java、php、c++语言代码实现TSP旅行商问题,智能优化算法,随机寻优算法,全局最短路径...

    模拟退火算法SA原理及python.java.php.c++语言代码实现TSP旅行商问题,智能优化算法,随机寻优算法,全局最短路径 模拟退火算法(Simulated Annealing,SA)最早的思 ...

  4. 碉堡的小程序:用 Python 制作演示迷宫算法的 gif 动画

    微信改版,加星标不迷路! 碉堡的小程序:用 Python 制作演示迷宫算法的 gif 动画 作者:neozhaoliang 本文要介绍的是我写的一个有趣的小程序,一个脱离了低级趣味的程序,一个有益于广 ...

  5. 提高微信小程序的应用速度的常见方式有哪些? 小程序怎么实现下拉刷新? 简述微信小程序原理? 小程序的发布流程(开发流程)分析下微信小程序的优劣势?小程序授权登录流程? 小程序支付如何实现

    小程序部分常见面试题 提高微信小程序的应用速度的常见方式有哪些? 提高页面加载速度 用户行为预测 减少默认data的大小 组件化方案 分包预下载 小程序与原生App相比优缺点? 优点: 基于微信平台开 ...

  6. ssm基于微信小程序的游泳馆管理系统+uinapp+java+计算机毕业设计

    游泳馆管理系统小程序,主要对首页.个人中心.会员管理.场馆类型管理.泳池类型管理.饮食类型管理.场馆信息管理.泳池信息管理.饮食信息管理.泳池预订管理.购买信息管理.会员等级管理.会员充值管理.系统管 ...

  7. 小程序数据怎么传输到服务器,微信小程序怎么将数据传输到Java后台

    微信小程序怎么将数据传输到Java后台 发布时间:2020-12-10 14:19:49 来源:亿速云 阅读:124 作者:Leah 今天就跟大家聊聊有关微信小程序怎么将数据传输到Java后台,可能很 ...

  8. app小程序手机端Python爬虫实战12实现自动化退出考研帮app并清空缓存

    app小程序手机端Python爬虫实战11实现自动化退出考研帮app并清空缓存 一.捕获安卓吐司的消息 结束安卓的吐司操作: while True:if self.d.toast.get_messag ...

  9. 小程序人像卡通化(Java)(模板使用)

    小程序人像卡通化(Java)(模板使用) 1.打开阿里云开发平台 https://workbench.aliyun.com/ 2.创建应用,通过该模板创建应用. 3.填写基本信息 开启各项服务: 下面 ...

最新文章

  1. Android 实现闹钟功能
  2. 【转】首先为人编写程序,其次才是计算机
  3. 服务器修改mime类型,服务器上没有设置mime类型
  4. 【Java】Struts2配置默认Action和配置Action的默认处理类
  5. 折半查找一个有序数组中的一个元素,即二分法
  6. 从技术分工的角度来看996.ICU
  7. 因为一个循环,CPU搞了个新技术
  8. nginx(windows环境安装)
  9. LabelSmoothing标签平滑
  10. 推荐 四种优秀的数据库设计工具
  11. 知识点滴 - X射线和伽马射线有什么区别?
  12. 入侵检测技术综述(比较全)
  13. 网络爬虫---用urllib模块爬取京东笔记本电脑的数据、并对其做一个可视化
  14. Win7的资源管理器打不开
  15. 利用尾注插入参考文献
  16. Spring 项目无法解析包含 uri http://java.sun.com/jsp/jstl/core 的 taglib
  17. xp 没有应用程序服务器,XP双击exe文件没反应不能安装程序
  18. 中秋邀请共赏图数据库-蚂蚁集团图数据TuGraph 正式开源
  19. KSOM培养基添加氨基酸——KSOM+AA培养基方案
  20. GCPC2015 F Divisions (约数个数定理)

热门文章

  1. ElasticSearch 6.x 学习笔记:20.搜索排序
  2. 通过Boomerang按计划在Gmail中发送或接收电子邮件(并且我们有邀请)
  3. java jcf查看_JAVA 集合框架(JCF)
  4. Wifi直连(p2p)一对多音频传输
  5. 基于微信小程序的酒店管理系统
  6. Gigaphoton 取得70%*中国市场份额
  7. 冠群金辰网络安全多层次综合解决方案(转)
  8. VT在BIOS内已开启,但CPU-v显示未开启
  9. 高精度地图制作一些资料
  10. 【Jquery】------- Jquery实现左侧页面切换滑入,滑出实例代码展示