你还在苦苦拉票吗?

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

点击此处,获取海量Python学习资料!

前言

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

剖析投票原理

作为一名程序员,你是否想为自己的生活开一点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():url2 = 'http://piping.mogumiao.com/proxy/api/get_ip_al?appKey=f16367295e284173ae450fc38d9098b3&count=20&expiryDate=0&format=1&newLine=2'req = requests.get(url2)date = req.json()if(date['code'])!='3001':ipdate2 = date['msg']global ipdateipdate.extend(ipdate2)for va in ipdate2:que.put(va)print(ipdate)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:print(self.name,end='')toupiaospider(que,self.threadname)except Exception as e:print(e,'888')break
def getproxies():b = ipdate[0]b=que.get()d = '%s:%s' % (b['ip'], b['port'])global proxiesproxies['http'] = dglobal msgmsg = breturn 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:#ipdate.remove(msg)continueprint(threadname,res,que.qsize())except Exception as e:print('errror',e)# ipdate.remove(msg)if __name__ == '__main__':ipdate = []msg = {}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)threadList = ['thread-1','thread-2','thread-3','thread-4','thread-4']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包)

然后写个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 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 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);}} elsereturn 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 date=new HashMap();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的多线程是(假)多线程。想提高速度的可以研究多进程。

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

python 获取用户ip_Python爬虫教程:你还在苦苦拉票吗?刷票小程序案例原理剖析!...相关推荐

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

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

  2. 12306 被质疑过度获取用户隐私,不授权还买不了票

    点击上方"CSDN",选择"置顶公众号" 关键时刻,第一时间送达! 从功能和系统上的非常难用,到前段时间爆出"一张身份证可买两张相同火车票" ...

  3. 刷票小程序原理剖析(python和java)

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

  4. python输入end退出循环_4.学习python获取用户输入和while循环及if判断语句

    0x00 Abstract 在开发中为了增加程序与用户的互动性需要增加获取用户输入的功能,在python中可以使用input()函数来获取用户的输入.当获取用户的各种输入后,我们需要使用逻辑语句来对数 ...

  5. python requests模块_Python 爬虫教程 requests 模块

    经过 前边文章<简单Python爬虫教程 (一)>.简单Python爬虫教程 (二)两篇文章的学习,能写一些比较简单的爬虫了,但是还不够,这一篇文章主要介绍Requests模块,reque ...

  6. python 获取用户的一个输入值_Python中,用于获取用户输入的命令为:

    [多选题]以下关于机器学习说法正确的是? [判断题]Python内置函数sum____用来返回数值型序列中所有元素之和. [单选题]关于自定义函数的下列说法不正确的是: [判断题]Python内置函数 ...

  7. 微信公众号上完成获取用户openid-----详细教程

    本文从零开始到获取用户openid并存到数据库 运用到SpringBoot+mybatis+RestTemplate 准备条件 需要一个公众号 需要简单配置一下,在左方菜单最下方----开发–基本配置 ...

  8. python获取主机ip_Python 获取本地主机 hostname 和 IP 地址的简单方法

    Python 获取本地主机 hostname 很简单,一行代码就能搞定.获取 IP 地址也一样简单,下面分享一下这些方法.都很简单,基本都是通过 Python 的 socket 库来进行获取的.Pyt ...

  9. 微信小程序案例:获取微信访问用户的openid

    在微信开发项目中,获取openid是项目常遇的问题,本文通过主要讲解实现在微信小程序中如何获取用户的openid,案例实现非常简单 具体实现方法是通过登录接口获取登录凭证,然后通过request请求微 ...

最新文章

  1. 口碑扑街光环不在,2018将是苹果手机最难熬的年头!
  2. js组合模式和寄生组合模式的区别研究
  3. ecmall开发记录(三)
  4. java程序员面试怎么难为面试官_Java程序员面试这些多线程问题你知道吗?
  5. 再次携号转网_陕西通信管理局:对移动公司拒绝对用户提供携号转网服务的违法行为处罚!...
  6. 培训学web前端前景如何?
  7. tomcat 运行报错 JRE_HOME
  8. 第六章 jQuery中的Ajax应用
  9. vue使用阿里巴巴矢量图标库
  10. 传统方法做分割 解析种子cues
  11. Apache网页与安全优化(网页压缩、网页缓存、隐藏版本信息、网页图片防盗链)——理论+实验!超详细
  12. bzoj 2144: 跳跳棋
  13. 什么是 Skype?
  14. 苹果主题商店_小米怕被苹果找茬,开始下架相关IOS主题了!
  15. 大数据Hadoop之——总结篇
  16. 好看的网站跳转页面网站源码
  17. python常用标准库的基本用法_Python常用标准库之fileinput
  18. 百度网盘压缩下载文件的CRC校验错误的解决方法
  19. 如何使用asp.net开发一套完整的智慧小区物业系统
  20. 1103平均分绩点(函数专题)

热门文章

  1. linux 命令之文件读取,head, tail, tailf, sed
  2. alpha阶段个人总结(201521123031林庭亦)
  3. spring 3.X与jdk 1.8不兼容
  4. 通过sqlserver日志恢复误删除的数据
  5. myeclipse 遇到的一些问题及解决方案
  6. 获取结构体中变量的偏移量
  7. Javascript到PHP加密通讯的简单实现
  8. Squid下Http头信息优先级
  9. GCC生成的汇编代码
  10. 判断一个string是否可以为数字