mxs 1 рік тому
батько
коміт
5100f580e9
6 змінених файлів з 294 додано та 88 видалено
  1. 19 18
      src/main.go
  2. 32 20
      src/spider/handler.go
  3. 18 9
      src/spider/script.go
  4. 157 24
      src/spider/spider.go
  5. 17 17
      src/spider/store.go
  6. 51 0
      src/spider/supplement.go

+ 19 - 18
src/main.go

@@ -60,8 +60,9 @@ func init() {
 		qu.ObjToString(Config.OssInfo["ossAccessKeySecret"]),
 		qu.ObjToString(Config.OssInfo["ossBucketName"]),
 	)
+	//数据补采配置
+	spider.InitSupplement()
 	//xweb框架配置
-
 	logger.SetConsole(false)
 	if Config.LogLevel <= 1 {
 		logger.SetLevel(logger.DEBUG)
@@ -86,7 +87,7 @@ func init() {
 	xweb.RootApp().Logger.SetOutputLevel(4)
 }
 
-//初始化数据源
+// 初始化数据源
 func InitMgo() {
 	spider.MgoS = &mgo.MongodbSim{
 		MongodbAddr: Config.Mongodb_spider,
@@ -110,29 +111,29 @@ func InitMgo() {
 	spider.MgoEB.InitPool()
 }
 
-//
 func main() {
 	//临时统计总的线程数
 	go spider.AllThreadLog()
 	//定时清理日志
 	go clearLogs()
-	//初始化爬虫服务,开始下载列表
-	go spider.InitSpider()
 	//清理计数
 	go spider.GcCount()
-	//定时重载脚本文件
-	go spider.ReloadSpiderFile()
-	//内存信息
-	go heapprint()
-	//查列表页信息采集三级页
-	go spider.DetailData()
-	//处理心跳信息
-	go spider.SaveHeartInfo()
-	//批量保存心跳信息
-	go spider.UpdateHeartInfo()
-	//7000历史节点下载详情页
-	go spider.HistoryEventDownloadDetail()
-
+	if !spider.Supplement {
+		//初始化爬虫服务,开始下载列表
+		go spider.InitSpider()
+		//定时重载脚本文件
+		go spider.ReloadSpiderFile()
+		//内存信息
+		go heapprint()
+		//查列表页信息采集三级页
+		go spider.DetailData()
+		//处理心跳信息
+		go spider.SaveHeartInfo()
+		//批量保存心跳信息
+		go spider.UpdateHeartInfo()
+		//7000历史节点下载详情页
+		go spider.HistoryEventDownloadDetail()
+	}
 	//批量保存data_bak
 	//go spider.SaveDataBak()
 	//批量保存错误数据

+ 32 - 20
src/spider/handler.go

@@ -61,7 +61,7 @@ func InitSpider() {
 	}
 }
 
-//高性能模式
+// 高性能模式
 func NoQueueScript() {
 	list, _ := MgoS.Find("spider_ldtime", nil, nil, map[string]interface{}{"code": 1, "uplimit": 1, "lowlimit": 1}, false, -1, -1)
 	LoopListPath.Range(func(key, temp interface{}) bool {
@@ -81,7 +81,7 @@ func NoQueueScript() {
 					}
 				}
 
-				if util.Config.Modal == 1 && !util.Config.IsHistoryEvent { //列表页、三级页分开采集模式
+				if !Supplement && util.Config.Modal == 1 && !util.Config.IsHistoryEvent { //列表页、三级页分开采集模式
 					sp2, _ := CreateSpider(code, script, true, false)
 					sp2.IsMainThread = true //多线程采集时使用
 					Allspiders2.Store(sp.Code, sp2)
@@ -129,7 +129,7 @@ func NoQueueScript() {
 	logger.Info("总共加载脚本数:", numSpider)
 }
 
-//排队模式下载列表页数据
+// 排队模式下载列表页数据
 func QueueUpScriptList() {
 	logger.Info("节能模式列表页")
 	CC = make(chan *lua.LState, util.Config.Chansize)
@@ -241,7 +241,7 @@ func QueueUpScriptList() {
 	}
 }
 
-//排队模式下载三级页数据
+// 排队模式下载三级页数据
 func QueueUpScriptDetail() {
 	logger.Info("节能模式三级页")
 	chanSize := util.Config.DetailChansize
@@ -293,11 +293,20 @@ func QueueUpScriptDetail() {
 	}
 }
 
-//获取所有爬虫脚本--数据库
+// 获取所有爬虫脚本--数据库
 func getSpiderScriptDB(code string) map[string]map[string]string {
 	scriptSpider := map[string]map[string]string{}
 	query := map[string]interface{}{}
-	if code == "all" { //初始化所有脚本
+	if Supplement { //数据采集
+		query = map[string]interface{}{
+			"state":    5,
+			"platform": "golua平台",
+			"event": map[string]interface{}{
+				"$ne": 7000,
+			},
+			"spiderimportant": true,
+		}
+	} else if code == "all" { //初始化所有脚本
 		query = map[string]interface{}{"state": 5, "event": util.Config.Uploadevent}
 	} else { //消息在线上传
 		query = map[string]interface{}{"code": code, "event": util.Config.Uploadevent}
@@ -308,6 +317,9 @@ func getSpiderScriptDB(code string) map[string]map[string]string {
 	//listdb, _ := MgoEB.Find("luaconfig_test", query, map[string]interface{}{"_id": -1}, nil, false, -1, -1)
 
 	for _, v := range *listdb {
+		if Supplement && strings.Contains(qu.ObjToString(v["code"]), "_bu") { //补采去除含“_bu”后缀的爬虫
+			continue
+		}
 		old := qu.IntAll(v["old_lua"])
 		script := ""
 		if old == 1 {
@@ -334,7 +346,7 @@ func getSpiderScriptDB(code string) map[string]map[string]string {
 	return scriptSpider
 }
 
-//获取所有爬虫脚本--文件
+// 获取所有爬虫脚本--文件
 func getSpiderScriptFile(newscript bool) map[string]map[string]string {
 	scriptSpider := map[string]map[string]string{}
 	filespider := 0
@@ -406,7 +418,7 @@ func getSpiderScriptFile(newscript bool) map[string]map[string]string {
 	return scriptSpider
 }
 
-//脚本下架、上架、重载
+// 脚本下架、上架、重载
 func UpdateSpiderByCodeState(code, state string) (bool, error) {
 	up := false
 	var err error
@@ -629,7 +641,7 @@ func UpdateSpiderByCodeState(code, state string) (bool, error) {
 	return up, err
 }
 
-//定时重载脚本文件
+// 定时重载脚本文件
 func ReloadSpiderFile() {
 	scriptMap := getSpiderScriptFile(true)
 	for k, v := range scriptMap {
@@ -772,7 +784,7 @@ func ReloadSpiderFile() {
 	util.TimeAfterFunc(time.Duration(15)*time.Minute, ReloadSpiderFile, TimeChan)
 }
 
-//生成爬虫
+// 生成爬虫
 func CreateSpider(code, luafile string, newstate, thread bool) (*Spider, string) {
 	defer qu.Catch()
 	spider := &Spider{}
@@ -829,7 +841,7 @@ func CreateSpider(code, luafile string, newstate, thread bool) (*Spider, string)
 	return spider, ""
 }
 
-//更新爬虫
+// 更新爬虫
 func UpdateSpider(spider *Spider, code, script string) {
 	ts := &Spider{}
 	ts.Script.L = lua.NewState(lua.Options{
@@ -882,7 +894,7 @@ func UpdateSpider(spider *Spider, code, script string) {
 	spider.Infoformat = spider.GetIntVar("spiderInfoformat")
 }
 
-//多线程生成爬虫
+// 多线程生成爬虫
 func NewSpiderForThread(code, luafile string) (*Spider, string) {
 	defer qu.Catch()
 	spider := &Spider{}
@@ -938,7 +950,7 @@ func NewSpiderForThread(code, luafile string) (*Spider, string) {
 	return spider, ""
 }
 
-//下载量入库
+// 下载量入库
 func SaveDownCount(code string, addtotal bool, todayDowncount, todayRequestNum, yesterdayDowncount, yestoDayRequestNum int32) {
 	date := time.Unix(time.Now().Unix(), 0).Format(qu.Date_Short_Layout)
 	updata := map[string]interface{}{}
@@ -973,7 +985,7 @@ func SaveDownCount(code string, addtotal bool, todayDowncount, todayRequestNum,
 	MgoS.Update("spider_downlog", map[string]interface{}{"code": code, "date": date}, updata, true, false)
 }
 
-//获取下载的上下限(没用)
+// 获取下载的上下限(没用)
 func GetLimitDownload(code string) (uplimit, lowlimit int) {
 	defer qu.Catch()
 	ret, _ := MgoS.FindOne("spider_ldtime", map[string]interface{}{"code": code})
@@ -986,7 +998,7 @@ func GetLimitDownload(code string) (uplimit, lowlimit int) {
 	}
 }
 
-//拼装脚本
+// 拼装脚本
 func GetScriptByTmp(luaconfig map[string]interface{}) string {
 	defer qu.Catch()
 	script := ""
@@ -1064,7 +1076,7 @@ func GetScriptByTmp(luaconfig map[string]interface{}) string {
 	return script
 }
 
-//生成爬虫脚本
+// 生成爬虫脚本
 func GetTmpModel(param map[string][]interface{}) (script string, err interface{}) {
 	qu.Try(func() {
 		//param_common拼接
@@ -1110,7 +1122,7 @@ func GetTmpModel(param map[string][]interface{}) (script string, err interface{}
 	return script, err
 }
 
-//补充模型
+// 补充模型
 func ReplaceModel(script string, comm []interface{}, model map[string]interface{}) string {
 	defer qu.Catch()
 
@@ -1128,7 +1140,7 @@ func ReplaceModel(script string, comm []interface{}, model map[string]interface{
 	return script
 }
 
-//爬虫信息提交编辑器(心跳)
+// 爬虫信息提交编辑器(心跳)
 func SpiderInfoSend() {
 	time.Sleep(15 * time.Second)
 	list := []interface{}{}
@@ -1163,7 +1175,7 @@ func SpiderInfoSend() {
 	util.TimeAfterFunc(5*time.Minute, SpiderInfoSend, TimeChan)
 }
 
-//保存心跳信息
+// 保存心跳信息
 func SaveHeartInfo() {
 	time.Sleep(20 * time.Minute)
 	num := 0
@@ -1200,7 +1212,7 @@ func SaveHeartInfo() {
 	time.AfterFunc(1*time.Second, SaveHeartInfo)
 }
 
-//保存7000节点爬虫转增量节点日志
+// 保存7000节点爬虫转增量节点日志
 func SpiderCodeSendToEditor(code string) {
 	defer qu.Catch()
 	MgoEB.Save("luamovelog", map[string]interface{}{

+ 18 - 9
src/spider/script.go

@@ -1,4 +1,5 @@
-/**
+/*
+*
 脚本加载+调用 封装,
 前期走文件系统加载
 后期走数据库配置,
@@ -38,7 +39,7 @@ import (
 	"golang.org/x/text/transform"
 )
 
-//脚本
+// 脚本
 type Script struct {
 	//Ishttps            bool
 	SCode, ScriptFile  string
@@ -67,14 +68,13 @@ const (
 
 var workTime = true
 
-//
 func init() {
 	go isWorkTime()
 }
 
 var TimeSleepChan = make(chan bool, 1)
 
-//加载文件
+// 加载文件
 func (s *Script) LoadScript(site, channel, user *string, code, script_file string, newstate bool, thread bool) string {
 	defer qu.Catch()
 	s.SCode = code
@@ -925,6 +925,17 @@ func (s *Script) LoadScript(site, channel, user *string, code, script_file strin
 		S.Push(lua.LString(result))
 		return 1
 	}))
+	//GB2312字符集解码
+	s.L.SetGlobal("decodeGB2312", s.L.NewFunction(func(S *lua.LState) int {
+		text := S.ToString(-1)
+		result := ""
+		decodedString, _, err := transform.String(simplifiedchinese.GB18030.NewDecoder(), text)
+		if err == nil {
+			result = decodedString
+		}
+		S.Push(lua.LString(result))
+		return 1
+	}))
 	//aes cbc模式加密
 	s.L.SetGlobal("aesEncryptCBC", s.L.NewFunction(func(S *lua.LState) int {
 		origData := S.ToString(-3)
@@ -1284,7 +1295,7 @@ func getChildrenLen(sq *gq.Selection) (ret int) {
 //	s.LoadScript(s.SCode, s.ScriptFile, false)
 //}
 
-//unicode转码
+// unicode转码
 func transUnic(str string) string {
 	buf := bytes.NewBuffer(nil)
 	i, j := 0, len(str)
@@ -1312,12 +1323,11 @@ func transUnic(str string) string {
 	return buf.String()
 }
 
-//取得变量
+// 取得变量
 func (s *Script) GetVar(key string) string {
 	return s.L.GetGlobal(key).String()
 }
 
-//
 func (s *Script) GetIntVar(key string) int {
 	lv := s.L.GetGlobal(key)
 	if v, ok := lv.(lua.LNumber); ok {
@@ -1326,7 +1336,6 @@ func (s *Script) GetIntVar(key string) int {
 	return -1
 }
 
-//
 func (s *Script) GetBoolVar(key string) bool {
 	lv := s.L.GetGlobal(key)
 	if v, ok := lv.(lua.LBool); ok {
@@ -1340,7 +1349,7 @@ func isWorkTime() {
 	util.TimeAfterFunc(10*time.Minute, isWorkTime, TimeChan)
 }
 
-//设置睡眠时间
+// 设置睡眠时间
 func SleepTime(basetime int, times []time.Duration) {
 	st := 0 //记录最后睡眠时长
 	base := float64(basetime * 60)

+ 157 - 24
src/spider/spider.go

@@ -1,4 +1,5 @@
-/**
+/*
+*
 爬虫,脚本接口,需要扩展
 */
 package spider
@@ -112,7 +113,7 @@ type DelaySite struct {
 	Compete   bool
 }
 
-//任务
+// 任务
 func (s *Spider) StartJob() {
 	s.Stop = false
 	s.Pass = false
@@ -120,7 +121,7 @@ func (s *Spider) StartJob() {
 	go s.ExecJob(false)
 }
 
-//单次执行
+// 单次执行
 func (s *Spider) ExecJob(reload bool) {
 	defer func() {
 		s.ExecuteOkTime = time.Now().Unix()
@@ -150,11 +151,14 @@ func (s *Spider) ExecJob(reload bool) {
 	//}
 	//判断是否使用高并发下载三级页
 	var err interface{}
-	if util.Config.PageTurnInfo.ListThreadsNum > 1 {
+	if Supplement {
+		err = s.SupplementDownListPageItem() //增量补采数据,下载列表
+	} else if util.Config.PageTurnInfo.ListThreadsNum > 1 {
 		err = s.DownListPageItemByThreads() //并发下载列表
 	} else {
 		err = s.DownListPageItem() //下载列表
 	}
+
 	//if util.Config.Working == 0 && util.Config.Modal == 1 && !util.Config.IsHistoryEvent {
 	//	err = s.DownListPageItemByThreads() //下载列表
 	//} else {
@@ -168,7 +172,7 @@ func (s *Spider) ExecJob(reload bool) {
 		SpiderCodeSendToEditor(s.Code)       //历史转增量爬虫发送编辑器,切换节点上下架
 		return
 	} else {
-		if util.Config.Working == 0 { //高性能模式
+		if util.Config.Working == 0 && !Supplement { //高性能模式
 			/*
 				for !s.Stop && s.Pass {
 					util.TimeSleepFunc(2*time.Second, TimeSleepChan)
@@ -191,13 +195,13 @@ func (s *Spider) ExecJob(reload bool) {
 					return
 				}
 			}
-		} else { //排队模式
+		} else { //排队模式或者数据补采
 			return
 		}
 	}
 }
 
-//获取最新时间--作为最后更新时间
+// 获取最新时间--作为最后更新时间
 func (s *Spider) GetLastPublishTime() (errs interface{}) {
 	defer qu.Catch()
 	var lastpublishtime string
@@ -229,7 +233,7 @@ func (s *Spider) GetLastPublishTime() (errs interface{}) {
 	return nil
 }
 
-//下载列表(较DownListPageItemBack去掉了无数据的重试和重复页记录)
+// 下载列表(较DownListPageItemBack去掉了无数据的重试和重复页记录)
 func (s *Spider) DownListPageItem() (errs interface{}) {
 	defer qu.Catch()
 	start, max := s.GetIntVar("spiderStartPage"), s.GetIntVar("spiderMaxPage") //起始页、最大页
@@ -607,7 +611,7 @@ func (s *Spider) DownListPageItemBack() (errs interface{}) {
 	return errs
 }
 
-//并发下载列表
+// 并发下载列表
 func (s *Spider) DownListPageItemByThreads() (errs interface{}) {
 	defer qu.Catch()
 	start, max := s.GetIntVar("spiderStartPage"), s.GetIntVar("spiderMaxPage") //起始页、最大页
@@ -932,7 +936,133 @@ func (s *Spider) DownListPageItemByThreadsBack() (errs interface{}) {
 	return errs
 }
 
-//下载某一页数据
+// 补采下载列表
+func (s *Spider) SupplementDownListPageItem() (errs interface{}) {
+	defer qu.Catch()
+	var (
+		errtimes       int    //采集异常次数(暂定10次)
+		errPageNum     int    //当前采集异常页码
+		downtimes      int    //记录某页重试次数(暂定3次)
+		downloadAllNum int    //记录本次采集,信息采集总量
+		saveAllNum     int    //记录本次采集,信息补采总量
+		repeatAllNum   int    //记录本次采集,信息重复总量
+		pageTitleHash  string //记录当前页所有title文本
+		finishText     = "正常退出"
+	)
+	start := 1 //起始页
+	for {
+		if errtimes >= Supplement_MaxErrorTimes { //连续异常次数超过10次,爬虫不再翻页
+			finishText = "异常退出"
+			logger.Info(s.Code + "连续10页采集异常")
+			break
+		}
+		if err := s.L.CallByParam(lua.P{
+			Fn:      s.L.GetGlobal("downloadAndParseListPage"),
+			NRet:    1,
+			Protect: true,
+		}, lua.LNumber(start)); err != nil {
+			//panic(s.Code + "," + err.Error())
+			logger.Error("列表页采集报错", start, s.Code+","+err.Error())
+			errs = err.Error()
+			if downtimes < 3 {
+				downtimes++
+			} else if errtimes == 0 || start == errPageNum+1 {
+				errtimes++
+				errPageNum = start
+				start++
+				downtimes = 0
+			}
+			continue
+		}
+		lv := s.L.Get(-1)
+		s.L.Pop(1)
+		if tbl, ok := lv.(*lua.LTable); ok {
+			qu.Debug(tbl.Len())
+			if tabLen := tbl.Len(); tabLen > 0 { //列表页有数据,根据列表页信息下载三级页
+				repeatListNum := 0 // 当前列表页连接重复个数
+				isBreak := false
+				var publishtimeErrTimes int
+				var text string
+				num := 1
+				for ; num <= tabLen; num++ {
+					v := tbl.RawGetInt(num).(*lua.LTable)
+					tmp := util.TableToMap(v)
+					pTmp := qu.ObjToString(tmp["publishtime"])
+					title := qu.ObjToString(tmp["title"])
+					text += title
+					pTime, _ := time.ParseInLocation(qu.Date_Full_Layout, pTmp, time.Local)
+					publishtime := pTime.Unix()
+					if publishtime > 1000000000 && publishtime < Supplement_Publishtime { //正常退出
+						isBreak = true
+						break
+					} else if publishtime <= 1000000000 { //异常发布时间
+						publishtimeErrTimes++
+					}
+					tmp["dataging"] = 0 //数据中打标记dataging=0
+					s.DownloadDetailItem(tmp, &repeatListNum)
+				}
+				downloadAllNum += tabLen
+				repeatAllNum += repeatListNum
+				saveAllNum += num - 1 - repeatListNum
+				tmpPageTitleHash := pageTitleHash
+				pageTitleHash = util.HexText(text)
+				if tabLen == publishtimeErrTimes || tmpPageTitleHash == pageTitleHash { //当前页数据发布时间均异常;当前页与上页采集内容一致
+					//if errtimes == 0 || start == errPageNum+1  {
+					errtimes++
+					errPageNum = start
+					start++
+					//}
+					continue
+				} else if isBreak { //中断不再采集
+					start++
+					break
+				}
+			} else {
+				if downtimes < 3 {
+					downtimes++
+				} else if errtimes == 0 || start == errPageNum+1 {
+					errtimes++
+					errPageNum = start
+					start++
+					downtimes = 0
+				}
+				continue
+			}
+		} else {
+			if downtimes < 3 {
+				downtimes++
+			} else if errtimes == 0 || start == errPageNum+1 {
+				errtimes++
+				errPageNum = start
+				start++
+				downtimes = 0
+			}
+			continue
+		}
+		start++
+		downtimes = 0
+		errtimes = 0
+		errPageNum = 0
+		util.TimeSleepFunc(100*time.Millisecond, TimeSleepChan)
+	}
+	logger.Info(s.Code, "本轮列表页采集详情:", downloadAllNum, repeatAllNum, start, finishText)
+	if !util.Config.IsHistoryEvent && !s.Stop { //非历史节点统计下载率
+		save := map[string]interface{}{
+			"site":       s.Name,
+			"channel":    s.Channel,
+			"spidercode": s.Code,
+			"comeintime": time.Now().Unix(),
+			"modifyuser": s.MUserName,
+			"endpage":    start,
+			"finish":     finishText,
+			"num":        saveAllNum,
+		}
+		MgoS.Save("spider_supplement", save)
+	}
+	return errs
+}
+
+// 下载某一页数据
 func (s *Spider) DownListOnePage(pagenum int) (downnum, repeatnum int) {
 	defer qu.Catch()
 	downtimes := 0
@@ -988,7 +1118,7 @@ func (s *Spider) DownListOnePage(pagenum int) (downnum, repeatnum int) {
 	return
 }
 
-//开启单独线程继续采集列表页
+// 开启单独线程继续采集列表页
 func ContinueDownListPageItem(s *Spider) {
 	defer qu.Catch()
 	spTmp, errstr := CreateSpider(s.SCode, s.ScriptFile, true, true) //生成新爬虫
@@ -1004,7 +1134,7 @@ func ContinueDownListPageItem(s *Spider) {
 	}
 }
 
-//遍历,开启三级页下载(历史补漏)
+// 遍历,开启三级页下载(历史补漏)
 func (s *Spider) HistoricalMendDownloadDetailItem(p interface{}) {
 	//qu.Debug("--------------历史下载-----------------")
 	defer qu.Catch()
@@ -1121,7 +1251,7 @@ func (s *Spider) HistoricalMendDownloadDetailItem(p interface{}) {
 	//qu.Debug("--------------保存结束---------------")
 }
 
-//遍历,开启三级页下载(增量)
+// 遍历,开启三级页下载(增量)
 func (s *Spider) DownloadDetailItem(p interface{}, num *int) {
 	defer qu.Catch()
 	var err interface{}
@@ -1138,13 +1268,16 @@ func (s *Spider) DownloadDetailItem(p interface{}, num *int) {
 	hashHref := util.HexText(href)
 	//列表页redis判重
 	isExist := util.RedisExist("list", "list_"+hashHref)
+	if Supplement { //补采,再进行全量redis判重
+		isExist, _ = util.ExistsBloomRedis("href", href)
+	}
 	if isExist {
 		*num++ //已采集
 		return
 	}
 	id := "" //记录spider_listdata中保存的数据id,便于下载成功后更新状态
 	//if util.Config.Modal == 1 || (util.Config.IsHistoryEvent && s.GetVar("spiderType") == "history") { //列表页、详情页分开采集模式节点和7000节点新爬虫采集的数据数据
-	if util.Config.Modal == 1 || util.Config.IsHistoryEvent { //分开采集模式和历史节点(7000)
+	if util.Config.Modal == 1 || util.Config.IsHistoryEvent || Supplement { //分开采集模式和历史节点(7000)
 		SaveHighListPageData(paramdata, hashHref, num) //存表
 		return
 	} else {
@@ -1230,7 +1363,7 @@ func (s *Spider) DownloadDetailItem(p interface{}, num *int) {
 	Store(s.StoreMode, s.StoreToMsgEvent, s.Collection, s.CoverAttr, data, true)
 }
 
-//遍历下载名录
+// 遍历下载名录
 func (s *Spider) DownloadDetailByNames(p interface{}) {
 	defer qu.Catch()
 	var err interface{}
@@ -1266,7 +1399,7 @@ func (s *Spider) DownloadDetailByNames(p interface{}) {
 	Store(s.StoreMode, s.StoreToMsgEvent, s.Collection, s.CoverAttr, data, true)
 }
 
-//下载解析详情页
+// 下载解析详情页
 func (s *Spider) DownloadDetailPage(param map[string]interface{}, data map[string]interface{}) (map[string]interface{}, interface{}) {
 	defer qu.Catch()
 	s.LastHeartbeat = time.Now().Unix()
@@ -1321,7 +1454,7 @@ func (s *Spider) DownloadDetailPage(param map[string]interface{}, data map[strin
 	}
 }
 
-//高性能模式定时采集三级页信息
+// 高性能模式定时采集三级页信息
 func DetailData() {
 	defer qu.Catch()
 	<-InitAllLuaOver                                             //脚本加载完毕,执行
@@ -1340,7 +1473,7 @@ func GetListDataDownloadDetail() {
 	})
 }
 
-//高性能模式根据列表页数据下载三级页
+// 高性能模式根据列表页数据下载三级页
 func (s *Spider) DownloadHighDetail(reload bool) {
 	defer qu.Catch()
 	for {
@@ -1353,7 +1486,7 @@ func (s *Spider) DownloadHighDetail(reload bool) {
 	}
 }
 
-//队列模式根据列表页数据下载三级页
+// 队列模式根据列表页数据下载三级页
 func (s *Spider) DownloadListDetail(reload bool) {
 	defer qu.Catch()
 	s.DownloadDetail(reload, false)
@@ -1366,7 +1499,7 @@ func (s *Spider) DownloadListDetail(reload bool) {
 	CC2 <- s.L
 }
 
-//下载详情页
+// 下载详情页
 func (s *Spider) DownloadDetail(reload bool, isHistory bool) {
 	defer qu.Catch()
 	coll := "spider_highlistdata"
@@ -1600,7 +1733,7 @@ func (s *Spider) DownloadDetail(reload bool, isHistory bool) {
 	}
 }
 
-//初始化sp对象
+// 初始化sp对象
 func NewSpiderByScript(num int, code, script string, spChan chan *Spider) {
 	for i := 1; i <= num; i++ {
 		spTmp, errstr := CreateSpider(code, script, true, true)
@@ -1612,7 +1745,7 @@ func NewSpiderByScript(num int, code, script string, spChan chan *Spider) {
 	}
 }
 
-//detail含“详情请访问原网页!”且附件未下成功的,不计入下载成功
+// detail含“详情请访问原网页!”且附件未下成功的,不计入下载成功
 func AnalysisProjectInfo(data map[string]interface{}) string {
 	defer qu.Catch()
 	detail := qu.ObjToString(data["detail"])
@@ -1641,14 +1774,14 @@ func AnalysisProjectInfo(data map[string]interface{}) string {
 	return ""
 }
 
-//打印线程数
+// 打印线程数
 func AllThreadLog() {
 	logger.Info("List Download All Thread:", ListAllThreadNum)
 	logger.Info("Detail Download All Thread:", AllThreadNum)
 	time.AfterFunc(1*time.Minute, AllThreadLog)
 }
 
-//获取hascode
+// 获取hascode
 func GetHas1(data string) string {
 	t := sha1.New()
 	io.WriteString(t, data)

+ 17 - 17
src/spider/store.go

@@ -28,7 +28,7 @@ type LogMap struct {
 	DownloadCount int //下载量
 }
 
-//数据存储批量
+// 数据存储批量
 func StoreBlak(mode, event int, c, coverAttr string, data []map[string]interface{}) {
 	defer util.Catch()
 	for _, v := range data {
@@ -49,7 +49,7 @@ func StoreBlak(mode, event int, c, coverAttr string, data []map[string]interface
 	}
 }
 
-//数据存储
+// 数据存储
 func Store(mode, event int, c, coverAttr string, data map[string]interface{}, flag bool) {
 	defer util.Catch()
 	if t, err := time.ParseInLocation(util.Date_Full_Layout, util.ObjToString(data["publishtime"]), time.Local); err == nil {
@@ -76,7 +76,7 @@ func Store(mode, event int, c, coverAttr string, data map[string]interface{}, fl
 		//}
 	} else if mode == 2 {
 		data["T"] = c
-		SaveObjNew(event, coverAttr, data, flag)
+		SaveObj(event, coverAttr, data, flag)
 	}
 	//公示数据,发送其他服务请求
 	if strings.HasPrefix(c, "ecps") {
@@ -84,7 +84,7 @@ func Store(mode, event int, c, coverAttr string, data map[string]interface{}, fl
 	}
 }
 
-//保存验证错误日志
+// 保存验证错误日志
 func saveVerificationLog(code, name, url, content string) {
 	defer util.Catch()
 	data := map[string]interface{}{}
@@ -97,7 +97,7 @@ func saveVerificationLog(code, name, url, content string) {
 	MgoS.Save("spider_errlog", data)
 }
 
-//查找信息是否存在
+// 查找信息是否存在
 func findHasExit(c, q string) bool {
 	defer util.Catch()
 	ret, _ := MgoS.FindOne(c, q)
@@ -108,7 +108,7 @@ func findHasExit(c, q string) bool {
 	}
 }
 
-//获取最后发布时间
+// 获取最后发布时间
 var spider_ldtime = map[string]map[string]interface{}{}
 
 func GetLastPubtime(code string) int64 {
@@ -127,7 +127,7 @@ func GetLastPubtime(code string) int64 {
 	}
 }
 
-//获取最后执行时间
+// 获取最后执行时间
 func GetLastExectime(code string) int64 {
 	defer util.Catch()
 	if len(spider_ldtime) < 1 {
@@ -144,7 +144,7 @@ func GetLastExectime(code string) int64 {
 	}
 }
 
-//获取下载量
+// 获取下载量
 var spider_downlog = map[string]map[string]interface{}{}
 
 func GetDownloadLast(code, date string) map[string]interface{} {
@@ -162,7 +162,7 @@ func GetDownloadLast(code, date string) map[string]interface{} {
 	}
 }
 
-//GcCount
+// GcCount
 func GcCount() {
 	t := time.Now()
 	if t.Hour() == 0 {
@@ -188,12 +188,12 @@ func GcCount() {
 	lu.TimeAfterFunc(30*time.Minute, GcCount, TimeChan)
 }
 
-//保存modal=1模式采集的列表页信息
+// 保存modal=1模式采集的列表页信息
 func SaveHighListPageData(tmp map[string]interface{}, hashHref string, num *int) {
 	tmp["state"] = 0
 	tmp["event"] = lu.Config.Uploadevent
 	tmp["comeintime"] = time.Now().Unix()
-	if lu.Config.IsHistoryEvent {
+	if lu.Config.IsHistoryEvent || Supplement { //补采历史
 		MgoS.Save("spider_historydata", tmp)
 	} else {
 		MgoS.Save("spider_highlistdata", tmp)
@@ -201,7 +201,7 @@ func SaveHighListPageData(tmp map[string]interface{}, hashHref string, num *int)
 	lu.RedisSet("list", "list_"+hashHref, "", 86400*365*2)
 }
 
-//保存7410、7500、7510、7520、7700采集的列表页信息
+// 保存7410、7500、7510、7520、7700采集的列表页信息
 func SaveListPageData(tmp map[string]interface{}, id *string, isEsRepeat bool) {
 	//spider_listdata数据保证href唯一
 	count := MgoS.Count("spider_listdata", map[string]interface{}{"href": tmp["href"]})
@@ -218,7 +218,7 @@ func SaveListPageData(tmp map[string]interface{}, id *string, isEsRepeat bool) {
 	*id = MgoS.Save("spider_listdata", tmp)
 }
 
-//获取第day天凌晨的时间戳
+// 获取第day天凌晨的时间戳
 func GetTime(day int) int64 {
 	nowTime := time.Now().AddDate(0, 0, day)
 	timeStr := util.FormatDate(&nowTime, util.Date_Short_Layout)
@@ -226,7 +226,7 @@ func GetTime(day int) int64 {
 	return t.Unix()
 }
 
-//更新state状态
+// 更新state状态
 func UpdateHighListDataByCode(code string) {
 	query := map[string]interface{}{
 		"spidercode": code,
@@ -245,7 +245,7 @@ func UpdateHighListDataByCode(code string) {
 	MgoS.Update("spider_highlistdata", query, set, false, true)
 }
 
-//心跳
+// 心跳
 func UpdateHeart(site, channel, code, user, t string, firstpage bool) {
 	//sp, spiderOk := LoopListPath.Load(code)
 	//if spiderOk && sp != nil {
@@ -287,7 +287,7 @@ func UpdateHeart(site, channel, code, user, t string, firstpage bool) {
 	//}
 }
 
-//批量更新心跳信息
+// 批量更新心跳信息
 func UpdateHeartInfo() {
 	fmt.Println("Update Heart Info...")
 	heartarr := make([][]map[string]interface{}, 200)
@@ -324,7 +324,7 @@ func UpdateHeartInfo() {
 	}
 }
 
-//批量保存data_bak
+// 批量保存data_bak
 func SaveDataBak() {
 	fmt.Println("Save DataBak...")
 	savearr := make([]map[string]interface{}, 200)

+ 51 - 0
src/spider/supplement.go

@@ -0,0 +1,51 @@
+package spider
+
+import (
+	"flag"
+	"github.com/cron"
+	"os"
+)
+
+/*
+重点爬虫,定期补采
+*/
+
+var (
+	Supplement               bool   //是否为定时重采
+	Supplement_Cycle         string //运行周期(day:每天定点执行;week:每周定点执行)
+	Supplement_Day           int    //补采多少天的数据
+	Supplement_Publishtime   int64  //补采数据最小的发布时间
+	Supplement_StartCron     string //开始
+	Supplement_EndCron       string //关闭
+	Supplement_MaxErrorTimes int    //连续异常次数,中断采集
+)
+
+func InitSupplement() {
+	flag.BoolVar(&Supplement, "s", false, "是否为补采节点")
+	flag.StringVar(&Supplement_Cycle, "c", "day", "day:每天定点执行;week:每周定点执行")
+	flag.IntVar(&Supplement_Day, "d", 1, "补采几天的数据")
+	flag.IntVar(&Supplement_MaxErrorTimes, "e", 5, "连续几页异常采集中断")
+	if Supplement {
+		Supplement_Publishtime = GetTime(-Supplement_Day)
+		if Supplement_Cycle == "day" {
+			Supplement_StartCron = "0 16 9 ? * *"
+			//InitSpider()
+			Supplement_EndCron = "0 0 9 ? * *"
+		} else if Supplement_Cycle == "week" {
+			Supplement_StartCron = "0 0 0 ? * SAT"
+			Supplement_EndCron = "0 0 0 ? * MON"
+		}
+		c := cron.New()
+		c.Start()
+		c.AddFunc(Supplement_StartCron, SupplementStart)
+		c.AddFunc(Supplement_EndCron, SupplementEnd)
+	}
+}
+
+func SupplementStart() {
+	InitSpider() //加载爬虫,执行采集
+}
+
+func SupplementEnd() {
+	os.Exit(-1) //关闭应用
+}