Steve Dudenhoeffer
6de455b1bd
Added price field to Item struct in AisleGopher and implemented logic to extract price data. Updated Wegmans parser to validate URL structure by ensuring the second segment is "product". These changes improve data accuracy and error handling.
98 lines
1.7 KiB
Go
98 lines
1.7 KiB
Go
package wegmans
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"io"
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"gitea.stevedudenhoeffer.com/steve/go-extractor"
|
|
)
|
|
|
|
type Config struct {
|
|
}
|
|
|
|
var DefaultConfig = Config{}
|
|
|
|
var ErrNilBrowser = errors.New("browser is nil")
|
|
var ErrNilURL = errors.New("url is nil")
|
|
var ErrInvalidURL = errors.New("invalid url")
|
|
|
|
type Item struct {
|
|
ID int
|
|
Name string
|
|
Price float64
|
|
}
|
|
|
|
func deferClose(c io.Closer) {
|
|
if c != nil {
|
|
_ = c.Close()
|
|
}
|
|
}
|
|
|
|
func (c Config) GetItemPrice(ctx context.Context, b extractor.Browser, u *url.URL) (Item, error) {
|
|
if b == nil {
|
|
return Item{}, ErrNilBrowser
|
|
}
|
|
|
|
if u == nil {
|
|
return Item{}, ErrNilURL
|
|
}
|
|
|
|
// urls in the format of:
|
|
// https://shop.wegmans.com/product/24921[/wegmans-frozen-thin-crust-uncured-pepperoni-pizza]
|
|
// (the slug is optional)
|
|
|
|
// get the product ID
|
|
a := strings.Split(u.Path, "/")
|
|
|
|
if len(a) < 3 {
|
|
return Item{}, ErrInvalidURL
|
|
}
|
|
|
|
if a[1] != "product" {
|
|
return Item{}, ErrInvalidURL
|
|
}
|
|
|
|
id, _ := strconv.Atoi(a[2])
|
|
|
|
if id == 0 {
|
|
return Item{}, ErrInvalidURL
|
|
}
|
|
|
|
doc, err := b.Open(ctx, u.String(), extractor.OpenPageOptions{})
|
|
defer deferClose(doc)
|
|
|
|
if err != nil {
|
|
return Item{}, err
|
|
}
|
|
|
|
timeout := 15 * time.Second
|
|
_ = doc.WaitForNetworkIdle(&timeout)
|
|
|
|
res := Item{
|
|
ID: id,
|
|
}
|
|
|
|
titles := doc.Select("h1[data-test]")
|
|
|
|
if len(titles) != 0 {
|
|
res.Name, _ = titles[0].Text()
|
|
}
|
|
|
|
prices := doc.Select("span[data-test=\"amount\"] span:nth-child(1)")
|
|
|
|
if len(prices) != 0 {
|
|
priceStr, _ := prices[0].Text()
|
|
priceStr = strings.ReplaceAll(priceStr, "$", "")
|
|
priceStr = strings.ReplaceAll(priceStr, ",", "")
|
|
price, _ := strconv.ParseFloat(priceStr, 64)
|
|
res.Price = price
|
|
}
|
|
|
|
return res, nil
|
|
}
|