smm_shanghai.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  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. upMonth := time.Now().AddDate(0, -1, 0).Format(utils.FormatDate)
  384. curDate := time.Now().Format(utils.FormatDate)
  385. reqList := make([]SmmRequest, 0)
  386. reqList = append(reqList, zincReqs...)
  387. reqList = append(reqList, copperReqs...)
  388. reqList = append(reqList, nickelReqs...)
  389. edbInfoList := make([]*EdbInfoData, 0)
  390. for _, v := range reqList {
  391. url := fmt.Sprintf("%s/%s/%s", v.Url, upMonth, curDate)
  392. req, e := http.NewRequest("GET", url, nil)
  393. if e != nil {
  394. fmt.Println(e)
  395. return
  396. }
  397. // 发送请求
  398. client := &http.Client{}
  399. resp, e := client.Do(req)
  400. if e != nil {
  401. fmt.Println(e)
  402. return
  403. }
  404. var respData SmmResponse
  405. body, er := io.ReadAll(resp.Body)
  406. if er != nil {
  407. fmt.Println(er)
  408. return er
  409. }
  410. if err = json.Unmarshal(body, &respData); err != nil {
  411. fmt.Println(err)
  412. return
  413. }
  414. if respData.Code != 0 {
  415. fmt.Printf("上海有色爬虫请求失败, 指标名称:%s, 指标地址:%s", v.Name, v.Url)
  416. continue
  417. }
  418. data := respData.Data
  419. edbInfoList = append(edbInfoList, &EdbInfoData{
  420. IndexName: v.Name,
  421. Frequency: v.Frequency,
  422. Unit: v.Unit,
  423. Value: v.Value,
  424. SmmData: *data[len(data)-1],
  425. })
  426. utils.FileLog.Info("上海有色爬虫请求成功, 指标名称:%s, 指标数据:%+v", v.Name, data[len(data)-1])
  427. }
  428. urlStr := `shanghai_smm/refresh/list`
  429. postUrl := utils.EDB_LIB_URL + urlStr
  430. postData, err := json.Marshal(edbInfoList)
  431. if err != nil {
  432. utils.FileLog.Info("Marshal Err:" + err.Error())
  433. return
  434. }
  435. result, err := sci99.HttpPost(postUrl, string(postData), "application/json")
  436. if err != nil {
  437. utils.FileLog.Info("HttpPost Err:" + err.Error())
  438. return
  439. }
  440. resp := new(models.BaseResponse)
  441. err = json.Unmarshal(result, &resp)
  442. if err != nil {
  443. fmt.Println(err)
  444. utils.FileLog.Info("Unmarshal resp Err:" + err.Error())
  445. return
  446. }
  447. if resp.Ret != 200 {
  448. fmt.Println("上海有色爬虫更新失败")
  449. return
  450. }
  451. return
  452. }
  453. // 解析读取历史excel数据,将历史数据转化为Smm结构体
  454. func ExcelToSmm(f *excelize.File, s string) (edbInfoList []*EdbInfoData) {
  455. cols, err := f.GetCols(s)
  456. if err != nil {
  457. fmt.Println(err)
  458. return
  459. }
  460. date := cols[0][4:]
  461. dateFormat := make([]string, 0)
  462. for _, v := range date {
  463. if v == "" {
  464. continue
  465. }
  466. var parseDate time.Time
  467. var err error
  468. // 表格的日期存在两种格式
  469. if strings.Contains(s, "锌") {
  470. parseDate, err = time.Parse(utils.FormatDate, v)
  471. if err != nil {
  472. parseDate, err = time.Parse("01-02-06", v)
  473. }
  474. } else {
  475. parseDate, err = time.Parse("01-02-06", v)
  476. if err != nil {
  477. parseDate, err = time.Parse(utils.FormatDate, v)
  478. }
  479. }
  480. if err != nil {
  481. fmt.Println(err)
  482. return
  483. }
  484. dateFormat = append(dateFormat, parseDate.Format(utils.FormatDate))
  485. }
  486. for i := 1; i < len(cols); i++ {
  487. tmpEdbInfo := new(EdbInfoData)
  488. tmpEdbInfo.IndexName = cols[i][0]
  489. tmpEdbInfo.IndexCode = cols[i][1]
  490. tmpEdbInfo.Frequency = cols[i][2]
  491. tmpEdbInfo.Unit = cols[i][3]
  492. tmpEdbInfo.Data = make(map[string]float64)
  493. tmpEdbInfo.OldDate = time.Now()
  494. for j := 4; j < len(cols[i]); j++ {
  495. floatVal, err := strconv.ParseFloat(cols[i][j], 64)
  496. if err != nil {
  497. fmt.Println("无效字符", cols[i][j])
  498. continue
  499. }
  500. tmpEdbInfo.Data[dateFormat[j-4]] = floatVal
  501. curTime, _ := time.Parse(utils.FormatDate, dateFormat[j-4])
  502. if curTime.After(tmpEdbInfo.LastDate) {
  503. tmpEdbInfo.LastDate = curTime
  504. }
  505. if curTime.Before(tmpEdbInfo.OldDate) {
  506. tmpEdbInfo.OldDate = curTime
  507. }
  508. }
  509. edbInfoList = append(edbInfoList, tmpEdbInfo)
  510. }
  511. return
  512. }
  513. func SyncOldExcel(ctx context.Context) error {
  514. fmt.Println("excel数据录入中")
  515. err := OldExcel()
  516. if err != nil {
  517. fmt.Println(err)
  518. utils.FileLog.Info(err.Error())
  519. return err
  520. }
  521. fmt.Println("excel数据录入成功")
  522. task.DeleteTask("shanghaiOldExcel")
  523. return nil
  524. }
  525. func OldExcel() (err error) {
  526. excelPath := utils.OLD_EXCEL_PATH_JR
  527. if excelPath == "" {
  528. fmt.Println("excel文件路径为空")
  529. return
  530. }
  531. f, err := excelize.OpenFile(excelPath)
  532. if err != nil {
  533. fmt.Print(err)
  534. return
  535. }
  536. var edbClassify = []string{`镍`, `铜`, `锌`, `锌(日度)`, `二期`}
  537. for _, v := range edbClassify {
  538. edbInfoList := ExcelToSmm(f, v)
  539. _, err = json.Marshal(edbInfoList)
  540. if err != nil {
  541. fmt.Println(err)
  542. return
  543. }
  544. fmt.Println("成功:", v)
  545. if len(edbInfoList) == 0 {
  546. continue
  547. }
  548. urlStr := `shanghai_smm/refresh/excel`
  549. postUrl := utils.EDB_LIB_URL + urlStr
  550. postData, er := json.Marshal(edbInfoList)
  551. if er != nil {
  552. err = er
  553. utils.FileLog.Info("Marshal Err:" + er.Error())
  554. return
  555. }
  556. result, er := sci99.HttpPost(postUrl, string(postData), "application/json")
  557. if er != nil {
  558. err = er
  559. utils.FileLog.Info("HttpPost Err:" + er.Error())
  560. return
  561. }
  562. resp := new(models.BaseResponse)
  563. err = json.Unmarshal(result, &resp)
  564. if err != nil {
  565. utils.FileLog.Info("Unmarshal resp Err:" + err.Error())
  566. return
  567. }
  568. if resp.Ret != 200 {
  569. err = errors.New(resp.ErrMsg)
  570. utils.FileLog.Info("上海有色网excel历史有色数据更新失败")
  571. return
  572. }
  573. time.Sleep(time.Second)
  574. }
  575. return
  576. }