Browse Source

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

等待下周测试
main
ztino 4 years ago
parent
commit
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
}
log.Println("抢购链接获取失败,稍后自动重试")
time.Sleep(3*time.Millisecond)
time.Sleep(300*time.Millisecond)
}
//https://divide.jd.com/user_routing?skuId=8654289&sn=c3f4ececd8461f0e4d7267e96a91e0e0&from=pc
url=strings.ReplaceAll(url,"divide","marathon")
@ -158,14 +158,12 @@ func (this *Seckill) SubmitSeckillOrder() bool {
invoiceContentType:="-1"
invoicePhone:=""
invoicePhoneKey:=""
invoiceInfo:="false"
if isinvoiceInfo {
invoiceTitle=gjson.Get(initInfo,"invoiceInfo.invoiceTitle").String()
invoiceContentType=gjson.Get(initInfo,"invoiceInfo.invoiceContentType").String()
invoicePhone=gjson.Get(initInfo,"invoiceInfo.invoicePhone").String()
invoicePhoneKey=gjson.Get(initInfo,"invoiceInfo.invoicePhoneKey").String()
}
invoiceInfo:="false"
if isinvoiceInfo {
invoiceInfo="true"
}
token:=gjson.Get(initInfo,"token").String()

2
jd_seckill/user.go

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

84
main.go

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