util.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /**
  2. * 工具包封装
  3. */
  4. package util
  5. import (
  6. "crypto/sha256"
  7. "fmt"
  8. "io/ioutil"
  9. "log"
  10. "net/url"
  11. "regexp"
  12. "strings"
  13. "time"
  14. "unicode/utf8"
  15. // "app.yhyue.com/moapp/jybase/redis"
  16. "KeyWebsiteMonitor/util"
  17. "github.com/yuin/gopher-lua"
  18. )
  19. // ParseTimeStr 尝试解析给定的时间字符串,使用提供的格式列表。 自己封装的
  20. func ParseTimeStr(timeStr string) int64 {
  21. timeStr, err := ExtractDates(timeStr)
  22. if err != nil {
  23. return 0
  24. }
  25. if timeStr == "" {
  26. return 0
  27. }
  28. formats := []string{
  29. "02/01/2006 15:04:05", // 美国常用格式
  30. "01-02-2006 15:04:05", // 欧洲常用格式
  31. "01/02/2006 15:04:05", // 另一种欧洲格式
  32. "2006-01-02T15:04:05", // ISO 8601格式
  33. "2006-01-02",
  34. "2006.01.02",
  35. "2006/01/02",
  36. "2006-01-02 15:04:05", // 标准格式
  37. "2006.01.02 15:04:05",
  38. "2006/01/02 15:04:05",
  39. "2006/1/02",
  40. "2006-1-02",
  41. "2006.1.02",
  42. "2006/1/2",
  43. "2006-1-2",
  44. "2006.1.2",
  45. "2006年01月02日",
  46. "2006年1月2日",
  47. "2006年1月02日",
  48. "2006年01月02",
  49. "2006年1月02",
  50. "2006年1月2",
  51. }
  52. for _, format := range formats {
  53. loc, _ := time.LoadLocation("Asia/Shanghai")
  54. t, err := time.ParseInLocation(format, timeStr, loc)
  55. if err == nil {
  56. return t.Unix()
  57. }
  58. }
  59. return 0
  60. }
  61. //GetDockerId 获取docker容器id
  62. func GetDockerId() string {
  63. hostFile := "/etc/hostname"
  64. containerID, err := ioutil.ReadFile(hostFile)
  65. if err != nil {
  66. fmt.Println("读取容器 ID 失败:", err)
  67. return ""
  68. }
  69. return string(containerID)
  70. }
  71. //获取redis的key
  72. func GetRedisKey(href string) string {
  73. hashHref := HexText(href)
  74. key := "cmsp_list_" + hashHref
  75. return key
  76. }
  77. //判断redis中是否存在
  78. func GetRedisKeyExists(href string) bool {
  79. key := GetRedisKey(href)
  80. // exists, _ := redis.Exists("other", key)
  81. exists := spider_com.RedisExist("other", key)
  82. return exists
  83. }
  84. //向redis中存值
  85. func PutRedisKey(href string) bool {
  86. key := GetRedisKey(href)
  87. timeout := 86400 * 365 * 2
  88. // bl :=redis.Put("other", key, "", timeout)
  89. bl := spider_com.RedisSet("other", key, "", timeout)
  90. return bl
  91. }
  92. //求hash
  93. func HexText(href string) string {
  94. h := sha256.New()
  95. h.Write([]byte(href))
  96. return fmt.Sprintf("%x", h.Sum(nil))
  97. }
  98. // Catch 异常崩溃拦截
  99. func Catch() {
  100. if err := recover(); err != nil {
  101. log.Println(err)
  102. }
  103. }
  104. // MapToTable converts a Go map to a lua table
  105. func MapToTable(m map[string]interface{}) *lua.LTable {
  106. // Main table pointer
  107. resultTable := &lua.LTable{}
  108. // Loop map
  109. for key, element := range m {
  110. switch element.(type) {
  111. case float64:
  112. resultTable.RawSetString(key, lua.LNumber(element.(float64)))
  113. case int64:
  114. resultTable.RawSetString(key, lua.LNumber(element.(int64)))
  115. case string:
  116. resultTable.RawSetString(key, lua.LString(element.(string)))
  117. case bool:
  118. resultTable.RawSetString(key, lua.LBool(element.(bool)))
  119. case []byte:
  120. resultTable.RawSetString(key, lua.LString(string(element.([]byte))))
  121. case map[string]interface{}:
  122. // Get table from map
  123. tble := MapToTable(element.(map[string]interface{}))
  124. resultTable.RawSetString(key, tble)
  125. case time.Time:
  126. resultTable.RawSetString(key, lua.LNumber(element.(time.Time).Unix()))
  127. case []map[string]interface{}:
  128. // Create slice table
  129. sliceTable := &lua.LTable{}
  130. // Loop element
  131. for _, s := range element.([]map[string]interface{}) {
  132. // Get table from map
  133. tble := MapToTable(s)
  134. sliceTable.Append(tble)
  135. }
  136. // Set slice table
  137. resultTable.RawSetString(key, sliceTable)
  138. case []interface{}:
  139. // Create slice table
  140. sliceTable := &lua.LTable{}
  141. // Loop interface slice
  142. for _, s := range element.([]interface{}) {
  143. // Switch interface type
  144. switch s.(type) {
  145. case map[string]interface{}:
  146. // Convert map to table
  147. t := MapToTable(s.(map[string]interface{}))
  148. // Append result
  149. sliceTable.Append(t)
  150. case float64:
  151. // Append result as number
  152. sliceTable.Append(lua.LNumber(s.(float64)))
  153. case string:
  154. // Append result as string
  155. sliceTable.Append(lua.LString(s.(string)))
  156. case bool:
  157. // Append result as bool
  158. sliceTable.Append(lua.LBool(s.(bool)))
  159. }
  160. }
  161. // Append to main table
  162. resultTable.RawSetString(key, sliceTable)
  163. }
  164. }
  165. return resultTable
  166. }
  167. // TabletoMap converts a lua table to go map
  168. func TableToMap(t *lua.LTable) map[string]interface{} {
  169. ret := make(map[string]interface{})
  170. t.ForEach(func(k, v lua.LValue) {
  171. key := fmt.Sprint(k)
  172. if val, ok := v.(*lua.LTable); ok {
  173. ret[key] = TableToMap(val)
  174. } else {
  175. if val, ok := v.(lua.LString); ok {
  176. ret[key] = string(val)
  177. } else if val, ok := v.(lua.LNumber); ok {
  178. ret[key] = int64(val)
  179. } else if val, ok := v.(lua.LBool); ok {
  180. ret[key] = bool(val)
  181. } else {
  182. ret[key] = fmt.Sprint(v)
  183. }
  184. }
  185. })
  186. return ret
  187. }
  188. // urlLastSegs
  189. func urlLastSegs(href string, segs int) string {
  190. tmp := strings.Split(href, "/")
  191. if len(tmp) < segs {
  192. return href
  193. }
  194. return strings.Join(tmp[len(tmp)-segs-1:], "/")
  195. }
  196. // StrHasFlags
  197. func StrHasFlags(src string, flags []string) bool {
  198. for _, v := range flags {
  199. if strings.Contains(src, v) {
  200. return true
  201. }
  202. }
  203. return false
  204. }
  205. // ExtractDomain 从 URL 中提取域名
  206. func ExtractDomain(urlString string) (string, error) {
  207. // 解析 URL
  208. u, err := url.Parse(urlString)
  209. if err != nil {
  210. return "", err
  211. }
  212. // 提取主机名
  213. host := u.Hostname()
  214. // 如果主机名包含端口号,去除端口号
  215. host = strings.Split(host, ":")[0]
  216. return host, nil
  217. }
  218. // 定义所有可能的时间格式
  219. var timeFormats = []string{
  220. "02/01/2006 15:04:05", "01-02-2006 15:04:05", "01/02/2006 15:04:05",
  221. "2006-01-02T15:04:05", "2006-01-02", "2006.01.02", "2006/01/02",
  222. "2006-01-02 15:04:05", "2006.01.02 15:04:05", "2006/01/02 15:04:05",
  223. "2006/1/02", "2006-1-02", "2006.1.02", "2006/1/2", "2006-1-2", "2006.1.2",
  224. "2006年01月02日", "2006年1月2日", "2006年1月02日", "2006年01月02", "2006年1月02", "2006年1月2",
  225. }
  226. // ExtractDates 从文本中提取所有符合给定时间格式的日期和时间。
  227. func ExtractDates(text string) (string, error) {
  228. // 构建正则表达式,匹配所有给定的时间格式
  229. datePattern := `(0[1-9]|[12][0-9]|3[01])[./-](0[1-9]|1[012])[./-](19|20)\d{2}` +
  230. `(?:\s+([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]))?` +
  231. `|` +
  232. `(19|20)\d{2}[./-](0[1-9]|1[012]|[1-9])[./-](0[1-9]|[12][0-9]|3[01]|[1-9])` +
  233. `(?:\s+([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]))?` +
  234. `|` +
  235. `(19|20)\d{2}[T](0[1-9]|1[012])[./-](0[1-9]|[12][0-9]|3[01])` +
  236. `(?:\s+([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]))?` +
  237. `|` +
  238. `(19|20)\d{2}[年](0[1-9]|1[012])[月](0[1-9]|[12][0-9]|3[01])[日]` +
  239. `|` +
  240. `(19|20)\d{2}[年](0[1-9]|1[0-9])[月](0[1-9]|[12][0-9]|3[01])[日]` +
  241. `|` +
  242. `(19|20)\d{2}[年](0[1-9]|1[0-9]|[0-9])[月](0[1-9]|[12][0-9]|3[01]|[0-9])[日]?`
  243. // 编译正则表达式
  244. re, err := regexp.Compile(datePattern)
  245. if err != nil {
  246. return "", err
  247. }
  248. // 找到所有匹配项
  249. matches := re.FindAllString(text, -1)
  250. if len(matches) == 0 {
  251. datePattern2 := `\b\d{1,2}[-./月]\d{1,2}\b`
  252. // 编译正则表达式
  253. re2, err := regexp.Compile(datePattern2)
  254. if err != nil {
  255. return "", err
  256. }
  257. // 找到所有匹配项
  258. matches2 := re2.FindAllString(text, -1)
  259. if len(matches2) > 0 {
  260. match := matches2[0]
  261. // 获取当前时间
  262. now := time.Now()
  263. currentYear := now.Year()
  264. completeDate := fmt.Sprintf("%d-%s", currentYear, match)
  265. return completeDate, nil
  266. }
  267. return "", nil
  268. }
  269. if len(matches) > 0 {
  270. return matches[0], nil
  271. }
  272. return "", nil
  273. }
  274. func RemoveNewlinesAndSpaces(text string) string {
  275. return strings.ReplaceAll(strings.ReplaceAll(text, "\n", ""), " ", "")
  276. }
  277. //判断是否是招标信息的标题
  278. func IsBidTitle(title string) bool {
  279. length := utf8.RuneCountInString(title)
  280. if length < 4 {
  281. return false
  282. }
  283. pattern := `(?i)(?:招标|需求|预公告|采购|合同|中标|磋商|预选人|废标|流标|非招标|审批|竞价|挂牌|出让|出租|成交|结果|交易|竣工|开工|批准|建设|工程|更正|公告|备案|澄清|租赁|资产|转让|行政许可|土地|矿产|国土|使用权|验收|环保|环境|验收|林权|核准|项目|金额|中标|招标|竞价|编号|招标人|中标人|招标时间|中标时间|项目名称|公告名称|项目代码|项目编号|代理机构|供应方式|采购单位|采购项目|预算金额|合同编号|合同名称|采购人|供应商|合同金额|服务时间|服务要求|采购方式|网上竞价|开始时间|截止时间|预算金额|竞价明细|工程名称|建设单位|施工单位|工程费用|挂牌出让|出让年限|土地用途|宗地编号|土地面积|公示期|出让人|采购编号|发布时间|公示期|宗地编号|资金来源|建设地址|建设内容|建设期限|项目位置|供地方式|成交价格|批准单位|开工时间|竣工时间|签订时间|交地时间|最高限价|采购需求|最高限价|挂牌编号|挂牌价格|挂牌期限|公告日期|成交价格|成交数量|工期要求|工程地点|承包方式|发包人|发包地点|发包面积|发包要求|发包|招标|投标|竞标|询价|采购|合同|工程|项目|建设|施工|设计|监理|检测|验收|维修|改造|装修|设备|材料|供应|服务|合作|承包|发包|招标公告|招标文件|投标文件|中标公示|评标结果|合同签订|工程验收|采购公告|招标通知|投标通知|招标项目|招标公示|招标公告书|中标结果|中标通知|成交结果|中标名单|中标文件|中标公告|中标通告|中标通知书|废标|流标|变更公告|补遗|废标公告|流标公告|补遗公告|评标公示|评标通知|中标候选人|转让|建设许可证|环境影响|拍卖|出让|产权|出租|批复|租赁|变更|终止|询比|竞谈|比价|开标|中标|成交|单一|项目结果|磋商|谈判|竞争|比选|邀标|评标|资格预审|议价|中选|答疑|竞价转让|竞价|服务项目中标|中标药品|标段中标|中标品种|建设项目中标|部分中标|工程项目中标|包中标|工程施工中标|招标中标|公开招标中标|服务中标|中标企业|租赁中标|建设工程中标|配套工程中标|监理中标|中标产品|审计中标|系统中标|施工中标|初步设计中标|咨询服务中标|预中标|设计中标|药品中标|招标代理|招标代理服务|电子化公开招标|招标书第|招标计划|招标投标|服务公开招标|物资公开招标|设备公开招标|招标答疑|服务项目公开招标|分包公开招标|药品公开招标|建设公开招标|云商采购部|周采购计划|采购计划任务|物资采购计划|复印纸采购计划|专业分包|劳务分包|购销合同|车辆保险合同|合同段|总承包合同|监理合同|工程施工合同|合同能源管理|服务合同|合同续签|服务项目合同|租赁合同|合同订立|加油合同|标段合同|合同备案|建设项目合同|候选人公示|竣工验收|竣工财务决算|竣工决算|竣工结算|建设项目竣工|竣工测量|交竣工|竣工日期|设施竣工|竣工环境保护|竣工测绘|验收报告编制|消防验收|水土保持验收|行政审批|审批决定|施工图设计|建设项目施工|改造工程施工|施工图审查|施工监理|建设工程施工|工程施工监理|治理工程施工|土建施工|工程项目施工|提升工程施工|整治工程施工|养护工程施工|道路工程施工|改造施工|机电工程施工|标段施工|安装施工|扩建工程施工|建设施工|改扩建工程施工|装修工程施工|土建工程施工|配套工程施工|修复工程施工|二期工程施工|新建工程施工|一期工程施工|安装工程施工|维修工程施工|维修施工|迁改工程施工|零星工程施工|附属工程施工|改建工程施工|施工劳务|施工分包|段施工|大修工程施工|管网工程施工|修缮工程施工|段工程施工|道路施工|排水工程施工|装修施工|绿化工程施工|施工服务项目|精装修工程施工|大修施工|施工标|大中修工程施工|劳务施工|电气施工|施工图预算|综合治理工程施工|工程施工单位|施工过程|管道工程施工|重建工程施工|工程施工标|公路工程施工|标施工|绿化施工|施工阶段|施工标段|防护工程施工|工程施工第|恢复工程施工|施工一体化|主体施工|配电工程施工|工程设计施工|施工澄清|勘察设计|勘测设计|设计服务项目|建设项目初步设计|初步设计概算|建设项目设计|提升工程设计|城市设计|建设工程设计|改造工程设计|改造设计|治理工程设计|广告设计制作|规划设计研究院|加固设计|二期工程设计|工程项目设计|道路工程设计|设计搭建|改扩建工程设计|规划设计方案|系统设计|勘测设计院|设计审查|修复工程设计|装修设计|设计研究院|规划设计院|迁改工程设计|勘查设计|配套工程设计|软装设计|精装修设计|图纸设计|整治工程设计|建设项目方案设计|乡村规划设计|建筑设计方案|建设设计|招标|投标|竞标|询价|采购|合同|工程|项目|建设|施工|设计|监理|检测|验收|维修|改造|装修|设备|材料|供应|服务|合作|承包|发包|招标公告|招标文件|投标文件|中标公示|评标结果|合同签订|工程验收|采购公告|招标通知|投标通知|招标项目|招标公示|招标公告书|中标结果|中标通知|成交结果|中标名单|中标文件|中标公告|中标通告|中标通知书|废标|流标|变更公告|补遗|废标公告|流标公告|补遗公告|评标公示|评标通知|中标候选人)`
  284. matched, _ := regexp.MatchString(pattern, title)
  285. if matched {
  286. return true
  287. }
  288. return false
  289. }