浏览代码

优化抢购逻辑,提高抢购成功率、添加自动检测会话状态

等待下周测试
main
ztino 4 年前
父节点
当前提交
0a90b7b3d3
  1. 6
      jd_seckill/seckill.go
  2. 2
      jd_seckill/user.go
  3. 84
      main.go

6
jd_seckill/seckill.go

@ -78,7 +78,7 @@ func (this *Seckill) getSeckillUrl() (string,error) {
break break
} }
log.Println("抢购链接获取失败,稍后自动重试") log.Println("抢购链接获取失败,稍后自动重试")
time.Sleep(3*time.Millisecond) time.Sleep(300*time.Millisecond)
} }
//https://divide.jd.com/user_routing?skuId=8654289&sn=c3f4ececd8461f0e4d7267e96a91e0e0&from=pc //https://divide.jd.com/user_routing?skuId=8654289&sn=c3f4ececd8461f0e4d7267e96a91e0e0&from=pc
url=strings.ReplaceAll(url,"divide","marathon") url=strings.ReplaceAll(url,"divide","marathon")
@ -158,14 +158,12 @@ func (this *Seckill) SubmitSeckillOrder() bool {
invoiceContentType:="-1" invoiceContentType:="-1"
invoicePhone:="" invoicePhone:=""
invoicePhoneKey:="" invoicePhoneKey:=""
invoiceInfo:="false"
if isinvoiceInfo { if isinvoiceInfo {
invoiceTitle=gjson.Get(initInfo,"invoiceInfo.invoiceTitle").String() invoiceTitle=gjson.Get(initInfo,"invoiceInfo.invoiceTitle").String()
invoiceContentType=gjson.Get(initInfo,"invoiceInfo.invoiceContentType").String() invoiceContentType=gjson.Get(initInfo,"invoiceInfo.invoiceContentType").String()
invoicePhone=gjson.Get(initInfo,"invoiceInfo.invoicePhone").String() invoicePhone=gjson.Get(initInfo,"invoiceInfo.invoicePhone").String()
invoicePhoneKey=gjson.Get(initInfo,"invoiceInfo.invoicePhoneKey").String() invoicePhoneKey=gjson.Get(initInfo,"invoiceInfo.invoicePhoneKey").String()
}
invoiceInfo:="false"
if isinvoiceInfo {
invoiceInfo="true" invoiceInfo="true"
} }
token:=gjson.Get(initInfo,"token").String() token:=gjson.Get(initInfo,"token").String()

2
jd_seckill/user.go

@ -121,7 +121,7 @@ func (this *User) GetUserInfo() (string,error) {
break break
} }
errorCount=errorCount-1 errorCount=errorCount-1
time.Sleep(3*time.Millisecond) time.Sleep(300*time.Millisecond)
}else{ }else{
break break
} }

84
main.go

