resourceChannel.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. package resourceChannel
  2. import (
  3. "encoding/json"
  4. "github.com/bilibili/gengine/builder"
  5. gengineContext "github.com/bilibili/gengine/context"
  6. "github.com/bilibili/gengine/engine"
  7. "github.com/go-redis/redis"
  8. "golang.org/x/net/context"
  9. "strconv"
  10. "strings"
  11. "time"
  12. )
  13. func redisCli() *redis.Client {
  14. client := redis.NewClient(&redis.Options{
  15. Addr: "192.168.204.180:3377", // Redis地址
  16. Password: "", // Redis密码,默认为空
  17. DB: 1, // 使用哪个数据库,默认为0
  18. })
  19. _, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
  20. defer cancel()
  21. return client
  22. }
  23. type ResourceAssessment struct {
  24. ID uint `gorm:"primaryKey" json:"id"` // 留学评估表
  25. DataType uint8 `json:"data_type"` // 1.网课 2.api资源 3.专题页 4.工作台录入 5.后台录入 6 小程序
  26. ChatID string `json:"chat_id"` // 会话id
  27. Channel int `json:"channel"` // 渠道id
  28. Category int `json:"category"` // 分类id
  29. CreatedAt time.Time `json:"created_at"` // 数据创建时间
  30. ReferPageURL string `json:"refer_page_url"` // 来源网址
  31. URL string `json:"url"` // 落地页地址
  32. ChatURL string `json:"chat_url"` // 对话发起页
  33. GrUserId string `json:"gr_user_id"` // 神策distinct_id
  34. }
  35. type SemJsChatRecord struct {
  36. ChatID int64 `gorm:"column:CHAT_ID"`
  37. CreateTime time.Time `gorm:"column:CREATE_TIME"`
  38. ReferPage string `gorm:"type:text;column:REFER_PAGE"`
  39. ChatURL string `gorm:"type:text;column:CHAT_URL"`
  40. ChannleID int `gorm:"column:CHANNLE_ID"`
  41. CategoryID int `gorm:"column:CATEGORY_ID"`
  42. GrUserID string `gorm:"column:gr_user_id"`
  43. }
  44. type ChannelCategory struct {
  45. Channel int
  46. Category int
  47. }
  48. // AssessmentAnalysisRule 表单解析
  49. func (a ResourceAssessment) AssessmentAnalysisRule(assessment *ResourceAssessment) {
  50. // 获取神策URL(不包含utm)
  51. cc, _ := redisCli().Get("website:" + assessment.GrUserId).Result()
  52. var websiteUrl SensorsData
  53. json.Unmarshal([]byte(cc), &websiteUrl)
  54. // 获取神策url(包含utm)
  55. cc1, _ := redisCli().Get("sensors:" + assessment.GrUserId).Result()
  56. var utmUrl SensorsData
  57. json.Unmarshal([]byte(cc1), &utmUrl)
  58. // 到梦解析
  59. if !strings.Contains(assessment.URL, "utm") && !strings.Contains(assessment.ChatURL, "utm") && !strings.Contains(assessment.ReferPageURL, "utm") && (strings.Contains(assessment.ReferPageURL, "daomeng") || strings.Contains(assessment.ChatURL, "daomeng")) {
  60. println("解析到梦")
  61. assessment.Channel = 38
  62. assessment.Category = 201
  63. return
  64. }
  65. // 网课解析
  66. if assessment.DataType == 1 {
  67. println("解析网课")
  68. assessment.Channel = 26
  69. assessment.Category = 121
  70. return
  71. }
  72. // 小程序解析
  73. if strings.Contains(assessment.ChatURL, "pages") && strings.Split(strings.Split(assessment.ChatURL, "?")[1], "=")[0] == "miniapp" {
  74. println("解析小程序")
  75. appType := strings.Split(strings.Split(strings.Split(assessment.ChatURL, "?")[1], "=")[1], "_")[1]
  76. if appType == "baidu" {
  77. assessment.Channel = 1
  78. assessment.Category = 30
  79. } else if appType == "wechat" {
  80. assessment.Channel = 8
  81. assessment.Category = 32
  82. }
  83. return
  84. }
  85. // URL解析
  86. if strings.Contains(assessment.URL, "link") || strings.Contains(assessment.ReferPageURL, "link") || strings.Contains(assessment.ChatURL, "link") {
  87. println("解析URL")
  88. if strings.Contains(assessment.URL, "link") {
  89. assessment.Channel, _ = strconv.Atoi(strings.Split(strings.Split(strings.Split(assessment.URL, "link")[1], "form")[0], "_")[1])
  90. assessment.Category, _ = strconv.Atoi(strings.Split(strings.Split(strings.Split(assessment.URL, "link")[1], "form")[0], "_")[2])
  91. } else if strings.Contains(assessment.ReferPageURL, "link") {
  92. assessment.Channel, _ = strconv.Atoi(strings.Split(strings.Split(strings.Split(assessment.ReferPageURL, "link")[1], "form")[0], "_")[1])
  93. assessment.Category, _ = strconv.Atoi(strings.Split(strings.Split(strings.Split(assessment.ReferPageURL, "link")[1], "form")[0], "_")[2])
  94. } else {
  95. assessment.Channel, _ = strconv.Atoi(strings.Split(strings.Split(strings.Split(assessment.ChatURL, "link")[1], "form")[0], "_")[1])
  96. assessment.Category, _ = strconv.Atoi(strings.Split(strings.Split(strings.Split(assessment.ChatURL, "link")[1], "form")[0], "_")[2])
  97. }
  98. return
  99. }
  100. // 神策解析
  101. if utmUrl.Url != "" && !strings.Contains(assessment.URL, "link") && !strings.Contains(assessment.ReferPageURL, "link") && !strings.Contains(assessment.ChatURL, "link") {
  102. println("解析神策")
  103. assessment.Channel = utmUrl.Channel
  104. assessment.Category = utmUrl.Category
  105. return
  106. }
  107. // 搜索引擎SEO,外链解析
  108. if assessment.ReferPageURL != "" && !strings.Contains(assessment.ReferPageURL, "https://www.jjl.cn/") && !strings.Contains(assessment.ReferPageURL, "https://m.jjl.cn/") {
  109. println("解析SEO")
  110. assessment.Channel = 5
  111. assessment.Category = 11
  112. return
  113. }
  114. // 官网自然访问解析
  115. if strings.Contains(assessment.URL, "https://www.jjl.cn/") || strings.Contains(assessment.URL, "https://m.jjl.cn/") ||
  116. strings.Contains(assessment.ReferPageURL, "https://www.jjl.cn/") || strings.Contains(assessment.ReferPageURL, "https://m.jjl.cn/") ||
  117. strings.Contains(assessment.ChatURL, "https://www.jjl.cn/") || strings.Contains(assessment.ChatURL, "https://m.jjl.cn/") ||
  118. strings.Contains(utmUrl.Url, "https://www.jjl.cn/") || strings.Contains(utmUrl.Url, "https://m.jjl.cn/") {
  119. println("解析官网")
  120. assessment.Channel = 7
  121. assessment.Category = 126
  122. return
  123. }
  124. println("默认解析为SEO")
  125. assessment.Channel = 5
  126. assessment.Category = 11
  127. }
  128. // ChatAnalysisRule 表单解析规则
  129. func (c SemJsChatRecord) ChatAnalysisRule(chat *SemJsChatRecord) {
  130. // 获取神策URL(不包含utm)
  131. cc, _ := redisCli().Get("website:" + chat.GrUserID).Result()
  132. var websiteUrl SensorsData
  133. json.Unmarshal([]byte(cc), &websiteUrl)
  134. // 获取神策url(包含utm)
  135. cc1, _ := redisCli().Get("sensors:" + chat.GrUserID).Result()
  136. var utmUrl SensorsData
  137. json.Unmarshal([]byte(cc1), &utmUrl)
  138. // 小程序解析
  139. if strings.Contains(chat.ChatURL, "pages") && strings.Split(strings.Split(chat.ChatURL, "?")[1], "=")[0] == "miniapp" {
  140. println("小程序解析")
  141. appType := strings.Split(strings.Split(strings.Split(chat.ChatURL, "?")[1], "=")[1], "_")[1]
  142. if appType == "baidu" {
  143. chat.ChannleID = 1
  144. chat.CategoryID = 30
  145. } else if appType == "wechat" {
  146. chat.ChannleID = 8
  147. chat.CategoryID = 32
  148. }
  149. return
  150. }
  151. // 到梦解析
  152. if !strings.Contains(chat.ReferPage, "utm") && !strings.Contains(chat.ChatURL, "utm") && (strings.Contains(chat.ReferPage, "daomeng") || strings.Contains(chat.ChatURL, "daomeng")) {
  153. println("到梦解析")
  154. chat.ChannleID = 38
  155. chat.CategoryID = 201
  156. return
  157. }
  158. // URL解析
  159. if strings.Contains(chat.ChatURL, "link") || strings.Contains(chat.ReferPage, "link") {
  160. println("解析URL")
  161. if strings.Contains(chat.ChatURL, "link") {
  162. chat.ChannleID, _ = strconv.Atoi(strings.Split(strings.Split(strings.Split(chat.ChatURL, "link")[1], "form")[0], "_")[1])
  163. chat.CategoryID, _ = strconv.Atoi(strings.Split(strings.Split(strings.Split(chat.ChatURL, "link")[1], "form")[0], "_")[2])
  164. } else {
  165. chat.ChannleID, _ = strconv.Atoi(strings.Split(strings.Split(strings.Split(chat.ReferPage, "link")[1], "form")[0], "_")[1])
  166. chat.ChannleID, _ = strconv.Atoi(strings.Split(strings.Split(strings.Split(chat.ReferPage, "link")[1], "form")[0], "_")[2])
  167. }
  168. return
  169. }
  170. // 神策解析
  171. if utmUrl.Url != "" && !strings.Contains(chat.ReferPage, "link") && !strings.Contains(chat.ChatURL, "link") {
  172. println("解析神策")
  173. chat.ChannleID = utmUrl.Channel
  174. chat.CategoryID = utmUrl.Category
  175. return
  176. }
  177. // 搜索引擎SEO,外链解析
  178. if chat.ReferPage != "" && !strings.Contains(chat.ReferPage, "https://www.jjl.cn/") && !strings.Contains(chat.ReferPage, "https://m.jjl.cn/") {
  179. println("解析SEO")
  180. chat.ChannleID = 5
  181. chat.CategoryID = 11
  182. return
  183. }
  184. // 官网自然访问解析
  185. if strings.Contains(chat.ReferPage, "https://www.jjl.cn/") || strings.Contains(chat.ReferPage, "https://m.jjl.cn/") ||
  186. strings.Contains(chat.ChatURL, "https://www.jjl.cn/") || strings.Contains(chat.ChatURL, "https://m.jjl.cn/") ||
  187. strings.Contains(utmUrl.Url, "https://www.jjl.cn/") || strings.Contains(utmUrl.Url, "https://m.jjl.cn/") {
  188. println("解析官网")
  189. chat.ChannleID = 7
  190. chat.CategoryID = 126
  191. return
  192. }
  193. println("默认解析为SEO")
  194. chat.ChannleID = 5
  195. chat.CategoryID = 11
  196. }
  197. const AssessmentAnalysisRule = `
  198. rule "AssessmentAnalysisRule" "表单解析" salience 1
  199. begin
  200. assessment.AssessmentAnalysisRule(assessment)
  201. end`
  202. const ChatAnalysisRule = `
  203. rule "ChatAnalysisRule" "会话解析" salience 1
  204. begin
  205. chat.ChatAnalysisRule(chat)
  206. end`
  207. // GetChannel 表单渠道归因处理
  208. func GetChannel(assessment ResourceAssessment) ChannelCategory {
  209. dataContext := gengineContext.NewDataContext()
  210. dataContext.Add("assessment", &assessment)
  211. ruleBuilder := builder.NewRuleBuilder(dataContext)
  212. ruleBuilder.BuildRuleFromString(AssessmentAnalysisRule)
  213. engine := engine.NewGengine()
  214. engine.Execute(ruleBuilder, true)
  215. return ChannelCategory{assessment.Channel, assessment.Category}
  216. }
  217. // GetChatChannel 会话渠道归因处理
  218. func GetChatChannel(chat SemJsChatRecord) ChannelCategory {
  219. dataContext := gengineContext.NewDataContext()
  220. dataContext.Add("chat", &chat)
  221. ruleBuilder := builder.NewRuleBuilder(dataContext)
  222. ruleBuilder.BuildRuleFromString(ChatAnalysisRule)
  223. engine := engine.NewGengine()
  224. engine.Execute(ruleBuilder, true)
  225. return ChannelCategory{chat.ChannleID, chat.CategoryID}
  226. }
  227. type SensorsData struct {
  228. DistinctId string `json:"distinctID"`
  229. Channel int `json:"channel"`
  230. Category int `json:"category"`
  231. Url string `json:"url"`
  232. }
  233. //func main() {
  234. // //var assessment []ResourceAssessment
  235. // //lib.GetDbInstance().Where("DATE(created_at) >= '2023-05-23' and id = 382346").Find(&assessment)
  236. // //for _, value := range assessment {
  237. // // cc := GetChannel(value)
  238. // // println(cc.Channel)
  239. // // println(cc.Category)
  240. // // println("END")
  241. // //}
  242. //
  243. // var chat []SemJsChatRecord
  244. // lib.GetDbInstance().Where("DATE(CREATE_TIME) >= '2023-01-01'").Find(&chat)
  245. // for _, value := range chat {
  246. // println(value.ChatID)
  247. // cc := GetChatChannel(value)
  248. // println(cc.Channel, cc.Category)
  249. // }
  250. //}