krasoffski/lsgbc

View on GitHub
item.go

Summary

Maintainability
A
1 hr
Test Coverage
package main

import (
    "fmt"
    "strings"

    "github.com/krasoffski/gomill/node"
    glob "github.com/ryanuber/go-glob"
    "golang.org/x/net/html"
)

var skipNodeData = map[string]bool{
    "":       true,
    "br":     true,
    "td":     true,
    "img":    true,
    "strong": true,
    "span":   true,
}

type item struct {
    No       int
    Name     string
    Category string
    Link     string
    Usual    float64
    Price    float64
    Discount float64
    Lowest   float64
}

func globWords(subj string, patterns map[string]struct{}) bool {
    subjLower := strings.ToLower(subj)
    for p := range patterns {
        p = strings.ToLower(strings.Trim(p, "*"))
        if glob.Glob(p+"*", subjLower) {
            return true
        }
    }
    return false
}

func uniqOpts(s string) map[string]struct{} {
    unique := make(map[string]struct{})
    for _, w := range strings.Split(s, ",") {
        unique[w] = struct{}{}
    }
    return unique
}

func nonZero(val float64) string {
    var printable string
    if val > 0.0 {
        printable = fmt.Sprintf("%.1f", val)
    } else {
        printable = "-"
    }
    return printable
}

func makeItemsFromURL(url string) ([]*item, error) {
    doc, err := parseList(url)
    if err != nil {
        return []*item{}, err
    }

    tableNode := node.Find(doc, func(n *html.Node) bool {
        return n.Type == html.ElementNode && n.Data == "table"
    })

    tbodyNode := node.Find(tableNode, func(n *html.Node) bool {
        attr, _ := node.Attr(n, "class")
        return n.Type == html.ElementNode && n.Data == "tbody" && attr == "list"
    })

    trNodes := node.Children(tbodyNode, func(n *html.Node) bool {
        return n.Type == html.ElementNode && n.Data == "tr"
    })

    items := make([]*item, 0, len(trNodes))

    for _, tr := range trNodes[1:] {
        itm, err := makeItem(tr)
        if err != nil {
            return nil, err
        }
        items = append(items, itm)
    }
    return items, nil
}

func makeItem(n *html.Node) (*item, error) {
    tdNodes := node.Children(n, func(n *html.Node) bool {
        return n.Type == html.ElementNode && n.Data == "td"
    })
    var err error
    itm := new(item)
    if itm.No, err = extractNo(tdNodes[0]); err != nil {
        return nil, fmt.Errorf("unable to parse No: %v", err)
    }

    if itm.Name, err = extractName(tdNodes[2]); err != nil {
        return nil, fmt.Errorf("unable to parse Name %v", err)
    }

    if itm.Category, err = extractCategory(tdNodes[2]); err != nil {
        return nil, fmt.Errorf("unable to parse Category: %v", err)
    }

    if itm.Link, err = extractLink(tdNodes[2]); err != nil {
        return nil, fmt.Errorf("unable to parse Link: %v", err)
    }

    if itm.Usual, err = extractUsualPrice(tdNodes[3]); err != nil {
        return nil, fmt.Errorf("unable to parse Usual price: %v", err)
    }

    if itm.Price, err = extractSalePrice(tdNodes[4]); err != nil {
        return nil, fmt.Errorf("unable to parse Sale price: %v", err)
    }

    if itm.Discount, err = extractDiscountPersent(tdNodes[4]); err != nil {
        return nil, fmt.Errorf("unable to parse Discount persent: %v", err)
    }

    if itm.Lowest, err = extractLowestPrice(tdNodes[5]); err != nil {
        return nil, fmt.Errorf("unable to parse Lowest price: %v", err)
    }

    return itm, nil
}