转载

看我是如何跟羊毛党战斗的之我也变成羊毛党

*本文原创作者:西毒若相惜,本文属FreeBuf原创奖励计划,未经许可禁止转载

一、前言

快钱、飞凡双旦活动已经过去,这里跟大家分享下我是如何跟羊毛党战斗的。/doge

由于是事后写的,所以当时活动的一些截图可能就没有了,大家自行脑补~

就当顺便给快钱、飞凡打个广告啦~

二、导火索

作为老东家,有活动当然要支持一下啦,也就一元购还算比较靠谱划算了。

看我是如何跟羊毛党战斗的之我也变成羊毛党

想抢个东西,从来没有看到过存在有货的情况,特别是整点放货的时候也基本都是已抢光,可恶的羊毛党

特别是发现咸鱼上都是卖这个东西的

看我是如何跟羊毛党战斗的之我也变成羊毛党

于是想着自己也去做个羊毛党算了,机智啊。

三、卧薪尝胆

说做就做,无非就是写脚本监控起来,发现有货了告诉我们一下,我们去抢即可。

代理APP抓包(如有不会请自行百度),抓到活动页面的api请求 http://api.ffan.com/xxxxxxx

看我是如何跟羊毛党战斗的之我也变成羊毛党

可以看到返回的内容,简单分析下可知stockNum就是当前数量,totalStockNum是总共放出抢购的数量

当然识别你想抢购的商品,可以通过detailUrl,goodsPic,goodsSn等唯一识别码去识别

所以这一块的代码应该是这样

fight against sheep beta0.9

def shuliang():

geturl=' http://api.ffan.com/xxxxx '

headers ={(User-Agent),(Referer),(Cookie)}

opener.addheaders = headers

response = opener.open(geturl).read()//打开网页获取返回内容

if(response.find('s1e58a65f13d284c1e811bd3a33c62e9f0')>0)://找到你想要关注的商品

str=response[response.find('s1e58a65f13d284c1e811bd3a33c62e9f0'):]

str=str[str.find('stockNum'):]

shuliang=str[str.find(':')+1:str.find(',')]//通过最简单的字符串截取获得stockNum的值,也就是当前库存数量

if(int(shuliang)<10)://这地方没货的情况值应该是0,这里设为10的意思是,就算库存有10个也就当做没有货,反正也抢不到,因为可能存在抢购到但是没有付款,于是订单超时取消的情况

print("没有货")

else:

print("有货")

else:

print("没有上架")

上面beta0.9版本应该是有了雏形,但还是有一些需要优化的地方

1.程序不能无限制的执行下去吧(通过time.sleep()来控制请求的频率)

2.通过print打出的提醒不能及时看到(暂时想到通过一个弹框来提醒自己,在公司里,自己办公电脑总不能声音告警吧,但是当你在认真工作时,程序执行的时候发现有货了,会谈一个框告诉你有货了,这样来达到及时的效果)

于是就有了以下的代码

fight against sheep beta1.0

while True:
shuliang()
time.sleep(60)//每分钟请求一下查询库存

当然这个频率不是很合适,需要细化,结合业务,每隔两小时的整点上货,那么我们就在那段时间请求频繁一点即可

//每日9点到21点,每2小时的整点进行抢购,那我在55分到05分直接就多进行关注就行了。例如我8:55-9:05 10:55-11:05等等多加关注
if((int(time.strftime("%M"))>55 and int(time.strftime("%H"))%2==0 and int(time.strftime("%H"))>7 and int(time.strftime("%H"))<22) or (int(time.strftime("%H"))%2==1 and int(time.strftime("%M"))<5 and int(time.strftime("%H"))>7 and int(time.strftime("%H"))<22)):
time.sleep(5)//濒临抢购时间点,咱们5秒请求一次
......
if(int(shuliang)<10):
print("没有货")
else:
print("有货")
os.system("calc.exe")//弹个计算器出来,这样你一边在认证工作,突然出来个计算器,你就知道有货了,就去准备购买了

上面代码为什么还不能成为正式版,因为在程序运行过程中还会发生一些问题,程序不够健壮

1.当请求频率过高时,socket连接失败,例如打开连接超时,或者服务端拒绝了此次连接等等,导致程序直接崩了(你以为你程序在跑着呢,结果程序异常直接退出了,你还傻傻的等它提醒你呢)

2.print打印在终端,程序运行时间长了内容多了终端无法全部显示出来(加个日志吧,也不能说是日志,就是把终端打印的东西存在一个文本文件中去,方便查看)

3.感觉弹框提醒貌似也有局限性(比如1点的抢购,可能人还在外面吃午饭,你电脑上弹框了你也不知道有货了,所以增加邮件告警吧)

在解决了上面3个问题后,不是beta版的正式版本终于到来

fight against sheep 正式版

