/** * 工具包封装 */ package util import ( "crypto/sha256" "fmt" "io/ioutil" "log" "net/url" "regexp" "strings" "time" "unicode/utf8" // "app.yhyue.com/moapp/jybase/redis" "KeyWebsiteMonitor/util" "github.com/yuin/gopher-lua" ) // ParseTimeStr 尝试解析给定的时间字符串,使用提供的格式列表。 自己封装的 func ParseTimeStr(timeStr string) int64 { timeStr, err := ExtractDates(timeStr) if err != nil { return 0 } if timeStr == "" { return 0 } formats := []string{ "02/01/2006 15:04:05", // 美国常用格式 "01-02-2006 15:04:05", // 欧洲常用格式 "01/02/2006 15:04:05", // 另一种欧洲格式 "2006-01-02T15:04:05", // ISO 8601格式 "2006-01-02", "2006.01.02", "2006/01/02", "2006-01-02 15:04:05", // 标准格式 "2006.01.02 15:04:05", "2006/01/02 15:04:05", "2006/1/02", "2006-1-02", "2006.1.02", "2006/1/2", "2006-1-2", "2006.1.2", "2006年01月02日", "2006年1月2日", "2006年1月02日", "2006年01月02", "2006年1月02", "2006年1月2", } for _, format := range formats { loc, _ := time.LoadLocation("Asia/Shanghai") t, err := time.ParseInLocation(format, timeStr, loc) if err == nil { return t.Unix() } } return 0 } //GetDockerId 获取docker容器id func GetDockerId() string { hostFile := "/etc/hostname" containerID, err := ioutil.ReadFile(hostFile) if err != nil { fmt.Println("读取容器 ID 失败:", err) return "" } return string(containerID) } //获取redis的key func GetRedisKey(href string) string { hashHref := HexText(href) key := "cmsp_list_" + hashHref return key } //判断redis中是否存在 func GetRedisKeyExists(href string) bool { key := GetRedisKey(href) // exists, _ := redis.Exists("other", key) exists := spider_com.RedisExist("other", key) return exists } //向redis中存值 func PutRedisKey(href string) bool { key := GetRedisKey(href) timeout := 86400 * 365 * 2 // bl :=redis.Put("other", key, "", timeout) bl := spider_com.RedisSet("other", key, "", timeout) return bl } //求hash func HexText(href string) string { h := sha256.New() h.Write([]byte(href)) return fmt.Sprintf("%x", h.Sum(nil)) } // Catch 异常崩溃拦截 func Catch() { if err := recover(); err != nil { log.Println(err) } } // MapToTable converts a Go map to a lua table func MapToTable(m map[string]interface{}) *lua.LTable { // Main table pointer resultTable := &lua.LTable{} // Loop map for key, element := range m { switch element.(type) { case float64: resultTable.RawSetString(key, lua.LNumber(element.(float64))) case int64: resultTable.RawSetString(key, lua.LNumber(element.(int64))) case string: resultTable.RawSetString(key, lua.LString(element.(string))) case bool: resultTable.RawSetString(key, lua.LBool(element.(bool))) case []byte: resultTable.RawSetString(key, lua.LString(string(element.([]byte)))) case map[string]interface{}: // Get table from map tble := MapToTable(element.(map[string]interface{})) resultTable.RawSetString(key, tble) case time.Time: resultTable.RawSetString(key, lua.LNumber(element.(time.Time).Unix())) case []map[string]interface{}: // Create slice table sliceTable := &lua.LTable{} // Loop element for _, s := range element.([]map[string]interface{}) { // Get table from map tble := MapToTable(s) sliceTable.Append(tble) } // Set slice table resultTable.RawSetString(key, sliceTable) case []interface{}: // Create slice table sliceTable := &lua.LTable{} // Loop interface slice for _, s := range element.([]interface{}) { // Switch interface type switch s.(type) { case map[string]interface{}: // Convert map to table t := MapToTable(s.(map[string]interface{})) // Append result sliceTable.Append(t) case float64: // Append result as number sliceTable.Append(lua.LNumber(s.(float64))) case string: // Append result as string sliceTable.Append(lua.LString(s.(string))) case bool: // Append result as bool sliceTable.Append(lua.LBool(s.(bool))) } } // Append to main table resultTable.RawSetString(key, sliceTable) } } return resultTable } // TabletoMap converts a lua table to go map func TableToMap(t *lua.LTable) map[string]interface{} { ret := make(map[string]interface{}) t.ForEach(func(k, v lua.LValue) { key := fmt.Sprint(k) if val, ok := v.(*lua.LTable); ok { ret[key] = TableToMap(val) } else { if val, ok := v.(lua.LString); ok { ret[key] = string(val) } else if val, ok := v.(lua.LNumber); ok { ret[key] = int64(val) } else if val, ok := v.(lua.LBool); ok { ret[key] = bool(val) } else { ret[key] = fmt.Sprint(v) } } }) return ret } // urlLastSegs func urlLastSegs(href string, segs int) string { tmp := strings.Split(href, "/") if len(tmp) < segs { return href } return strings.Join(tmp[len(tmp)-segs-1:], "/") } // StrHasFlags func StrHasFlags(src string, flags []string) bool { for _, v := range flags { if strings.Contains(src, v) { return true } } return false } // ExtractDomain 从 URL 中提取域名 func ExtractDomain(urlString string) (string, error) { // 解析 URL u, err := url.Parse(urlString) if err != nil { return "", err } // 提取主机名 host := u.Hostname() // 如果主机名包含端口号,去除端口号 host = strings.Split(host, ":")[0] return host, nil } // 定义所有可能的时间格式 var timeFormats = []string{ "02/01/2006 15:04:05", "01-02-2006 15:04:05", "01/02/2006 15:04:05", "2006-01-02T15:04:05", "2006-01-02", "2006.01.02", "2006/01/02", "2006-01-02 15:04:05", "2006.01.02 15:04:05", "2006/01/02 15:04:05", "2006/1/02", "2006-1-02", "2006.1.02", "2006/1/2", "2006-1-2", "2006.1.2", "2006年01月02日", "2006年1月2日", "2006年1月02日", "2006年01月02", "2006年1月02", "2006年1月2", } // ExtractDates 从文本中提取所有符合给定时间格式的日期和时间。 func ExtractDates(text string) (string, error) { // 构建正则表达式,匹配所有给定的时间格式 datePattern := `(0[1-9]|[12][0-9]|3[01])[./-](0[1-9]|1[012])[./-](19|20)\d{2}` + `(?:\s+([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]))?` + `|` + `(19|20)\d{2}[./-](0[1-9]|1[012]|[1-9])[./-](0[1-9]|[12][0-9]|3[01]|[1-9])` + `(?:\s+([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]))?` + `|` + `(19|20)\d{2}[T](0[1-9]|1[012])[./-](0[1-9]|[12][0-9]|3[01])` + `(?:\s+([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]))?` + `|` + `(19|20)\d{2}[年](0[1-9]|1[012])[月](0[1-9]|[12][0-9]|3[01])[日]` + `|` + `(19|20)\d{2}[年](0[1-9]|1[0-9])[月](0[1-9]|[12][0-9]|3[01])[日]` + `|` + `(19|20)\d{2}[年](0[1-9]|1[0-9]|[0-9])[月](0[1-9]|[12][0-9]|3[01]|[0-9])[日]?` // 编译正则表达式 re, err := regexp.Compile(datePattern) if err != nil { return "", err } // 找到所有匹配项 matches := re.FindAllString(text, -1) if len(matches) == 0 { datePattern2 := `\b\d{1,2}[-./月]\d{1,2}\b` // 编译正则表达式 re2, err := regexp.Compile(datePattern2) if err != nil { return "", err } // 找到所有匹配项 matches2 := re2.FindAllString(text, -1) if len(matches2) > 0 { match := matches2[0] // 获取当前时间 now := time.Now() currentYear := now.Year() completeDate := fmt.Sprintf("%d-%s", currentYear, match) return completeDate, nil } return "", nil } if len(matches) > 0 { return matches[0], nil } return "", nil } func RemoveNewlinesAndSpaces(text string) string { return strings.ReplaceAll(strings.ReplaceAll(text, "\n", ""), " ", "") } //判断是否是招标信息的标题 func IsBidTitle(title string) bool { length := utf8.RuneCountInString(title) if length < 4 { return false } pattern := `(?i)(?:招标|需求|预公告|采购|合同|中标|磋商|预选人|废标|流标|非招标|审批|竞价|挂牌|出让|出租|成交|结果|交易|竣工|开工|批准|建设|工程|更正|公告|备案|澄清|租赁|资产|转让|行政许可|土地|矿产|国土|使用权|验收|环保|环境|验收|林权|核准|项目|金额|中标|招标|竞价|编号|招标人|中标人|招标时间|中标时间|项目名称|公告名称|项目代码|项目编号|代理机构|供应方式|采购单位|采购项目|预算金额|合同编号|合同名称|采购人|供应商|合同金额|服务时间|服务要求|采购方式|网上竞价|开始时间|截止时间|预算金额|竞价明细|工程名称|建设单位|施工单位|工程费用|挂牌出让|出让年限|土地用途|宗地编号|土地面积|公示期|出让人|采购编号|发布时间|公示期|宗地编号|资金来源|建设地址|建设内容|建设期限|项目位置|供地方式|成交价格|批准单位|开工时间|竣工时间|签订时间|交地时间|最高限价|采购需求|最高限价|挂牌编号|挂牌价格|挂牌期限|公告日期|成交价格|成交数量|工期要求|工程地点|承包方式|发包人|发包地点|发包面积|发包要求|发包|招标|投标|竞标|询价|采购|合同|工程|项目|建设|施工|设计|监理|检测|验收|维修|改造|装修|设备|材料|供应|服务|合作|承包|发包|招标公告|招标文件|投标文件|中标公示|评标结果|合同签订|工程验收|采购公告|招标通知|投标通知|招标项目|招标公示|招标公告书|中标结果|中标通知|成交结果|中标名单|中标文件|中标公告|中标通告|中标通知书|废标|流标|变更公告|补遗|废标公告|流标公告|补遗公告|评标公示|评标通知|中标候选人|转让|建设许可证|环境影响|拍卖|出让|产权|出租|批复|租赁|变更|终止|询比|竞谈|比价|开标|中标|成交|单一|项目结果|磋商|谈判|竞争|比选|邀标|评标|资格预审|议价|中选|答疑|竞价转让|竞价|服务项目中标|中标药品|标段中标|中标品种|建设项目中标|部分中标|工程项目中标|包中标|工程施工中标|招标中标|公开招标中标|服务中标|中标企业|租赁中标|建设工程中标|配套工程中标|监理中标|中标产品|审计中标|系统中标|施工中标|初步设计中标|咨询服务中标|预中标|设计中标|药品中标|招标代理|招标代理服务|电子化公开招标|招标书第|招标计划|招标投标|服务公开招标|物资公开招标|设备公开招标|招标答疑|服务项目公开招标|分包公开招标|药品公开招标|建设公开招标|云商采购部|周采购计划|采购计划任务|物资采购计划|复印纸采购计划|专业分包|劳务分包|购销合同|车辆保险合同|合同段|总承包合同|监理合同|工程施工合同|合同能源管理|服务合同|合同续签|服务项目合同|租赁合同|合同订立|加油合同|标段合同|合同备案|建设项目合同|候选人公示|竣工验收|竣工财务决算|竣工决算|竣工结算|建设项目竣工|竣工测量|交竣工|竣工日期|设施竣工|竣工环境保护|竣工测绘|验收报告编制|消防验收|水土保持验收|行政审批|审批决定|施工图设计|建设项目施工|改造工程施工|施工图审查|施工监理|建设工程施工|工程施工监理|治理工程施工|土建施工|工程项目施工|提升工程施工|整治工程施工|养护工程施工|道路工程施工|改造施工|机电工程施工|标段施工|安装施工|扩建工程施工|建设施工|改扩建工程施工|装修工程施工|土建工程施工|配套工程施工|修复工程施工|二期工程施工|新建工程施工|一期工程施工|安装工程施工|维修工程施工|维修施工|迁改工程施工|零星工程施工|附属工程施工|改建工程施工|施工劳务|施工分包|段施工|大修工程施工|管网工程施工|修缮工程施工|段工程施工|道路施工|排水工程施工|装修施工|绿化工程施工|施工服务项目|精装修工程施工|大修施工|施工标|大中修工程施工|劳务施工|电气施工|施工图预算|综合治理工程施工|工程施工单位|施工过程|管道工程施工|重建工程施工|工程施工标|公路工程施工|标施工|绿化施工|施工阶段|施工标段|防护工程施工|工程施工第|恢复工程施工|施工一体化|主体施工|配电工程施工|工程设计施工|施工澄清|勘察设计|勘测设计|设计服务项目|建设项目初步设计|初步设计概算|建设项目设计|提升工程设计|城市设计|建设工程设计|改造工程设计|改造设计|治理工程设计|广告设计制作|规划设计研究院|加固设计|二期工程设计|工程项目设计|道路工程设计|设计搭建|改扩建工程设计|规划设计方案|系统设计|勘测设计院|设计审查|修复工程设计|装修设计|设计研究院|规划设计院|迁改工程设计|勘查设计|配套工程设计|软装设计|精装修设计|图纸设计|整治工程设计|建设项目方案设计|乡村规划设计|建筑设计方案|建设设计|招标|投标|竞标|询价|采购|合同|工程|项目|建设|施工|设计|监理|检测|验收|维修|改造|装修|设备|材料|供应|服务|合作|承包|发包|招标公告|招标文件|投标文件|中标公示|评标结果|合同签订|工程验收|采购公告|招标通知|投标通知|招标项目|招标公示|招标公告书|中标结果|中标通知|成交结果|中标名单|中标文件|中标公告|中标通告|中标通知书|废标|流标|变更公告|补遗|废标公告|流标公告|补遗公告|评标公示|评标通知|中标候选人)` matched, _ := regexp.MatchString(pattern, title) if matched { return true } return false }