smm_shanghai.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. package services
  2. import (
  3. "context"
  4. "encoding/json"
  5. "errors"
  6. "eta/eta_crawler/models"
  7. "eta/eta_crawler/services/sci99"
  8. "eta/eta_crawler/utils"
  9. "fmt"
  10. "io"
  11. "net/http"
  12. "strconv"
  13. "strings"
  14. "time"
  15. "github.com/beego/beego/v2/task"
  16. "github.com/xuri/excelize/v2"
  17. )
  18. type SmmRequest struct {
  19. Name string
  20. IndexCode string
  21. Url string
  22. Frequency string
  23. Unit string
  24. Value string
  25. }
  26. var nickelReqs = []SmmRequest{
  27. // {
  28. // Name: "SMM 1#电解镍",
  29. // IndexCode: "",
  30. // Url: "https://hq.smm.cn/ajax/spot/history/201102250239",
  31. // Frequency: "日度",
  32. // Unit: "元/吨",
  33. // },
  34. {
  35. Name: "1#金川镍",
  36. Url: "https://hq.smm.cn/ajax/spot/history/201102250174",
  37. Frequency: "日度",
  38. Unit: "元/吨",
  39. },
  40. {
  41. Name: "1#进口镍",
  42. Url: "https://hq.smm.cn/ajax/spot/history/201102250423",
  43. Frequency: "日度",
  44. Unit: "元/吨",
  45. },
  46. {
  47. Name: "镍豆",
  48. Url: "https://hq.smm.cn/ajax/spot/history/202008270001",
  49. Frequency: "日度",
  50. Unit: "元/吨",
  51. },
  52. // {
  53. // Name: `印尼内贸红土镍矿1.2%(到厂价)`,
  54. // Url: "https://hq.smm.cn/ajax/spot/history/202311230010",
  55. // Frequency: "周度",
  56. // Unit: "美元/湿吨",
  57. // },
  58. // {
  59. // Name: `印尼内贸红土镍矿1.6%(到厂价)`,
  60. // Url: "https://hq.smm.cn/ajax/spot/history/202311230011",
  61. // Frequency: "周度",
  62. // Unit: "美元/湿吨",
  63. // },
  64. {
  65. Name: `菲律宾红土镍矿0.9%,Al≥7%(CIF)`,
  66. Url: "https://hq.smm.cn/ajax/spot/history/201608170001",
  67. Frequency: "日度",
  68. Unit: "美元/湿吨",
  69. },
  70. // {
  71. // Name: `菲律宾红土镍矿0.9%,Al<7%(CIF) `, // 重名
  72. // Url: "https://hq.smm.cn/ajax/spot/history/202109140006",
  73. // Frequency: "日度",
  74. // Unit: "美元/湿吨",
  75. // },
  76. // {
  77. // Name: `菲律宾红土镍矿1.3%(CIF)`,
  78. // Url: "https://hq.smm.cn/ajax/spot/history/202109140001",
  79. // Frequency: "日度",
  80. // Unit: "美元/湿吨",
  81. // },
  82. // {
  83. // Name: `菲律宾红土镍矿1.4%(CIF)`,
  84. // Url: "https://hq.smm.cn/ajax/spot/history/202109140003",
  85. // Frequency: "日度",
  86. // Unit: "美元/湿吨",
  87. // },
  88. {
  89. Name: `菲律宾红土镍矿1.5%(CIF)`,
  90. Url: "https://hq.smm.cn/ajax/spot/history/201608170002",
  91. Frequency: "日度",
  92. Unit: "美元/湿吨",
  93. },
  94. {
  95. Name: `红土镍矿1.8%(CIF)`,
  96. Url: "https://hq.smm.cn/ajax/spot/history/201608170003",
  97. Frequency: "日度",
  98. Unit: "美元/湿吨",
  99. },
  100. {
  101. Name: `菲律宾红土镍矿0.9%,Al≥7%(FOB)`,
  102. Url: "https://hq.smm.cn/ajax/spot/history/201509220001",
  103. Frequency: "日度",
  104. Unit: "美元/湿吨",
  105. },
  106. // {
  107. // Name: `菲律宾红土镍矿0.9%,Al<7%(FOB)`, //重名
  108. // Url: "https://hq.smm.cn/ajax/spot/history/202109140005",
  109. // Frequency: "日度",
  110. // Unit: "美元/湿吨",
  111. // },
  112. // {
  113. // Name: `菲律宾红土镍矿1.3%(FOB)`,
  114. // Url: "https://hq.smm.cn/ajax/spot/history/202109140002",
  115. // Frequency: "日度",
  116. // Unit: "美元/湿吨",
  117. // },
  118. // {
  119. // Name: `菲律宾红土镍矿1.4%(FOB)`,
  120. // Url: "https://hq.smm.cn/ajax/spot/history/202109140004",
  121. // Frequency: "日度",
  122. // Unit: "美元/湿吨",
  123. // },
  124. {
  125. Name: `菲律宾红土镍矿1.5%(FOB)`,
  126. Url: "https://hq.smm.cn/ajax/spot/history/201509220002",
  127. Frequency: "日度",
  128. Unit: "美元/湿吨",
  129. },
  130. {
  131. Name: `红土镍矿1.8%(FOB)`,
  132. Url: "https://hq.smm.cn/ajax/spot/history/201509220003",
  133. Frequency: "日度",
  134. Unit: "美元/湿吨",
  135. },
  136. {
  137. Name: `8-12%高镍生铁(出厂价)`,
  138. Url: "https://hq.smm.cn/ajax/spot/history/201106150005",
  139. Frequency: "日度",
  140. Unit: "元/镍点",
  141. },
  142. {
  143. Name: `1.5-1.7%镍生铁(出厂价)`,
  144. Url: "https://hq.smm.cn/ajax/spot/history/201106150007",
  145. Frequency: "日度",
  146. Unit: "元/吨",
  147. },
  148. }
  149. var copperReqs = []SmmRequest{
  150. {
  151. Name: "SMM 1#电解铜",
  152. Url: "https://hq.smm.cn/ajax/spot/history/201102250376",
  153. Unit: "元/吨",
  154. Frequency: "日度",
  155. },
  156. {
  157. Name: "SMM 1#电解铜升贴水最大值",
  158. Url: "https://hq.smm.cn/ajax/premium/history/201102250185",
  159. Value: "highs",
  160. Frequency: "日度",
  161. },
  162. {
  163. Name: "SMM 1#电解铜升贴水最小值",
  164. Url: "https://hq.smm.cn/ajax/premium/history/201102250185",
  165. Value: "low",
  166. Frequency: "日度",
  167. },
  168. // {
  169. // Name: "SMM 广东1#电解铜",
  170. // Url: "https://hq.smm.cn/ajax/spot/history/201912300001",
  171. // Unit: "元/吨",
  172. // Frequency: "日度",
  173. // },
  174. {
  175. Name: "SMM 广东1#电解铜升贴水最大值",
  176. Url: "https://hq.smm.cn/ajax/premium/history/201912300002",
  177. Value: "highs",
  178. Frequency: "日度",
  179. },
  180. {
  181. Name: "SMM 广东1#电解铜升贴水最小值",
  182. Url: "https://hq.smm.cn/ajax/premium/history/201912300002",
  183. Value: "low",
  184. Frequency: "日度",
  185. },
  186. {
  187. Name: "进口铜精矿指数(周)",
  188. Url: "https://hq.smm.cn/ajax/spot/history/201910240001",
  189. Unit: "美元/吨",
  190. Frequency: "周度",
  191. },
  192. {
  193. Name: "废铜:广东:1#光亮铜线",
  194. Url: "https://hq.smm.cn/ajax/spot/history/201108090036",
  195. Unit: "元/吨",
  196. Frequency: "日度",
  197. },
  198. {
  199. Name: "电力行业用杆加工费(华东)-平均价",
  200. Url: "https://hq.smm.cn/ajax/spot/history/201811010001",
  201. Unit: "元/吨",
  202. Frequency: "日度",
  203. },
  204. {
  205. Name: "电力行业用杆加工费(华南)-平均价",
  206. Url: "https://hq.smm.cn/ajax/spot/history/202004080001",
  207. Unit: "元/吨",
  208. Frequency: "日度",
  209. },
  210. }
  211. var zincReqs = []SmmRequest{
  212. {
  213. Name: "SMM 0#锌锭",
  214. Url: "https://hq.smm.cn/ajax/spot/history/201102250173",
  215. Unit: "元/吨",
  216. Frequency: "日度",
  217. },
  218. {
  219. Name: "SMM 1#锌锭",
  220. Url: "https://hq.smm.cn/ajax/spot/history/201102250418",
  221. Unit: "元/吨",
  222. Frequency: "日度",
  223. },
  224. // {
  225. // Name: "SMM 0#锌锭溢价(广东)",
  226. // Url: "https://hq.smm.cn/ajax/spot/history/202010210003",
  227. // Unit: "元/吨",
  228. // Frequency: "日度",
  229. // },
  230. {
  231. Name: "SMM 0#锌锭(广东)",
  232. Url: "https://hq.smm.cn/ajax/spot/history/201102250231",
  233. Unit: "元/吨",
  234. Frequency: "日度",
  235. },
  236. // {
  237. // Name: "SMM 1#锌锭溢价(广东)",
  238. // Url: "https://hq.smm.cn/ajax/spot/history/202010210004",
  239. // Unit: "元/吨",
  240. // Frequency: "日度",
  241. // },
  242. {
  243. Name: "SMM 1#锌锭(广东)",
  244. Url: "https://hq.smm.cn/ajax/spot/history/201102250069",
  245. Unit: "元/吨",
  246. Frequency: "日度",
  247. },
  248. // {
  249. // Name: "SMM 0#锌锭溢价(天津)",
  250. // Url: "https://hq.smm.cn/ajax/spot/history/202010210001",
  251. // Unit: "元/吨",
  252. // Frequency: "日度",
  253. // },
  254. {
  255. Name: "SMM 1#锌锭(天津)",
  256. Url: "https://hq.smm.cn/ajax/spot/history/201102250556",
  257. Unit: "元/吨",
  258. Frequency: "日度",
  259. },
  260. {
  261. Name: "SMM 0#锌锭(天津)",
  262. Url: "https://hq.smm.cn/ajax/spot/history/201102250399",
  263. Unit: "元/吨",
  264. Frequency: "日度",
  265. },
  266. // {
  267. // Name: "SMM 1#锌锭溢价(天津)",
  268. // Url: "https://hq.smm.cn/ajax/spot/history/202010210002",
  269. // Unit: "元/吨",
  270. // Frequency: "日度",
  271. // },
  272. // {
  273. // Name: "SMM 0#锌锭溢价(宁波)",
  274. // Url: "https://hq.smm.cn/ajax/spot/history/202010210005",
  275. // Unit: "元/吨",
  276. // Frequency: "日度",
  277. // },
  278. // {
  279. // Name: "SMM 0#锌锭(宁波)",
  280. // Url: "https://hq.smm.cn/ajax/spot/history/202004070006",
  281. // Unit: "元/吨",
  282. // Frequency: "日度",
  283. // },
  284. // {
  285. // Name: "Zn50国产TC(月)",
  286. // Url: "https://hq.smm.cn/ajax/spot/history/201312030008",
  287. // Unit: "元/金属吨",
  288. // Frequency: "月度",
  289. // },
  290. // {
  291. // Name: "Zn50进口TC(月)",
  292. // Url: "https://hq.smm.cn/ajax/spot/history/201312030009",
  293. // Unit: "美元/千吨",
  294. // Frequency: "月度",
  295. // },
  296. {
  297. Name: "Zn50国产TC(周)",
  298. Url: "https://hq.smm.cn/ajax/spot/history/202004070002",
  299. Unit: "元/金属吨",
  300. Frequency: "周度",
  301. },
  302. {
  303. Name: "Zn50进口TC(周)",
  304. Url: "https://hq.smm.cn/ajax/spot/history/202004070001",
  305. Unit: "美元/千吨",
  306. Frequency: "周度",
  307. },
  308. {
  309. Name: "Zn50内蒙古国产TC(周)",
  310. Url: "https://hq.smm.cn/ajax/spot/history/201504080006",
  311. Unit: "元/金属吨",
  312. Frequency: "周度",
  313. },
  314. {
  315. Name: "Zn50陕西国产TC(周)",
  316. Url: "https://hq.smm.cn/ajax/spot/history/201504080007",
  317. Unit: "元/金属吨",
  318. Frequency: "周度",
  319. },
  320. {
  321. Name: "Zn50甘肃国产TC(周)",
  322. Url: "https://hq.smm.cn/ajax/spot/history/202108050001",
  323. Unit: "元/金属吨",
  324. Frequency: "周度",
  325. },
  326. {
  327. Name: "Zn50四川国产TC(周)",
  328. Url: "https://hq.smm.cn/ajax/spot/history/201504080008",
  329. Unit: "元/金属吨",
  330. Frequency: "周度",
  331. },
  332. {
  333. Name: "Zn50广西国产TC(周)",
  334. Url: "https://hq.smm.cn/ajax/spot/history/201504080009",
  335. Unit: "元/金属吨",
  336. Frequency: "周度",
  337. },
  338. {
  339. Name: "Zn50云南国产TC(周)",
  340. Url: "https://hq.smm.cn/ajax/spot/history/201504080010",
  341. Unit: "元/金属吨",
  342. Frequency: "周度",
  343. },
  344. {
  345. Name: "Zn50湖南国产TC(周)",
  346. Url: "https://hq.smm.cn/ajax/spot/history/201504080011",
  347. Unit: "元/金属吨",
  348. Frequency: "周度",
  349. },
  350. }
  351. type SmmResponse struct {
  352. Code int
  353. Data []*SmmData
  354. Msg string
  355. }
  356. type SmmData struct {
  357. Highs float64 `json:"highs"`
  358. Low float64 `json:"low"`
  359. Average float64 `json:"average"`
  360. VchangeRate float64 `json:"vchange_rate"`
  361. LowShow string `json:"low_show"`
  362. HighShow string `json:"high_show"`
  363. AverageShow string `json:"average_show"`
  364. ProductId string `json:"product_id"`
  365. Vchange float64 `json:"vchange"`
  366. RenewDate string `json:"renew_date"`
  367. ChangeValueShow string `json:"change_value_show"`
  368. ChangeRateShow string `json:"change_rate_show"`
  369. }
  370. type EdbInfoData struct {
  371. ClassifyName string
  372. IndexName string
  373. IndexCode string
  374. Frequency string
  375. Unit string
  376. Value string
  377. LastDate time.Time
  378. OldDate time.Time
  379. Data map[string]float64
  380. SmmData
  381. }
  382. func SyncShangHaiSmm(cont context.Context) (err error) {
  383. utils.FileLog.Info("上海有色爬虫开始更新")
  384. defer func() {
  385. if err := recover(); err != nil {
  386. utils.FileLog.Error("上海有色爬虫更新失败:%+v", err)
  387. }
  388. }()
  389. upMonth := time.Now().AddDate(0, -1, 0).Format(utils.FormatDate)
  390. curDate := time.Now().Format(utils.FormatDate)
  391. reqList := make([]SmmRequest, 0)
  392. reqList = append(reqList, zincReqs...)
  393. reqList = append(reqList, copperReqs...)
  394. reqList = append(reqList, nickelReqs...)
  395. edbInfoList := make([]*EdbInfoData, 0)
  396. for _, v := range reqList {
  397. url := fmt.Sprintf("%s/%s/%s", v.Url, upMonth, curDate)
  398. req, e := http.NewRequest("GET", url, nil)
  399. if e != nil {
  400. fmt.Println(e)
  401. return
  402. }
  403. // 发送请求
  404. client := &http.Client{}
  405. resp, e := client.Do(req)
  406. if e != nil {
  407. fmt.Println(e)
  408. return
  409. }
  410. var respData SmmResponse
  411. body, er := io.ReadAll(resp.Body)
  412. if er != nil {
  413. fmt.Println(er)
  414. return er
  415. }
  416. if err = json.Unmarshal(body, &respData); err != nil {
  417. fmt.Println(err)
  418. return
  419. }
  420. if respData.Code != 0 {
  421. fmt.Printf("上海有色爬虫请求失败, 指标名称:%s, 指标地址:%s", v.Name, v.Url)
  422. continue
  423. }
  424. data := respData.Data
  425. edbInfoList = append(edbInfoList, &EdbInfoData{
  426. IndexName: v.Name,
  427. Frequency: v.Frequency,
  428. Unit: v.Unit,
  429. Value: v.Value,
  430. SmmData: *data[len(data)-1],
  431. })
  432. utils.FileLog.Info("上海有色爬虫请求成功, 指标名称:%s, 指标数据:%+v", v.Name, data[len(data)-1])
  433. }
  434. urlStr := `shanghai_smm/refresh/list`
  435. postUrl := utils.EDB_LIB_URL + urlStr
  436. postData, err := json.Marshal(edbInfoList)
  437. if err != nil {
  438. utils.FileLog.Info("Marshal Err:" + err.Error())
  439. return
  440. }
  441. result, err := sci99.HttpPost(postUrl, string(postData), "application/json")
  442. if err != nil {
  443. utils.FileLog.Info("HttpPost Err:" + err.Error())
  444. return
  445. }
  446. resp := new(models.BaseResponse)
  447. err = json.Unmarshal(result, &resp)
  448. if err != nil {
  449. fmt.Println(err)
  450. utils.FileLog.Info("Unmarshal resp Err:" + err.Error())
  451. return
  452. }
  453. if resp.Ret != 200 {
  454. fmt.Println("上海有色爬虫更新失败")
  455. return
  456. }
  457. utils.FileLog.Info("上海有色爬虫完成更新")
  458. return
  459. }
  460. // 解析读取历史excel数据,将历史数据转化为Smm结构体
  461. func ExcelToSmm(f *excelize.File, s string) (edbInfoList []*EdbInfoData) {
  462. cols, err := f.GetCols(s)
  463. if err != nil {
  464. fmt.Println(err)
  465. return
  466. }
  467. date := cols[0][4:]
  468. dateFormat := make([]string, 0)
  469. for _, v := range date {
  470. if v == "" {
  471. continue
  472. }
  473. var parseDate time.Time
  474. var err error
  475. // 表格的日期存在两种格式
  476. if strings.Contains(s, "锌") {
  477. parseDate, err = time.Parse(utils.FormatDate, v)
  478. if err != nil {
  479. parseDate, err = time.Parse("01-02-06", v)
  480. }
  481. } else {
  482. parseDate, err = time.Parse("01-02-06", v)
  483. if err != nil {
  484. parseDate, err = time.Parse(utils.FormatDate, v)
  485. }
  486. }
  487. if err != nil {
  488. fmt.Println(err)
  489. return
  490. }
  491. dateFormat = append(dateFormat, parseDate.Format(utils.FormatDate))
  492. }
  493. for i := 1; i < len(cols); i++ {
  494. tmpEdbInfo := new(EdbInfoData)
  495. tmpEdbInfo.IndexName = cols[i][0]
  496. tmpEdbInfo.IndexCode = cols[i][1]
  497. tmpEdbInfo.Frequency = cols[i][2]
  498. tmpEdbInfo.Unit = cols[i][3]
  499. tmpEdbInfo.Data = make(map[string]float64)
  500. tmpEdbInfo.OldDate = time.Now()
  501. for j := 4; j < len(cols[i]); j++ {
  502. floatVal, err := strconv.ParseFloat(cols[i][j], 64)
  503. if err != nil {
  504. fmt.Println("无效字符", cols[i][j])
  505. continue
  506. }
  507. tmpEdbInfo.Data[dateFormat[j-4]] = floatVal
  508. curTime, _ := time.Parse(utils.FormatDate, dateFormat[j-4])
  509. if curTime.After(tmpEdbInfo.LastDate) {
  510. tmpEdbInfo.LastDate = curTime
  511. }
  512. if curTime.Before(tmpEdbInfo.OldDate) {
  513. tmpEdbInfo.OldDate = curTime
  514. }
  515. }
  516. edbInfoList = append(edbInfoList, tmpEdbInfo)
  517. }
  518. return
  519. }
  520. func SyncOldExcel(ctx context.Context) error {
  521. fmt.Println("excel数据录入中")
  522. err := OldExcel()
  523. if err != nil {
  524. fmt.Println(err)
  525. utils.FileLog.Info(err.Error())
  526. return err
  527. }
  528. fmt.Println("excel数据录入成功")
  529. task.DeleteTask("shanghaiOldExcel")
  530. return nil
  531. }
  532. func OldExcel() (err error) {
  533. excelPath := utils.OLD_EXCEL_PATH_JR
  534. if excelPath == "" {
  535. fmt.Println("excel文件路径为空")
  536. return
  537. }
  538. f, err := excelize.OpenFile(excelPath)
  539. if err != nil {
  540. fmt.Print(err)
  541. return
  542. }
  543. var edbClassify = []string{`镍`, `铜`, `锌`, `锌(日度)`, `二期`}
  544. for _, v := range edbClassify {
  545. edbInfoList := ExcelToSmm(f, v)
  546. _, err = json.Marshal(edbInfoList)
  547. if err != nil {
  548. fmt.Println(err)
  549. return
  550. }
  551. fmt.Println("成功:", v)
  552. if len(edbInfoList) == 0 {
  553. continue
  554. }
  555. urlStr := `shanghai_smm/refresh/excel`
  556. postUrl := utils.EDB_LIB_URL + urlStr
  557. postData, er := json.Marshal(edbInfoList)
  558. if er != nil {
  559. err = er
  560. utils.FileLog.Info("Marshal Err:" + er.Error())
  561. return
  562. }
  563. result, er := sci99.HttpPost(postUrl, string(postData), "application/json")
  564. if er != nil {
  565. err = er
  566. utils.FileLog.Info("HttpPost Err:" + er.Error())
  567. return
  568. }
  569. resp := new(models.BaseResponse)
  570. err = json.Unmarshal(result, &resp)
  571. if err != nil {
  572. utils.FileLog.Info("Unmarshal resp Err:" + err.Error())
  573. return
  574. }
  575. if resp.Ret != 200 {
  576. err = errors.New(resp.ErrMsg)
  577. utils.FileLog.Info("上海有色网excel历史有色数据更新失败")
  578. return
  579. }
  580. time.Sleep(time.Second)
  581. }
  582. return
  583. }