main.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. package main
  2. import (
  3. "encoding/csv"
  4. "flag"
  5. "fmt"
  6. "os"
  7. "strconv"
  8. "strings"
  9. "sync"
  10. "time"
  11. "main/httplib"
  12. "gitee.com/go-package/carbon"
  13. "github.com/cheggaaa/pb/v3"
  14. )
  15. var RecordBaseUrl = "https://master.weimob.com/api3/ec/mbp/userrecord/pageSession"
  16. var RecordInfoUrl = "https://master.weimob.com/api3/ec/mbp/userrecord/getRecordBySession"
  17. var api = "https://dopen.weimob.com/api/2_0/ec/membership/customerRollRecord"
  18. type RecordBaseResp struct {
  19. Errcode string `json:"errcode"`
  20. Errmsg interface{} `json:"errmsg"`
  21. Data struct {
  22. TotalCount int `json:"totalCount"`
  23. PageSize int `json:"pageSize"`
  24. PageNum int `json:"pageNum"`
  25. PageList []RecordBase `json:"pageList"`
  26. } `json:"data"`
  27. GlobalTicket string `json:"globalTicket"`
  28. MonitorTrackID string `json:"monitorTrackId"`
  29. }
  30. type RecordBase struct {
  31. StartTime int64 `json:"startTime"`
  32. EndTime int64 `json:"endTime"`
  33. Pid int64 `json:"pid"`
  34. CustomerWid int64 `json:"customerWid"`
  35. StoreID int64 `json:"storeId"`
  36. KeepingTime int64 `json:"keepingTime"`
  37. Sessionid string `json:"sessionid"`
  38. StoreName string `json:"storeName"`
  39. StatType string `json:"statType"`
  40. StatTypeName string `json:"statTypeName"`
  41. InPageName string `json:"inPageName"`
  42. OutPageName string `json:"outPageName"`
  43. SharedGuide string `json:"sharedGuide"`
  44. SharedTuike string `json:"sharedTuike"`
  45. InType string `json:"inType"`
  46. KeepingTimeStr string `json:"keepingTimeStr"`
  47. }
  48. type RecordInfo struct {
  49. Pid int64 `json:"pid"`
  50. Timestamp int64 `json:"timestamp"`
  51. CustomerWid int64 `json:"customerWid"`
  52. StoreID int64 `json:"storeId"`
  53. BizType int64 `json:"bizType"`
  54. BizValue int64 `json:"bizValue"`
  55. Sessionid string `json:"sessionid"`
  56. PageName string `json:"pageName"`
  57. Content string `json:"content"`
  58. TemplateKey string `json:"templateKey"`
  59. }
  60. type RecordInfoResp struct {
  61. Errcode string `json:"errcode"`
  62. Errmsg string `json:"errmsg"`
  63. Data struct {
  64. TotalCount int64 `json:"totalCount"`
  65. Records []RecordInfo `json:"records"`
  66. } `json:"data"`
  67. GlobalTicket string `json:"globalTicket"`
  68. MonitorTrackID string `json:"monitorTrackId"`
  69. }
  70. //postData = {"pid": "100001752327","storeId": "2630133327","pageNum": 2,"pageSize": 10,"customerWid": "2636610151"}
  71. type RecordBasePostData struct {
  72. Pid int64 `json:"pid"`
  73. StoreId int64 `json:"storeId"`
  74. CustomerWid int64 `json:"customerWid"`
  75. PageNum int64 `json:"pageNum"`
  76. PageSize int64 `json:"pageSize"`
  77. Vip Vip `json:"-"`
  78. }
  79. //postData = {"pid": "100001752327","storeId": "2630133327","pageNum": 2,"pageSize": 10,"customerWid": "2636610151"}
  80. type RecordInfoPostData struct {
  81. Pid int64 `json:"pid"`
  82. StoreId int64 `json:"storeId"`
  83. CustomerWid int64 `json:"customerWid"`
  84. PageNum int64 `json:"pageNum"`
  85. PageSize int64 `json:"pageSize"`
  86. SessionId string `json:"sessionId"`
  87. }
  88. type WriteCsv struct {
  89. file *csv.Writer
  90. mu sync.Mutex
  91. }
  92. var (
  93. brand string
  94. worker int64
  95. start int64
  96. token string
  97. allPids = map[string]int64{"ugg": 4019873615680, "ecco": 100001752327, "hdugg": 4019876273702}
  98. )
  99. func NewCsv(name string) (*WriteCsv, error) {
  100. _, err := os.Stat(name)
  101. if err == nil {
  102. os.Remove(name)
  103. }
  104. f, err := os.Create(name)
  105. if err != nil {
  106. return nil, err
  107. }
  108. f.WriteString("\xEF\xBB\xBF")
  109. return &WriteCsv{file: csv.NewWriter(f), mu: sync.Mutex{}}, nil
  110. }
  111. func (w *WriteCsv) Write(data []string) {
  112. w.mu.Lock()
  113. defer w.mu.Unlock()
  114. w.file.Write(data)
  115. w.file.Flush()
  116. }
  117. func main() {
  118. flag.StringVar(&brand, "b", "", "品牌 例如 : ugg ecco")
  119. flag.StringVar(&token, "t", "", "品牌 例如 : ugg ecco")
  120. flag.Int64Var(&worker, "w", 1, "工作线程数 : 默认 1")
  121. flag.Int64Var(&start, "n", 0, "用户起始id(WID)")
  122. flag.Parse()
  123. if len(brand) == 0 {
  124. fmt.Println("需要 品牌 Like -b ugg")
  125. return
  126. }
  127. if len(token) == 0 {
  128. fmt.Println("需要 token ")
  129. return
  130. }
  131. pid, ok := allPids[brand]
  132. if !ok {
  133. fmt.Println("不存在该品牌的 PID 程序终止")
  134. return
  135. }
  136. regMysql(brand)
  137. regOrcle(brand)
  138. wids, err := GetAllWid()
  139. if err != nil {
  140. fmt.Println(err)
  141. return
  142. }
  143. if len(wids) == 0 {
  144. fmt.Println("No Data Found")
  145. return
  146. }
  147. bar := pb.StartNew(len(wids))
  148. csvW, _ := NewCsv(brand + ".csv")
  149. csvW.Write([]string{
  150. "Wid",
  151. "姓名",
  152. "手机",
  153. "开始时间",
  154. "结束时间",
  155. "开始时间-年",
  156. "开始时间-月",
  157. "开始时间-日",
  158. "开始时间-时",
  159. "开始时间-分",
  160. "结束时间-年",
  161. "结束时间-月",
  162. "结束时间-日",
  163. "结束时间-时",
  164. "结束时间-分",
  165. "渠道",
  166. "进入页面",
  167. "退出页",
  168. "时长",
  169. "分享导购",
  170. "分享微客",
  171. "进入方式",
  172. })
  173. dataChan := make(chan RecordBasePostData, worker)
  174. if worker > 0 {
  175. for i := 0; i < int(worker); i++ {
  176. go RunWorker(dataChan, csvW, token)
  177. }
  178. } else {
  179. go RunWorker(dataChan, csvW, token)
  180. }
  181. for _, v := range wids {
  182. if len(v.Phone) == 0 {
  183. continue
  184. }
  185. pd := RecordBasePostData{}
  186. pd.Vip = v
  187. pd.CustomerWid = v.Wid
  188. pd.PageNum = 1
  189. pd.PageSize = 100
  190. pd.Pid = pid
  191. dataChan <- pd
  192. // fmt.Println(index, v.Wid, "ToDo")
  193. bar.Increment()
  194. // var wt = []string{strconv.Itoa(int(v.Wid)), v.Name, v.Phone, strconv.Itoa(len(rs.Data.PageList))}
  195. }
  196. bar.Finish()
  197. time.Sleep(10000 * time.Second)
  198. }
  199. func RunWorker(dataChan chan RecordBasePostData, wt *WriteCsv, token string) {
  200. //[Wid,姓名,手机,开始时间,结束时间,渠道,进入页面,退出页,时长,分享导购,分享微客,进入方式]
  201. for {
  202. select {
  203. case d := <-dataChan:
  204. rs, err := QueryRecordBaseOneWid(d, token)
  205. if err != nil {
  206. return
  207. }
  208. if rs.Data.TotalCount == 0 {
  209. wt.Write([]string{
  210. strconv.Itoa(int(d.Vip.Wid)),
  211. d.Vip.Name,
  212. d.Vip.Phone,
  213. "无",
  214. "无",
  215. "无",
  216. "无",
  217. "无",
  218. "无",
  219. "无",
  220. "无",
  221. "无",
  222. "无",
  223. "无",
  224. "无",
  225. "无",
  226. "无",
  227. "无",
  228. "无",
  229. "无",
  230. "无",
  231. "无",
  232. })
  233. } else {
  234. for _, v := range rs.Data.PageList {
  235. svs := carbon.CreateFromTimestamp(v.StartTime).Time.Format("2006-01-02-15-04")
  236. evs := carbon.CreateFromTimestamp(v.EndTime).Time.Format("2006-01-02-15-04")
  237. sv := strings.Split(svs, "-")
  238. ev := strings.Split(evs, "-")
  239. if v.InType == "" {
  240. v.InType = "无"
  241. }
  242. wt.Write([]string{
  243. strconv.Itoa(int(d.Vip.Wid)),
  244. d.Vip.Name,
  245. d.Vip.Phone,
  246. svs,
  247. evs,
  248. sv[0],
  249. sv[1],
  250. sv[2],
  251. sv[3],
  252. sv[4],
  253. ev[0],
  254. ev[1],
  255. ev[2],
  256. ev[3],
  257. ev[4],
  258. v.StatTypeName,
  259. v.InPageName,
  260. v.OutPageName,
  261. v.KeepingTimeStr,
  262. v.SharedGuide,
  263. v.SharedTuike,
  264. v.InType,
  265. })
  266. }
  267. }
  268. default:
  269. }
  270. }
  271. }
  272. // "cb446455d8855e88594e53588043fedfef282fed20ab59ff985888ad04b2a1c4"
  273. func QueryRecordBaseOneWid(post RecordBasePostData, token string) (*RecordBaseResp, error) {
  274. req := GetRequests(RecordBaseUrl, token)
  275. req, _ = req.JSONBody(&post)
  276. var result RecordBaseResp
  277. err := req.ToJSON(&result)
  278. if err != nil {
  279. return nil, err
  280. }
  281. return &result, nil
  282. }
  283. func QueryRecordInfoOneWid(post RecordInfoPostData, token string) (*RecordInfoResp, error) {
  284. req := GetRequests(RecordInfoUrl, token)
  285. req, _ = req.JSONBody(&post)
  286. var result RecordInfoResp
  287. err := req.ToJSON(&result)
  288. if err != nil {
  289. return nil, err
  290. }
  291. return &result, nil
  292. }
  293. func GetRequests(url string, token string) *httplib.HTTPRequest {
  294. req := httplib.Post(url)
  295. req.Header("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 QIHU 360SE")
  296. req.Header("authorization", fmt.Sprintf("bearer %s", token))
  297. return req
  298. }
  299. // func main() {
  300. // count := 100000
  301. // // create and start new bar
  302. // bar := pb.StartNew(count)
  303. // // start bar from 'default' template
  304. // // bar := pb.Default.Start(count)
  305. // // start bar from 'simple' template
  306. // // bar := pb.Simple.Start(count)
  307. // // start bar from 'full' template
  308. // // bar := pb.Full.Start(count)
  309. // for i := 0; i < count; i++ {
  310. // bar.Increment()
  311. // time.Sleep(time.Millisecond)
  312. // }
  313. // // finish bar
  314. // bar.Finish()
  315. // }