微信刷票Python脚本教程

2017-12-18 17:08:12


现阶段,在微信朋友圈举办的投票活动层出不穷,相信已经有不少同学对此不胜其烦,因为总会时不时地冒出个人(亲戚、朋友、or whatever)来请你帮TA投票。本文倒没有打算从道德或者情感层面来探讨这个问题,我所感兴趣的是,当前大多数投票活动其实都是存在明显漏洞的,通过简单的技术手段就可以实现“刷票”。
微信刷票Python脚本教程
 

一、探查敌情

第一步先搞清楚投票的具体流程以及可能的限制条件。
经过研究之后,总结如下:
投票需要登录
注册帐号需要验证邮箱
登录不需要验证码
每个帐号一天可以投一次票,票数可以选择,从0~10
投票不需要验证码
注意到红字了是吧,这就是最关键的地方了。
 

二、工欲利其事

1、语言嘛必然是我爱的Python。
工具的话,之前其实做过模拟登录,简单来说就是用一个模拟浏览器的Python插件,然后进行各种模拟用户操作,比如点击按钮啊输入信息啊之类的。
2、但是这类插件主要有两大问题:
headless的很少
基本上对于HTML页面的操作只能应用于form
3、headless是什么呢,可以简单理解为后台操作。如果做不到headless,那么你运行的时候其实还是需要打开一个浏览器,只不过脚本会操作浏览器。
所以我们可以看到,做不到headless的话,不仅看起来非常低端(想象一下电脑屏幕上开着一个浏览器,然后自动输入东西,而你之只能傻坐着什么都不能做),并且使用起来很不方便,比如在没有图形界面的系统就无法使用了。
4、只能应用于form是什么意思呢,我们拿jQuery来对比吧。jQuery可以选择所有HTML里出现的东西,但是只能应用于form就意味着只能操作表单,对于其他元素就无能为力了。我不知道为什么会出现这种情况,可能是插件底层有一些限制吧,反正大部分插件都只能操作form。
 

三、给大家提供三个方案以供参考吧:

Ghost.py 支持headless并且可以操作所有元素,甚至可以运行js,你就知道这个有多强大了。唯一缺点——依赖PyQt或者PySide,你装一下这俩货就知道了,简直折磨死人。所以如果你不想折腾的话,还是不要用这个了。
splinter  半支持headless——splinter默认是不支持headless,但是可以在使用zope的一个插件的前提下headless,因为我用的是默认的,所以具体怎么做到headless没有研究,感兴趣的自己搞搞吧。不过估计八成不给力。。。splinter的功能同样很强大,可以操作所有元素。
mechanize  支持headless但是只能操作form

四、Just Do It

重复一下我们的思路:
登录——投票
因为我决定采用headless的方案,所以就使用mechanize。
登录的话没问题,登录框本来就是form。投票嘛。。。先放着!我们先把登录搞定。 
直接上代码:
 
复制代码
# coding:utf-8
import cookielib
import mechanize
import urllib
br = mechanize.Browser()
cj = cookielib.LWPCookieJar()
br.set_cookiejar(cj)
br.open('http://k4w.cn/user/index.html')
br.select_form(nr=0)
br.form['mail'] = 'xxxx@xxx.com'
br.form['password'] = 'xxxxxxx'
br.submit()
复制代码
cookielib是用来操作cookie的。因为我们登录之后需要跳转到投票页面,如果我们不保留cookie,那么网站就会把我们当做未登录——别忘了,你现在是用代码在模拟登录,所以不要以为他会自动给你保存cookie。
代码很简单吧,我就不解释了,总之,打开页面——输入用户名密码——提交
可以输出一下结果看看:
 
.....同上.....
response = br.submit()
print response.read()
我们可以看到输出的HTML中有“xxx,欢迎你”这样的字样,说明已经成功登录了
下面就是重头戏了——如何投票。
 
先具体化投票的操作:
 
从下拉列表里选择“10”,然后点击确定。
 
我们已经知道,mechanize只能操作form,对于其他元素是无能为力的,所以我们不能直接来模拟人的操作。
 
那么该怎么办呢? 
 
大家先思考5秒钟 。。。。。。。。
 
好吧我知道你直接翻下来了。
 
我当时可是思考了半天才想出来的啊!!! 
 
我们可以换个思路,投票,表面上是人的操作,但是最终发送给服务器的其实是一个POST请求!所以,我们可以跳过模拟操作,直接发送请求! 
 
好的,这下思路清晰了。我们先——等等,我们POST什么东西?
 
投票啊,告诉服务器我们投票了。
 
但是代码是一个很严谨的东西,格式不对的话服务器是不认的!
 
好吧,这次不思考了,直接告诉你答案吧。 
 
我们先手动投一次票,然后查看POST请求中的数据格式。
  
我用的是firebug,打开firebug,然后选择票数,按确定按钮,可以看到firebug中出来了这次POST请求的具体信息。
 
我们点开信息,可以看到数据的格式:
 
