package cardsinfo import ( "errors" "github.com/antchfx/htmlquery" "golang.org/x/net/html" "strconv" "strings" ) const SCGURL = "http://www.starcitygames.com/results?name=" func GetSCGPrices(name string) ([]CardPrice, error) { preprocessedName := preprocessNameForSearch(name) url := getSCGUrl(preprocessedName) doc, err := htmlquery.LoadURL(url) if err != nil { return nil, err } return fetchPrices(doc) } func preprocessNameForSearch(name string) string { return strings.Replace(name, "|", "", 1) } func fetchPrices(doc *html.Node) ([]CardPrice, error) { priceContainers := getPriceContainers(doc) prices := make([]CardPrice, 0) for _, container := range priceContainers { name := parseName(container) edition := parseEdition(container) price := parsePrice(container) link := parseLink(container) cardPrice := buildCardPrice(name, edition, price, link) if isValidPrice(&cardPrice) { prices = append(prices, cardPrice) } } return prices, nil } func isValidPrice(price *CardPrice) bool { isValid := true isValid = isValid && (price.Name != "") isValid = isValid && (price.Edition != "") isValid = isValid && (price.Price != 0.0) isValid = isValid && (price.Link != "") return isValid } func buildCardPrice(name, edition string, price float64, link string) CardPrice { cardPrice := CardPrice{ Name: name, Edition: edition, Price: price, Link: link, } return cardPrice } func getPriceContainers(doc *html.Node) []*html.Node { nodesOdd := htmlquery.Find(doc, "//tr[contains(@class, 'deckdbbody_row')]") nodesEven := htmlquery.Find(doc, "//tr[contains(@class, 'deckdbbody2_row')]") nodes := append(nodesOdd, nodesEven...) return nodes } func fetchPrice(price string) (float64, error) { split := strings.Split(price, "$") if len(split) < 2 { return 0, errors.New("Not enough values") } p := split[1] v, err := strconv.ParseFloat(p, 64) return v, err } func getSCGUrl(name string) string { splitted := strings.Split(name, " ") scgName := strings.Join(splitted, "+") url := SCGURL + scgName return url } func parseName(container *html.Node) string { nameNode := htmlquery.FindOne(container, "//td[contains(@class, 'search_results_1')]") if nameNode == nil { return "" } name := htmlquery.InnerText(nameNode) return name } func parseEdition(container *html.Node) string { editionNode := htmlquery.FindOne(container, "//td[contains(@class, 'search_results_2')]") if editionNode == nil { return "" } edition := strings.Trim(htmlquery.InnerText(editionNode), "\n ") return edition } func parsePrice(container *html.Node) float64 { priceNode := htmlquery.FindOne(container, "//td[contains(@class, 'search_results_9')]") if priceNode == nil { return 0.0 } priceString := htmlquery.InnerText(priceNode) price, err := fetchPrice(priceString) if err != nil { return 0.0 } return price } func parseLink(container *html.Node) string { linkNodes := htmlquery.Find(container, "//td[contains(@class, 'search_results_1')]/b/a") if len(linkNodes) == 0 { return "" } linkNode := linkNodes[0] link := fetchLink(linkNode) return link } func fetchLink(linkContainer *html.Node) string { for _, v := range linkContainer.Attr { if v.Key == "href" { return v.Val } } return "" }