@ -11,7 +11,6 @@ import (
"net/http" "net/http"
"os" "os"
"runtime" "runtime"
"sync"
"time" "time"
) )
@ -21,7 +20,7 @@ var cookieJar *httpc.CookieJar
var config *goconfig.ConfigFile var config *goconfig.ConfigFile
var wg *sync.WaitGroup var seckillStatus chan bool
func init() { func init() {
//客户端设置初始化 //客户端设置初始化
@ -40,8 +39,8 @@ func init() {
os.Exit(0) os.Exit(0)
} }
wg=new(sync.WaitGroup) //抢购状态管道
wg.Add(1) seckillStatus=make(chan bool)
} }
func main() { func main() {
@ -64,16 +63,19 @@ func main() {
_,err=user.TicketInfo(ticket) _,err=user.TicketInfo(ticket)
if err==nil { if err==nil {
log.Println("登录成功") log.Println("登录成功")
//刷新用户状态和获取用户信息 //刷新用户状态
if status:=user.RefreshStatus();status==nil { if status:=user.RefreshStatus();status==nil {
//活跃用户会话,当会话失效自动退出程序
go KeepSession(user)
//获取用户信息
userInfo,_:=user.GetUserInfo() userInfo,_:=user.GetUserInfo()
log.Println("用户:"+userInfo) log.Println("用户:"+userInfo)
//开始预约,预约过的就重复预约 //开始预约,预约过的就重复预约
seckill:=jd_seckill.NewSeckill(client,config) seckill:=jd_seckill.NewSeckill(client,config)
seckill.MakeReserve() seckill.MakeReserve()
//等待抢购/开始抢购 //计算抢购时间
nowLocalTime:=time.Now().UnixNano()/1e6 nowLocalTime:=time.Now().UnixNano()/1e6
jdTime,_:=getJdTime() jdTime,_:=GetJdTime()
buyDate:=config.MustValue("config","buy_time","") buyDate:=config.MustValue("config","buy_time","")
loc, _ := time.LoadLocation("Local") loc, _ := time.LoadLocation("Local")
t,_:=time.ParseInLocation("2006-01-02 15:04:05",buyDate,loc) t,_:=time.ParseInLocation("2006-01-02 15:04:05",buyDate,loc)
@ -85,18 +87,22 @@ func main() {
log.Println("请设置抢购时间") log.Println("请设置抢购时间")
os.Exit(0) os.Exit(0)
} }
//等待抢购
time.Sleep(time.Duration(timerTime)*time.Millisecond) time.Sleep(time.Duration(timerTime)*time.Millisecond)
//开启任务 //开始抢购
log.Println("时间到达,开始执行……") log.Println("时间到达,开始执行……")
start(seckill,5) //开启抢购任务,第二个参数为开启几个协程
wg.Wait() //怕封号的可以减少协程数量,相反抢到的成功率也减低了
Start(seckill,5)
}else{
log.Println("登录失效")
} }
}else{ }else{
log.Println("登录失败") log.Println("登录失败")
} }
} }
func getJdTime() (int64,error) { func GetJdTime() (int64,error) {
req:=httpc.NewRequest(client) req:=httpc.NewRequest(client)
resp,body,err:=req.SetUrl("https://a.jd.com//ajax/queryServerData.html").SetMethod("get").Send().End() resp,body,err:=req.SetUrl("https://a.jd.com//ajax/queryServerData.html").SetMethod("get").Send().End()
if err!=nil || resp.StatusCode!=http.StatusOK { if err!=nil || resp.StatusCode!=http.StatusOK {
@ -106,12 +112,54 @@ func getJdTime() (int64,error) {
return gjson.Get(body,"serverTime").Int(),nil return gjson.Get(body,"serverTime").Int(),nil
} }
func start(seckill *jd_seckill.Seckill,taskNum int) { func Start(seckill *jd_seckill.Seckill,taskNum int) {
for i:=1;i<=taskNum;i++ { seckillTotalTime:=time.Now().Add(2*time.Minute).Unix()
go func(seckill *jd_seckill.Seckill) { //开始检测抢购状态
seckill.RequestSeckillUrl() go CheckSeckillStatus()
seckill.SeckillPage() //抢购总时间两分钟,超时程序自动退出
seckill.SubmitSeckillOrder() for time.Now().Unix()<seckillTotalTime {
}(seckill) for i:=1;i<=taskNum;i++ {
go task(seckill)
}
//每隔1.5秒执行一次
//怕封号的可以增加间隔时间,相反抢到的成功率也减低了
time.Sleep(1500*time.Millisecond)
}
log.Println("抢购结束,具体详情请查看日志")
}
func task(seckill *jd_seckill.Seckill) {
seckill.RequestSeckillUrl()
seckill.SeckillPage()
flag:=seckill.SubmitSeckillOrder()
//提前抢购成功的,直接结束程序
if flag {
//通知管道
seckillStatus<-true
}
}
func CheckSeckillStatus() {
for {
select {
case <-seckillStatus:
//抢购成功,程序退出
os.Exit(0)
}
}
}
func KeepSession(user *jd_seckill.User) {
//每30分钟检测一次
t:=time.NewTicker(30*time.Minute)
for {
select {
case <-t.C:
if err:=user.RefreshStatus();err!=nil {
log.Println("会话失效,程序自动退出")
os.Exit(0)
}
log.Println("活跃会话成功")
}
} }
} }
正在加载...
取消
保存