z_data : 10
id : 99
sid : 78
一下就看出来了嘛!
z_data是票数,id是项目编号,sid。。。好吧我不知道这是什么。总之就写78好了。 
 
数据格式获取到了,下面我们回到代码中,模拟一个POST请求:
parameters = {'z_data' : '10',
                  'id' : '99',
                  'sid' : '78'
                 }              #  POST data
data = urllib.urlencode(parameters)
response = br.open('http://k4w.cn/zone/z_num.html', data)
很简单吧?
 
别忘了import urllib!
 
好了,我们和前面的代码组合起来实验一下,看看效果。
 
发现票数确实增加了,我们的方法是可行的。 
 
然后呢,我们改一下,加个for循环,这样就可以按照我们设定好的用户名密码,自动登录所有用户并投票。 
 
基本功能就是这样了,但是使用了几天之后发现了一个不爽的地方:投票完要想查看票数还得手动打开网页。如果能直接显示出来当前票数就好了! 
 
于是我们继续踏上征程。

 五、微信刷票Python脚本教程迭代好吃吗

首先还是思路:
 
打开项目页面——获取票数——显示 
 
打开页面我们已经会了,br.open()就行。显示也很简单,print。那么怎么获取票数呢?
 
给大家介绍一个新工具——BeautifulSoup,靓汤!
 
我承认名字有点。。。。
 
不管了,继续我们编程之路。 
 
靓汤是一个解析HTML的插件,介绍完毕。 
 
我们可以把获取到的HTML用靓汤解析一下,然后找到我们需要的票数对应的那个元素,就可以获取票数了。
 
很简单是吧!我们把HTML传入靓汤。。。。
 
我靠怎么出错了!
 
Google了半天,原来是HTML中有不规范的标签,就解析失败了。
 
微软的页面原来也不符合标准。。。 
 
好吧,解析不了,怎么办呢? 
 
有人给出了解决办法:用lxml。 
 
lxml又是个什么东西?lxml是解析xml的一个插件,但是可以解析HTML并且,注意啊,并且可以忽略不规范的标签。
 
正好是我们需要的!
 
OK,照着官方文档使用一下~
 
亮代码:
 
br = mechanize.Browser()
response = br.open('http://k4w.cn/level_search/1/78/0/0/0.html')
page = etree.HTML(response.read().lower().decode('utf-8'))
hrefs = page.xpath(u"//span[@class='number n_99']")
print "当前票数:" + hrefs[0].text
依然是很简单不解释,看看就明白了。
  
好的,这样我们整个刷票脚本就完工了~~
  
所有代码来个合影
 
复制代码
# coding:utf-8
import cookielib
import mechanize
import urllib
from lxml import etree
 
all_data = [['username1', 'password1'], ['username2', 'password2']]
for i in all_data:
    br = mechanize.Browser()
    cj = cookielib.LWPCookieJar()
    br.set_cookiejar(cj)
    br.open('http://k4w.cn/user/index.html')
    br.select_form(nr=0)
    br.form['mail'] = i[0]
    br.form['password'] = i[1]
    br.submit()
    response = br.open('http://k4w.cn/level_search/1/78/0/0/0.html')
    parameters = {'z_data' : '10',
                  'id' : '99',
                  'sid' : '78'
                 }              #  POST data
    data = urllib.urlencode(parameters)
    response = br.open('http://k4w.cn/zone/z_num.html', data)
    print "%s 投票成功!" % i[0]
br = mechanize.Browser()
response = br.open('http://k4w.cn/level_search/1/78/0/0/0.html')
page = etree.HTML(response.read().lower().decode('utf-8'))
hrefs = page.xpath(u"//span[@class='number n_99']")
print "当前票数:" + hrefs[0].text
复制代码
搞定。 

六、总结

我们使用了:
 
mechanize  模拟用户操作  模拟POST请求
firebug  获取POST数据格式
lxml  解析HTML内容 
 
我们实现了:自动登录、自动投票、输出票数 
 
好了,下面只要把这个脚本放到服务器上,并且设置一下每天运行就可以了。
 
 
某美发网上商城(以下简称S商城)在微信平台上举办了一场在线投票活动,微信用户可通过活动链接访问到投票页面,对喜欢的发型师作品进行投票;每个微信帐号每天只能给单个作品投1张选票。
 
投票活动页面如下图所示:
 
漏洞分析
 
表面上看,S商城已经对投票活动进行了反作弊处理,因为限制了每个微信用户每天只能投一张票。如果用户都是正常地通过微信访问这个投票服务进行投票的话,的确是能起到预期效果的。
 
然而,如果查看投票页面的原始地址,即按住页面向下拖动,会发现屏幕顶端显示为"本网页由XXX提供",需要注意的是,这里的"XXX"并不是"mp.weixin.qq.com",而是S商城的域名。也就是说,这个投票活动的程序是运行在S商城的服务器上面的。
 
基于以上分析,可以推断出用户投票操作的网络拓扑结构示意图应该是这样的:
 
微信用户访问投票页面时,微信服务器只是进行了请求转发,具体的投票计数与校验都是在S商城的服务器上的。
 
