This commit is contained in:
parent
8eb26b08f6
commit
d55cdfc0d5
15
cmd/main.go
15
cmd/main.go
@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"gitea.timerzz.com/kedaya_haitao/cn-coach-spider/pkg/options"
|
"gitea.timerzz.com/kedaya_haitao/cn-coach-spider/pkg/options"
|
||||||
|
"gitea.timerzz.com/kedaya_haitao/cn-coach-spider/server"
|
||||||
"gitea.timerzz.com/kedaya_haitao/cn-coach-spider/spider"
|
"gitea.timerzz.com/kedaya_haitao/cn-coach-spider/spider"
|
||||||
coach_client "gitea.timerzz.com/kedaya_haitao/common/pkg/coach-client"
|
coach_client "gitea.timerzz.com/kedaya_haitao/common/pkg/coach-client"
|
||||||
"gitea.timerzz.com/kedaya_haitao/common/pkg/database"
|
"gitea.timerzz.com/kedaya_haitao/common/pkg/database"
|
||||||
@ -38,13 +39,21 @@ func main() {
|
|||||||
Colorful: true,
|
Colorful: true,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
shopType := os.Getenv("SHOP_TYPE")
|
||||||
|
if shopType != options.ShopType_coach && shopType != options.ShopType_outlet {
|
||||||
|
glog.Fatalf("SHOP_TYPE环境变量错误,请设置SHOP_TYPE=coach或SHOP_TYPE=outlet")
|
||||||
|
}
|
||||||
// coach client
|
// coach client
|
||||||
client, err := coach_client.CNClient()
|
var xMac = coach_client.XMac_Coach
|
||||||
|
if shopType == options.ShopType_outlet {
|
||||||
|
xMac = coach_client.XMac_Outlet
|
||||||
|
}
|
||||||
|
client, err := coach_client.CNClient(xMac)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Fatalf("初始化coach client失败:%v", err)
|
glog.Fatalf("初始化coach client失败:%v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
spiderCtl := spider.NewController(client, db, cfg.Interval)
|
spiderCtl := spider.NewController(client, db, cfg.Interval, shopType)
|
||||||
|
|
||||||
go spiderCtl.Run(ctx)
|
go spiderCtl.Run(ctx)
|
||||||
|
|
||||||
@ -54,7 +63,9 @@ func main() {
|
|||||||
r.Get("/health", func(ctx fiber.Ctx) error {
|
r.Get("/health", func(ctx fiber.Ctx) error {
|
||||||
return ctx.SendString("ok")
|
return ctx.SendString("ok")
|
||||||
})
|
})
|
||||||
|
api := r.Group("/api/v1")
|
||||||
|
|
||||||
|
server.NewSpiderSvc(spiderCtl, shopType).RegistryRouter(api)
|
||||||
if err = r.Listen(":8080"); err != nil {
|
if err = r.Listen(":8080"); err != nil {
|
||||||
glog.Warningf("server over: %v", err)
|
glog.Warningf("server over: %v", err)
|
||||||
}
|
}
|
||||||
|
3
go.mod
3
go.mod
@ -5,7 +5,7 @@ go 1.22.2
|
|||||||
toolchain go1.22.3
|
toolchain go1.22.3
|
||||||
|
|
||||||
require (
|
require (
|
||||||
gitea.timerzz.com/kedaya_haitao/common v0.0.0-20240614095701-e7fa9e7dd21a
|
gitea.timerzz.com/kedaya_haitao/common v0.0.0-20240616020231-a7d6c7c6661e
|
||||||
github.com/gofiber/fiber/v3 v3.0.0-beta.2
|
github.com/gofiber/fiber/v3 v3.0.0-beta.2
|
||||||
github.com/golang/glog v1.2.1
|
github.com/golang/glog v1.2.1
|
||||||
github.com/samber/lo v1.39.0
|
github.com/samber/lo v1.39.0
|
||||||
@ -41,6 +41,7 @@ require (
|
|||||||
github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 // indirect
|
github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 // indirect
|
||||||
github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 // indirect
|
github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 // indirect
|
||||||
github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010 // indirect
|
github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010 // indirect
|
||||||
|
github.com/expr-lang/expr v1.16.9 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||||
github.com/gaukas/godicttls v0.0.4 // indirect
|
github.com/gaukas/godicttls v0.0.4 // indirect
|
||||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||||
|
6
go.sum
6
go.sum
@ -1,6 +1,6 @@
|
|||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
gitea.timerzz.com/kedaya_haitao/common v0.0.0-20240614095701-e7fa9e7dd21a h1:+O1PXfkfUQG5A830+q6YAg76jX663W8cMJxTCcGwjW0=
|
gitea.timerzz.com/kedaya_haitao/common v0.0.0-20240616020231-a7d6c7c6661e h1:WCJfnIO44DZmkMdEoyZLMUSG68btBZ6FzVAnXe68Spg=
|
||||||
gitea.timerzz.com/kedaya_haitao/common v0.0.0-20240614095701-e7fa9e7dd21a/go.mod h1:MAmc7ooakm0o+4YshgKb+uE3Mfhex10s2RcJMiIYick=
|
gitea.timerzz.com/kedaya_haitao/common v0.0.0-20240616020231-a7d6c7c6661e/go.mod h1:uV586p6Z8LIq3I8O/pXZv+jIkIwnwBjAz0D7KrhB9JM=
|
||||||
github.com/3andne/restls-client-go v0.1.6 h1:tRx/YilqW7iHpgmEL4E1D8dAsuB0tFF3uvncS+B6I08=
|
github.com/3andne/restls-client-go v0.1.6 h1:tRx/YilqW7iHpgmEL4E1D8dAsuB0tFF3uvncS+B6I08=
|
||||||
github.com/3andne/restls-client-go v0.1.6/go.mod h1:iEdTZNt9kzPIxjIGSMScUFSBrUH6bFRNg0BWlP4orEY=
|
github.com/3andne/restls-client-go v0.1.6/go.mod h1:iEdTZNt9kzPIxjIGSMScUFSBrUH6bFRNg0BWlP4orEY=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
@ -82,6 +82,8 @@ github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 h1:tlDMEdcPRQKBE
|
|||||||
github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1/go.mod h1:4RfsapbGx2j/vU5xC/5/9qB3kn9Awp1YDiEnN43QrJ4=
|
github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1/go.mod h1:4RfsapbGx2j/vU5xC/5/9qB3kn9Awp1YDiEnN43QrJ4=
|
||||||
github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010 h1:fuGucgPk5dN6wzfnxl3D0D3rVLw4v2SbBT9jb4VnxzA=
|
github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010 h1:fuGucgPk5dN6wzfnxl3D0D3rVLw4v2SbBT9jb4VnxzA=
|
||||||
github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010/go.mod h1:JtBcj7sBuTTRupn7c2bFspMDIObMJsVK8TeUvpShPok=
|
github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010/go.mod h1:JtBcj7sBuTTRupn7c2bFspMDIObMJsVK8TeUvpShPok=
|
||||||
|
github.com/expr-lang/expr v1.16.9 h1:WUAzmR0JNI9JCiF0/ewwHB1gmcGw5wW7nWt8gc6PpCI=
|
||||||
|
github.com/expr-lang/expr v1.16.9/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4=
|
||||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
||||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||||
|
6
pkg/options/shop.go
Normal file
6
pkg/options/shop.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package options
|
||||||
|
|
||||||
|
const (
|
||||||
|
ShopType_coach = "coach"
|
||||||
|
ShopType_outlet = "coach-outlet"
|
||||||
|
)
|
83
server/spider.go
Normal file
83
server/spider.go
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"gitea.timerzz.com/kedaya_haitao/cn-coach-spider/spider"
|
||||||
|
productv1 "gitea.timerzz.com/kedaya_haitao/common/model/product"
|
||||||
|
"github.com/gofiber/fiber/v3"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SpiderSvc struct {
|
||||||
|
ctl *spider.Controller
|
||||||
|
shopType string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSpiderSvc(ctl *spider.Controller, shopType string) *SpiderSvc {
|
||||||
|
return &SpiderSvc{
|
||||||
|
ctl: ctl,
|
||||||
|
shopType: shopType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SpiderSvc) RegistryRouter(r fiber.Router) {
|
||||||
|
r.Get(fmt.Sprintf("spider/cn/%s/global/calculate", s.shopType), s.GetGlobalCalculate)
|
||||||
|
r.Post(fmt.Sprintf("spider/cn/%s/global/calculate", s.shopType), s.UpsertGlobalCalculate)
|
||||||
|
r.Delete(fmt.Sprintf("spider/cn/%s/global/calculate/u/:id", s.shopType), s.DelGlobalCalculate)
|
||||||
|
r.Post(fmt.Sprintf("spider/cn/%s/calculate", s.shopType), s.UpsertCalculate)
|
||||||
|
r.Delete(fmt.Sprintf("spider/cn/%s/calculate/u/:id", s.shopType), s.DelCalculate)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SpiderSvc) GetGlobalCalculate(ctx fiber.Ctx) error {
|
||||||
|
cals, err := s.ctl.GetGlobalCalculateProcess()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return ctx.JSON(cals)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SpiderSvc) DelGlobalCalculate(ctx fiber.Ctx) error {
|
||||||
|
idStr := ctx.Params("id")
|
||||||
|
if idStr == "" {
|
||||||
|
return fiber.ErrBadRequest
|
||||||
|
}
|
||||||
|
id, _ := strconv.Atoi(idStr)
|
||||||
|
if err := s.ctl.DeleteGlobalCalculateProcess(uint(id)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SpiderSvc) UpsertGlobalCalculate(ctx fiber.Ctx) error {
|
||||||
|
var cs []productv1.CalculateProcess
|
||||||
|
if err := ctx.Bind().JSON(&cs); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.ctl.SaveGlobalCalculateProcess(cs); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SpiderSvc) DelCalculate(ctx fiber.Ctx) error {
|
||||||
|
idStr := ctx.Params("id")
|
||||||
|
if idStr == "" {
|
||||||
|
return fiber.ErrBadRequest
|
||||||
|
}
|
||||||
|
id, _ := strconv.Atoi(idStr)
|
||||||
|
if err := s.ctl.DeleteCalculateProcess(uint(id)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SpiderSvc) UpsertCalculate(ctx fiber.Ctx) error {
|
||||||
|
var cs []productv1.CalculateProcess
|
||||||
|
if err := ctx.Bind().JSON(&cs); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := s.ctl.SaveCalculateProcess(cs); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
115
spider/calculate.go
Normal file
115
spider/calculate.go
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
package spider
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
productv1 "gitea.timerzz.com/kedaya_haitao/common/model/product"
|
||||||
|
"github.com/samber/lo"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
CNCoachPid = "cn-coach"
|
||||||
|
CNCoachOutletPid = "cn-coach-outlet"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *Controller) LoadCalculateProcess() {
|
||||||
|
c.db.Model(&productv1.CalculateProcess{}).Find(&c.calculates, "pid = ?", c.pid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) GetGlobalCalculateProcess() (cs []productv1.CalculateProcess, err error) {
|
||||||
|
err = c.db.Model(&productv1.CalculateProcess{}).Find(&cs, "pid = ?", c.pid).Error
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteGlobalCalculateProcess 删除全局的计算规则
|
||||||
|
func (c *Controller) DeleteGlobalCalculateProcess(id uint) error {
|
||||||
|
if _, idx, exist := lo.FindIndexOf(c.calculates, func(item productv1.CalculateProcess) bool {
|
||||||
|
return item.ID == id
|
||||||
|
}); exist {
|
||||||
|
if err := c.db.Model(&productv1.CalculateProcess{}).Delete(&c.calculates[idx], "id = ?", id).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.calculates = append(c.calculates[:idx], c.calculates[idx+1:]...)
|
||||||
|
go c.updateRate()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SaveGlobalCalculateProcess 更新全局的计算规则
|
||||||
|
func (c *Controller) SaveGlobalCalculateProcess(cs []productv1.CalculateProcess) error {
|
||||||
|
if len(cs) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
cs = lo.Map(cs, func(item productv1.CalculateProcess, index int) productv1.CalculateProcess {
|
||||||
|
item.Pid = c.pid
|
||||||
|
return item
|
||||||
|
})
|
||||||
|
return c.db.Transaction(func(tx *gorm.DB) error {
|
||||||
|
if err := c.db.Save(&cs).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.db.Model(&productv1.CalculateProcess{}).Find(&c.calculates, "pid = ?", c.pid).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
go c.updateRate()
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteCalculateProcess 删除计算规则
|
||||||
|
func (c *Controller) DeleteCalculateProcess(id uint) error {
|
||||||
|
return c.db.Transaction(func(tx *gorm.DB) error {
|
||||||
|
cal := productv1.CalculateProcess{}
|
||||||
|
if err := tx.Model(&productv1.CalculateProcess{}).Where("id = ?", id).First(&cal).Error; err != nil && !errors.As(err, &gorm.ErrRecordNotFound) {
|
||||||
|
return err
|
||||||
|
} else if errors.As(err, &gorm.ErrRecordNotFound) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Model(&productv1.CalculateProcess{}).Where("id = ?", cal.ID).Delete(&cal).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var product productv1.Product
|
||||||
|
if err := tx.Preload("CalculateProcess").First(&product, "pid = ? AND website = ?", cal.Pid, c.website).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
product.CalCNY(append(product.CalculateProcess, c.calculates...))
|
||||||
|
return tx.Model(&product).Where("pid = ? AND website = ?", product.Pid, c.website).Select("rate", "cal_mark", "cny_price").Updates(&product).Error
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SaveCalculateProcess 更新计算规则
|
||||||
|
func (c *Controller) SaveCalculateProcess(cs []productv1.CalculateProcess) error {
|
||||||
|
if len(cs) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.db.Transaction(func(tx *gorm.DB) error {
|
||||||
|
if err := c.db.Save(&cs).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var product productv1.Product
|
||||||
|
if err := tx.Preload("CalculateProcess").First(&product, "pid = ? AND website = ?", cs[0].Pid, c.website).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
product.CalCNY(append(product.CalculateProcess, c.calculates...))
|
||||||
|
return tx.Model(&product).Where("pid = ? AND website = ?", product.Pid, c.website).Select("rate", "cal_mark", "cny_price").Updates(&product).Error
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) updateRate() {
|
||||||
|
var results []*productv1.Product
|
||||||
|
c.db.Where("website = ?", c.website).FindInBatches(&results, 20, func(tx *gorm.DB, batch int) error {
|
||||||
|
for _, result := range results {
|
||||||
|
var calculate []productv1.CalculateProcess
|
||||||
|
c.db.Find(&calculate, "pid = ? AND website = ?", result.Pid, c.website)
|
||||||
|
result.CalCNY(append(calculate, c.calculates...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存对当前批记录的修改
|
||||||
|
tx.Save(&results)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
@ -3,6 +3,7 @@ package spider
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"gitea.timerzz.com/kedaya_haitao/cn-coach-spider/pkg/options"
|
||||||
"gitea.timerzz.com/kedaya_haitao/common/model/product"
|
"gitea.timerzz.com/kedaya_haitao/common/model/product"
|
||||||
coach_client "gitea.timerzz.com/kedaya_haitao/common/pkg/coach-client"
|
coach_client "gitea.timerzz.com/kedaya_haitao/common/pkg/coach-client"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
@ -13,19 +14,33 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Controller struct {
|
type Controller struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
client *coach_client.CN
|
client *coach_client.CN
|
||||||
db *gorm.DB
|
db *gorm.DB
|
||||||
interval time.Duration
|
interval time.Duration
|
||||||
|
website productv1.Website
|
||||||
|
linkPrefix string
|
||||||
|
pid string
|
||||||
|
|
||||||
|
calculates []productv1.CalculateProcess
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewController(client *coach_client.CN, db *gorm.DB, interval time.Duration) *Controller {
|
func NewController(client *coach_client.CN, db *gorm.DB, interval time.Duration, shopType string) *Controller {
|
||||||
ctl := &Controller{
|
ctl := &Controller{
|
||||||
client: client,
|
client: client,
|
||||||
db: db,
|
db: db,
|
||||||
interval: interval,
|
interval: interval,
|
||||||
|
website: productv1.WebSite_CN_Coach,
|
||||||
|
linkPrefix: "https://www.coach.com.cn/products/",
|
||||||
|
pid: CNCoachPid,
|
||||||
|
}
|
||||||
|
if shopType == options.ShopType_outlet {
|
||||||
|
ctl.website = productv1.WebSite_CN_Coach_Outlet
|
||||||
|
ctl.linkPrefix = "https://www.coach.com.cn/outlet/products/"
|
||||||
|
ctl.pid = CNCoachOutletPid
|
||||||
}
|
}
|
||||||
ctl.AutoMigrate()
|
ctl.AutoMigrate()
|
||||||
|
ctl.LoadCalculateProcess()
|
||||||
return ctl
|
return ctl
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,6 +49,7 @@ func (c *Controller) AutoMigrate() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) Run(ctx context.Context) {
|
func (c *Controller) Run(ctx context.Context) {
|
||||||
c.ctx = ctx
|
c.ctx = ctx
|
||||||
ticker := time.NewTicker(c.interval)
|
ticker := time.NewTicker(c.interval)
|
||||||
@ -79,17 +95,24 @@ func (c *Controller) Crawl() error {
|
|||||||
func (c *Controller) saveRespData(list []coach_client.CNItem) error {
|
func (c *Controller) saveRespData(list []coach_client.CNItem) error {
|
||||||
var products = make([]productv1.Product, 0, len(list))
|
var products = make([]productv1.Product, 0, len(list))
|
||||||
for _, item := range list {
|
for _, item := range list {
|
||||||
products = append(products, productv1.Product{
|
var savedProduct productv1.Product
|
||||||
UpdatedAt: time.Now(),
|
c.db.Model(&savedProduct).Where("pid = ?", item.Code).Select("dw_price").Scan(&savedProduct)
|
||||||
Name: item.Title,
|
p := productv1.Product{
|
||||||
Pid: item.Code,
|
UpdatedAt: time.Now(),
|
||||||
Link: fmt.Sprintf("https://www.coachoutlet.cn/products/%s", item.Code),
|
Name: item.Title,
|
||||||
Image: item.Images[0].Imgs[0].Img,
|
Pid: item.Code,
|
||||||
Orderable: item.Stock > 0,
|
Link: fmt.Sprintf("%s%s", c.linkPrefix, item.Code),
|
||||||
DiscPercent: 100 - int(item.DiscountRateMin*100),
|
Image: item.Images[0].Imgs[0].Img,
|
||||||
CNYPrice: item.SkuMaxPrice,
|
Orderable: item.Stock > 0,
|
||||||
Website: productv1.WebSite_CN_Coach,
|
DiscPercent: 100 - int(item.DiscountRateMin*100),
|
||||||
})
|
OriginalPrice: item.SkuMaxPrice,
|
||||||
|
Website: c.website,
|
||||||
|
DWPrice: savedProduct.DWPrice,
|
||||||
|
}
|
||||||
|
var calculate []productv1.CalculateProcess
|
||||||
|
c.db.Model(&productv1.CalculateProcess{}).Find(&calculate, "pid = ? AND website = ?", p.Pid, c.website)
|
||||||
|
p.CalCNY(append(calculate, c.calculates...))
|
||||||
|
products = append(products, p)
|
||||||
}
|
}
|
||||||
// 去重
|
// 去重
|
||||||
products = lo.UniqBy(products, func(p productv1.Product) string {
|
products = lo.UniqBy(products, func(p productv1.Product) string {
|
||||||
@ -97,6 +120,6 @@ func (c *Controller) saveRespData(list []coach_client.CNItem) error {
|
|||||||
})
|
})
|
||||||
return c.db.Clauses(clause.OnConflict{
|
return c.db.Clauses(clause.OnConflict{
|
||||||
Columns: []clause.Column{{Name: "pid"}},
|
Columns: []clause.Column{{Name: "pid"}},
|
||||||
DoUpdates: clause.AssignmentColumns([]string{"name", "link", "orderable", "cny_price", "rate", "price_status", "disc_percent", "updated_at"}),
|
DoUpdates: clause.AssignmentColumns([]string{"name", "link", "orderable", "original_price", "rate", "price_status", "disc_percent", "updated_at"}),
|
||||||
}).Create(products).Error
|
}).Create(products).Error
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user