mirror of https://github.com/fmartingr/bazaar.git
108 lines
2.5 KiB
Go
108 lines
2.5 KiB
Go
package amazon
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/PuerkitoBio/goquery"
|
|
"github.com/fmartingr/bazaar/pkg/models"
|
|
"github.com/fmartingr/bazaar/pkg/utils"
|
|
"github.com/goodsign/monday"
|
|
)
|
|
|
|
var Domains = []string{"www.amazon.es", "www.amazon.com"}
|
|
|
|
type AmazonShop struct {
|
|
models.ShopOptions
|
|
domains []string
|
|
}
|
|
|
|
var priceSelectors = []string{
|
|
"#buybox span.a-color-price",
|
|
"#tp_price_block_total_price_ww",
|
|
"#price",
|
|
".priceToPay .a-offscreen",
|
|
}
|
|
|
|
var releaseDateLayoutByDomain = map[string]string{
|
|
Domains[0]: "2 January 2006",
|
|
Domains[1]: "January 2, 2006",
|
|
}
|
|
|
|
func (s *AmazonShop) Get(u *url.URL) (*models.Product, error) {
|
|
body, err := s.ShopOptions.Client.Get(u)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error during request: %s", err)
|
|
}
|
|
|
|
doc, err := goquery.NewDocumentFromReader(body)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error parsing body: %s", err)
|
|
}
|
|
|
|
product := models.Product{
|
|
URL: u.String(),
|
|
}
|
|
|
|
var tentativePrice string
|
|
for _, selector := range priceSelectors {
|
|
tentativePrice = strings.TrimSpace(doc.Find(selector).First().Text())
|
|
if tentativePrice != "" {
|
|
priceNum, err := strconv.ParseFloat(utils.ExtractPrice(tentativePrice), 64)
|
|
if err != nil {
|
|
log.Println(err)
|
|
} else {
|
|
product.PriceText = tentativePrice
|
|
product.Price = priceNum
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
product.Name = strings.TrimSpace(doc.Find("#productTitle").Text())
|
|
|
|
imagesJSON, exists := doc.Find("#main-image-container img").Attr("data-a-dynamic-image")
|
|
if !exists {
|
|
log.Printf("Can't find image for %s", u.String())
|
|
}
|
|
var images map[string]interface{}
|
|
if err := json.Unmarshal([]byte(imagesJSON), &images); err != nil {
|
|
log.Printf("error unmarshalling: %s", err)
|
|
}
|
|
var lastImage string
|
|
for key := range images {
|
|
lastImage = key
|
|
}
|
|
product.ImageURL = lastImage
|
|
|
|
releaseDateElement := doc.Find(".book_details-publication_date")
|
|
if len(releaseDateElement.Nodes) > 0 {
|
|
releaseDateRaw := releaseDateElement.Parent().Parent().Find(".rpi-attribute-value").Text()
|
|
|
|
releaseDate, err := utils.ParseReleaseDate(releaseDateLayoutByDomain[u.Host], strings.TrimSpace(releaseDateRaw), monday.LocaleEsES)
|
|
if err != nil {
|
|
log.Println(err)
|
|
} else {
|
|
product.ReleaseDate = releaseDate
|
|
}
|
|
}
|
|
|
|
product.InStock = !strings.Contains(doc.Find("#availability").Text(), "No disponible")
|
|
|
|
return &product, nil
|
|
}
|
|
|
|
func NewAmazonShopFactory() models.ShopFactory {
|
|
return func(shopOptions models.ShopOptions) models.Shop {
|
|
shop := AmazonShop{
|
|
ShopOptions: shopOptions,
|
|
domains: Domains,
|
|
}
|
|
return &shop
|
|
}
|
|
}
|