while 1:
try:
response = opener.open(geturl).read()
break//打开网页出错,则跳出循环重新执行 except Exception, e:
    print str(e)

while True:
f=open('a.txt','a')
old=sys.stdout//就是把输出流接收了,放到新建的a.txt的文本文件当中
sys.stdout=f
shuliang()
sys.stdout=old
f.close()

def send(to_list,sub,content):

me=" xxxx @xxx.com "

msg = MIMEText(content,_subtype='plain',_charset='utf-8')

msg['Subject'] = sub

msg['From'] = me

msg['To'] = to_list

try: 

server = smtplib.SMTP() 

server.connect(mail_host) 

server.login(mail_user,mail_pass)  //自己定义好告警邮箱

server.sendmail(me,to_list, msg.as_string())

server.close() 

return True 

except Exception, e: 

print str(e) 

return False

......

if(int(shuliang)<10):

print("没有货")

else:

print("有货")

send(me,"有货","有货有货,邮件告知,赶紧来买")

#os.system("calc.exe")

好了,不愧是正式版,程序这次跑了很久也没出问题,要说唯一的问题就是,貌似从来没有收到过邮件告警

那这个程序的存在还有什么意义

经过一段时间的观察,发现stockNum的值确实一直是0,但是totalstockNum的值却每个抢购时间点在增加,说明确实抢购时间点是在放货没错,这也不是程序的问题,只能说业务上货是先把商品下架,补充货源后再上架,这个过程也许可能可以购买了,这就导致当商品重新上架后,已经被抢光了。于是有了下面的版本

fight against sheep 正式改进版

主要改进几个问题

1.当检测到商品下架时,我就知道可能要准备上货了,这时候给提醒

2.到目前为止只是为了提醒我有货了赶紧抢购,为何不直接帮我买好呢

......
if(int(shuliang)<10):
print("没有货")
else:
print("有货")
send(me,"有货","有货有货,邮件告知,赶紧来买")
goumai()//发现有货不磨叽,直接购买
else:
print("没有上架")
goumai()//既然发现了商品没有上架也能购买,那这里就也直接购买吧

def goumai():
posturl='xxxxxx'
headers={xxx}
data='xxx'
opener.open(posturl,data)//直接请求购买的url即可

fight against sheep 正式改进优化版

再优化一下程序

1.有时候购买不成功,需要定位为什么购买不成功(没有库存了?还是说是我程序请求的间隔长了?一般抢购的点,10秒可能就没了)

2.有时候会发生邮件轰炸…..自己炸自己可不好玩

if(int(time.strftime("%M"))>58 or int(time.strftime("%M"))<2):
goumai()//在之前55分到05分的前提下,这里优化一下,在59分到01分这2分钟内,goumai的请求频率可以加大,比如可以1秒1次

def goumai():
......
response = opener.open(posturl,data).read()//我也获取购买请求的response
print response//打印出来分析下为什么购买不成功 if(response.find('5001')>0):
   #send(mailto_list,"购买失败","未上架或库存不足")
 if(response.find('5000')>0):
   #send(mailto_list,"购买失败","今日已购买过或今日已抢购满3次,无需购买,请注意")//就不都一一发邮件通知了,print记录下即可
 if(response.find('200')>0):
send(mailto_list,"购买成功","购买成功")//分析出各种购买失败的情况
time.sleep(60)//购买成功的话给个邮件通知,然后等待1分钟后程序继续跑,一般这时候抢购已经结束,就不会有多个邮件告警出来

到此为止也不是最终版,中间还经历了各种调试,优化的过程

fight against sheep 正式改进优化版V1.1

fight against sheep 正式改进优化版V1.2

fight against sheep 正式改进优化再三确认版

fight against sheep 正式改进优化再三确认版V9

fight against sheep 正式改进优化再三确认不修改版

fight against sheep 正式改进优化再三确认不修改最终版

fight against sheep 正式改进优化再三确认不修改最终真不修改版

fight against sheep 正式改进优化再三确认不修改最终真不修改最后一次修改版

………….

fight against sheep

四,结语

来看看到目前为止的效果吧

看我是如何跟羊毛党战斗的之我也变成羊毛党

这也是最终的日志的记录,包括各种时间戳,各种响应内容,请求次数等等

看我是如何跟羊毛党战斗的之我也变成羊毛党

基本上每次抢购也就一封邮件出来告知是成功还是失败,没有多余的轰炸

看我是如何跟羊毛党战斗的之我也变成羊毛党

每天稳定输出3块布朗尼

1月15号就要到了,快要过期了,送一块布朗尼,仅限上海虹口龙之梦店。需要的表哥MMM

*本文原创作者:西毒若相惜,本文属FreeBuf原创奖励计划,未经许可禁止转载

原文  http://www.freebuf.com/articles/web/124883.html
正文到此结束
Loading...