3030 queryStart = "06:00" // 12306服务时间
3131 queryEnd = "23:00" // 12306服务时间
3232 queryXurl string // 查询票务信息url
33- headers map [string ]string //需要的header
34- allMissions []QueryInfo //所有任务信息
35- period = 2 //查询周期,单位分钟
33+ headers map [string ]string // 需要的header
34+ allMissions []QueryInfo // 所有任务信息
35+ period = 2 // 查询周期,单位分钟
36+ async = true // 是否开启任务并行
37+ retry = 3 // 查询失败重试次数
38+ retryPeriod = 1 // 重试休眠间隔,单位s
3639)
3740
3841//查询票务信息
@@ -64,6 +67,11 @@ func queryX(queryInfo QueryInfo) []byte {
6467 return nil
6568 }
6669 defer resp .Body .Close ()
70+ contentHeader := resp .Header .Get ("Content-Type" )
71+ if ! strings .Contains (contentHeader , "application/json" ) {
72+ easylog .Debug ("not json." , contentHeader )
73+ return nil
74+ }
6775 body , err := ioutil .ReadAll (resp .Body )
6876 if err != nil {
6977 easylog .Error ("queryx can't read respBody.." , err )
@@ -246,6 +254,55 @@ func filterTk(allTks []TicketInfo, queryInfo QueryInfo) (filterTks []TicketInfo,
246254 return filterTks , canbuy
247255}
248256
257+ // 一次完整的查询任务
258+ func oneMission (jobIndex int , queryOnce QueryInfo , chDone chan string ) {
259+ easylog .Debug ("job" , jobIndex + 1 , "start :" , queryOnce )
260+ // 查询失败重试
261+ var ticketstr []byte
262+ for i := 0 ; ; i ++ {
263+ ticketstr = queryX (queryOnce )
264+ if ticketstr != nil || i >= retry {
265+ break
266+ }
267+ time .Sleep (time .Duration (retryPeriod ) * time .Second )
268+ easylog .Debug ("job" , jobIndex + 1 , queryOnce , "retry" , i + 1 )
269+ }
270+ if ticketstr == nil {
271+ easylog .Info ("job" , jobIndex + 1 , queryOnce , "job failed." )
272+ chDone <- "query nil"
273+ return
274+ }
275+ allTickets := parseTicketStr (ticketstr )
276+ filterTks , canbuyTks := filterTk (allTickets , queryOnce )
277+ easylog .Info ("job" , jobIndex + 1 , queryOnce , " job done. all=" , len (allTickets ),
278+ ", can buy=" , canbuyTks , ", filter=" , len (filterTks ))
279+ if filterTks != nil && len (filterTks ) > 0 {
280+ //拼接信息
281+ var textMsgBuf bytes.Buffer
282+ textMsgBuf .WriteString (queryOnce .Day )
283+ for _ , tk := range filterTks {
284+ if tkbytes := tk .getTkMsg (queryOnce ); tkbytes != nil {
285+ textMsgBuf .WriteRune ('\r' )
286+ textMsgBuf .WriteRune ('\n' )
287+ textMsgBuf .Write (tkbytes )
288+ }
289+ }
290+ textMsg := textMsgBuf .String ()
291+ easylog .Info ("job" , jobIndex + 1 , "查询余票成功:\n " , textMsg )
292+ //发送邮件
293+ if Mailflag {
294+ SendText (queryOnce .Day , textMsg )
295+ }
296+ //发送微信
297+ if Weixinflag {
298+ SendToQyweixin (textMsg )
299+ }
300+ chDone <- "send end"
301+ } else {
302+ chDone <- "filterTks nil"
303+ }
304+ }
305+
249306//一次任务查询
250307func oneJob () {
251308 //先判断是否在服务时间
@@ -255,41 +312,23 @@ func oneJob() {
255312 easylog .Debug ("非售票时间" )
256313 return
257314 }
258- easylog .Debug ("once job start. missions size =" , len (allMissions ))
315+ easylog .Info ("once job start. missions size =" , len (allMissions ))
316+ chDone := make (chan string , len (allMissions ))
317+ start := time .Now ().UnixNano ()
259318 for i , queryOnce := range allMissions {
260- easylog .Debug ("job" , i , "start :" , queryOnce )
261- ticketstr := queryX (queryOnce )
262- if ticketstr == nil {
263- continue
264- }
265- allTickets := parseTicketStr (ticketstr )
266- filterTks , canbuyTks := filterTk (allTickets , queryOnce )
267- easylog .Info (queryOnce , " job done. all=" , len (allTickets ),
268- ", can buy=" , canbuyTks , ", filter=" , len (filterTks ))
269- if filterTks != nil && len (filterTks ) > 0 {
270- //拼接信息
271- var textMsgBuf bytes.Buffer
272- textMsgBuf .WriteString (queryOnce .Day )
273- for _ , tk := range filterTks {
274- if tkbytes := tk .getTkMsg (queryOnce ); tkbytes != nil {
275- textMsgBuf .WriteRune ('\r' )
276- textMsgBuf .WriteRune ('\n' )
277- textMsgBuf .Write (tkbytes )
278- }
279- }
280- textMsg := textMsgBuf .String ()
281- easylog .Info ("查询余票成功:" , textMsg )
282- //发送邮件
283- if Mailflag {
284- SendText (queryOnce .Day , textMsg )
285- }
286- //发送微信
287- if Weixinflag {
288- SendToQyweixin (textMsg )
289- }
319+ if async {
320+ go oneMission (i , queryOnce , chDone )
321+ } else {
322+ oneMission (i , queryOnce , chDone )
290323 }
291324 } //end for allMissions
292- easylog .Info ("once job end." )
325+ for range allMissions {
326+ // ignore result
327+ <- chDone
328+ }
329+ close (chDone )
330+ end := time .Now ().UnixNano ()
331+ easylog .Info ("once job end. tookTime =" , (end - start )/ 1000000 , "ms" )
293332}
294333
295334//初始任务配置
@@ -343,54 +382,79 @@ func InitConf() (bool, string) {
343382 return false , "period 配置有误"
344383 }
345384 }
385+ asyncstr , ok := cfg ["async" ]
386+ if ok {
387+ async , _ = strconv .ParseBool (asyncstr )
388+ }
389+ retrystr , ok := cfg ["retry" ]
390+ if ok {
391+ retry , _ = strconv .Atoi (retrystr )
392+ }
393+ retryPeriodstr , ok := cfg ["retryPeriod" ]
394+ if ok {
395+ retryPeriod , _ = strconv .Atoi (retryPeriodstr )
396+ if retryPeriod < 1 {
397+ retryPeriod = 1
398+ }
399+ }
346400 //初始化所有任务配置
347401 arr := strings .Split (all , "," )
348- allMissions = make ([]QueryInfo , len (arr ))
349- for i , sectionName := range arr {
402+ for _ , sectionName := range arr {
350403 onceSecCfg := GetSectionCfg (CONF_FILE , sectionName )
351404 if onceSecCfg == nil {
352405 return false , "任务 " + sectionName + " 未配置"
353406 }
354407 easylog .Debug (sectionName , " cfg: " , onceSecCfg )
355- var queryInfo QueryInfo
356- //乘车日期
357- if day , ok := onceSecCfg ["day" ]; ! ok {
358- return false , sectionName + " day 配置有误"
359- } else {
360- if _ , err := time .Parse (DAY_FORMAT , day ); err != nil {
361- return false , sectionName + " day 格式不正确,必须为yyyy-MM-dd"
362- } else {
363- queryInfo .Day = day
364- }
365- }
366408 //始发站
367- if from , ok := onceSecCfg ["from" ]; ! ok {
409+ from , fromeCode := "" , ""
410+ if from , ok = onceSecCfg ["from" ]; ! ok {
368411 return false , sectionName + " from 配置有误"
369412 } else {
370- queryInfo .From = from
371- queryInfo .FromCode = GetCodeByChname (from )
372- if queryInfo .FromCode == "" {
413+ fromeCode = GetCodeByChname (from )
414+ if fromeCode == "" {
373415 return false , sectionName + " 不存在的车站名:" + from
374416 }
375417 }
376418 //抵达站
377- if to , ok := onceSecCfg ["to" ]; ! ok {
419+ to , toCode := "" , ""
420+ if to , ok = onceSecCfg ["to" ]; ! ok {
378421 return false , sectionName + " to 配置有误"
379422 } else {
380- queryInfo .To = to
381- queryInfo .ToCode = GetCodeByChname (to )
382- if queryInfo .ToCode == "" {
423+ toCode = GetCodeByChname (to )
424+ if toCode == "" {
383425 return false , sectionName + " 不存在的车站名:" + to
384426 }
385427 }
386- queryInfo .Starttime = onceSecCfg ["starttime" ]
387- queryInfo .Endtime = onceSecCfg ["endtime" ]
388- queryInfo .Train_type = onceSecCfg ["train_type" ]
389- queryInfo .Train = onceSecCfg ["train" ]
390- queryInfo .Prior_seat = onceSecCfg ["prior_seat" ]
391- allMissions [i ] = queryInfo
392- }
393- easylog .Debug ("allMissions:" , allMissions )
428+ //乘车日期
429+ if days , ok := onceSecCfg ["day" ]; ! ok {
430+ return false , sectionName + " day 配置有误"
431+ } else {
432+ for _ , day := range strings .Split (days , "," ) {
433+ if "" != strings .TrimSpace (day ) {
434+ if _ , err := time .Parse (DAY_FORMAT , day ); err != nil {
435+ return false , sectionName + " day 格式不正确,必须为yyyy-MM-dd"
436+ } else {
437+ var queryInfo QueryInfo
438+ queryInfo .From = from
439+ queryInfo .FromCode = fromeCode
440+ queryInfo .To = to
441+ queryInfo .ToCode = toCode
442+ queryInfo .Day = day
443+ queryInfo .Starttime = onceSecCfg ["starttime" ]
444+ queryInfo .Endtime = onceSecCfg ["endtime" ]
445+ queryInfo .Train_type = onceSecCfg ["train_type" ]
446+ queryInfo .Train = onceSecCfg ["train" ]
447+ queryInfo .Prior_seat = onceSecCfg ["prior_seat" ]
448+ allMissions = append (allMissions , queryInfo )
449+ }
450+ }
451+ }
452+ }
453+ }
454+ if len (allMissions ) < 1 {
455+ return false , ""
456+ }
457+ easylog .Info ("allMissions:" , allMissions )
394458
395459 initConfFlag = true
396460 return true , "任务配置初始化成功"
@@ -417,7 +481,8 @@ func StartMission() {
417481 }
418482 //开启定时任务
419483 ticker := time .NewTicker (time .Duration (period ) * time .Minute )
420- easylog .Info ("任务开始.周期=" , period , "总任务数=" , len (allMissions ))
484+ easylog .Info ("任务开始.周期=" , period , ",总任务数=" , len (allMissions ),
485+ ",是否并行=" , async , ",失败重试次数=" , retry , ",重试休眠间隔=" , retryPeriod , "s" )
421486 go oneJob ()
422487 for range ticker .C {
423488 go oneJob ()
0 commit comments