那么,S商城是怎么来区分投票用户的呢?
 
这里就涉及到微信公众平台OpenID的概念了。官方对OpenID的解释是:加密后的微信号,每个用户对每个公众号的OpenID是唯一的。
 
要验证这一点也很容易,只需要通过采用多个微信账号进行投票,并对投票过程进行网络抓包,查看POST中的参数就可以证实。
 
基于这一点,微信公众平台在转发投票请求时,会在POST参数中包含用户的OpenID;S商城在接收到投票的POST请求后,通过查询当前OpenID是否在当天已经投过票,就可以阻止单一用户重复投票的行为了。
 
然而,这里面却存在一个很大的漏洞!
 
S商城只能判断OpenID是否出现了重复,但是却无法校验OpenID的有效性,因为它是无法调用微信服务器来对这个OpenID进行校验的。
 
VoteRobot实现
 
明确了这个漏洞后,要实现刷票就很简单了。
 
采用微信用户正常地进行一次投票操作,对设备进行网络抓包,获取到投票过程中HTTP层面的请求参数和响应内容;
使用Fiddler(或Python脚本)构造投票的HTTP POST请求,保持各参数与真实投票时抓取到的参数内容一致;
随机生成不同的OpenID参数,重复进行POST请求。
如果要实现批量刷票,或者刷票自动化操作,那么就可以将刷票请求通过Python脚本来实现;甚至,采用LoadRunner也是可以的。
 
运行VoteRobot.py,输出日志如下:
 
======== Start to vote zpid(38), Total votes: 3
1 tickets has been voted, the next ticket will be voted after 35 seconds.
2 tickets has been voted, the next ticket will be voted after 31 seconds.
3 tickets has been voted, the next ticket will be voted after 10 seconds.
======== Voting Ended!
需要注意的是,通常自动化刷票时最好有个随机的时间间隔,并且,最好能动态模拟不同的设备,即修改User-Agent,否则,服务端可以较为容易地识别作弊行为。
 
作弊与反作弊?
 
看到这里,也许有的同学心中窃喜,以后投票都可以采用这种方式“刷票”了么?
 
很遗憾,当然不是。
 
其实本文中案例的漏洞是很低级的,只是,当前的确还存在不少比例的投票活动是采用这种模式。
 
要判断一个投票活动是否可以采用这种方式来作弊也很简单。采用本文中的方法,若查看到活动的网址是非微信官方的,而且整个投票过程也没有额外的校验,那么实现作弊的可能性就很大了;再通过抓包看下通讯交互过程,并用网络请求工具修改参数后重新请求下,即可验证是否真的可以作弊了。
 
另外,也许有人想问了,网络中的投票活动就没法杜绝“刷票”行为了么?
 
答案是,完全杜绝的确很难。听说过12306的黄牛党没?听说过Apple Store专业给应用刷榜单的没?听说过“网络水军”、“五毛党”没?
 
不过,活动举办方可以通过一些手段,大大提高作弊的门槛。例如,当前有不少活动就采用了如下方式:
 
要求投票用户先关注活动举办方的公众号,然后调用微信官方的投票功能;
要求投票用户在投票活动举办方的网站上进行注册(手机号验证、实名验证)
不管采用这两种方式中的哪一种,本文中的“刷票”方法就完全失效了。
漏洞分析

作弊与反作弊?

看到这里,也许有的同学心中窃喜,以后投票都可以采用这种方式“刷票”了么?
很遗憾,当然不是。
其实本文中案例的漏洞是很低级的,只是,当前的确还存在不少比例的投票活动是采用这种模式。
要判断一个投票活动是否可以采用这种方式来作弊也很简单。采用本文中的方法,若查看到活动的网址是非微信官方的,而且整个投票过程也没有额外的校验,那么实现作弊的可能性就很大了;再通过抓包看下通讯交互过程,并用网络请求工具修改参数后重新请求下,即可验证是否真的可以作弊了。
另外,也许有人想问了,网络中的投票活动就没法杜绝“刷票”行为了么?
答案是,完全杜绝的确很难。听说过12306的黄牛党没?听说过Apple Store专业给应用刷榜单的没?听说过“网络水军”、“五毛党”没?
不过,活动举办方可以通过一些手段,大大提高作弊的门槛。例如,当前有不少活动就采用了如下方式:
 
要求投票用户先关注活动举办方的公众号,然后调用微信官方的投票功能;
要求投票用户在投票活动举办方的网站上进行注册(手机号验证、实名验证)
不管采用这两种方式中的哪一种,本文中的“刷票”方法就完全失效了。

服务支持

我们珍惜您每一次在线询盘,有问必答,用专业的态度,贴心的服务。

让您真正感受到我们的与众不同!

合作流程

最方便快捷的微信投票流程

客户答疑

你们的投票费用是多少?如果主办方修改升级了投票系统,刷票会受影响吗?

联系我们

微信刷票诚信专业的投票网站为优秀的您打造成功平台!