added Manufacturer and MPN to Meta
This commit is contained in:
parent
ddf4b8fad5
commit
50edffe63a
@ -8,10 +8,11 @@ import (
|
|||||||
|
|
||||||
type Connection struct {
|
type Connection struct {
|
||||||
client http.Client
|
client http.Client
|
||||||
|
|
||||||
queryCount int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Opens a new connection to the reichelt-Server
|
||||||
|
// this will try to connect and consequently
|
||||||
|
// throw an error on connection failure
|
||||||
func NewConnection() (c *Connection, err error) {
|
func NewConnection() (c *Connection, err error) {
|
||||||
jar, err := cookiejar.New(nil)
|
jar, err := cookiejar.New(nil)
|
||||||
|
|
||||||
@ -25,7 +26,7 @@ func NewConnection() (c *Connection, err error) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// get reichelt SID cookie set
|
// set reichelt SID cookie
|
||||||
resp, err := c.client.Get(apiurl)
|
resp, err := c.client.Get(apiurl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
// gets the product image of a reichelt article using the internal Part number
|
// gets the product image of a reichelt article using the internal Part number
|
||||||
// the reader will return a image/jpg file
|
// the reader will return a image/jpg file
|
||||||
|
// NOTE: the Reader must be closed
|
||||||
func (c *Connection) GetImage(p Part, w, h uint) (io.ReadCloser, error) {
|
func (c *Connection) GetImage(p Part, w, h uint) (io.ReadCloser, error) {
|
||||||
resp, err := c.client.Get("https://www.reichelt.de/artimage/resize_" + strconv.Itoa(int(w)) + "x" + strconv.Itoa(int(h)) + "/" + strconv.Itoa(p.Number))
|
resp, err := c.client.Get("https://www.reichelt.de/artimage/resize_" + strconv.Itoa(int(w)) + "x" + strconv.Itoa(int(h)) + "/" + strconv.Itoa(p.Number))
|
||||||
|
|
46
meta.go
46
meta.go
@ -15,6 +15,10 @@ var (
|
|||||||
metaSelector = cascadia.MustCompile(".av_propview")
|
metaSelector = cascadia.MustCompile(".av_propview")
|
||||||
metaItemNameSelector = cascadia.MustCompile(".av_propname")
|
metaItemNameSelector = cascadia.MustCompile(".av_propname")
|
||||||
metaItemValueSelector = cascadia.MustCompile(".av_propvalue")
|
metaItemValueSelector = cascadia.MustCompile(".av_propvalue")
|
||||||
|
mpnSelector = cascadia.MustCompile("#av_articlemanufacturer > .av_fontnormal")
|
||||||
|
manufacturerSelector = cascadia.MustCompile("#av_articlemanufacturer > [itemprop=\"manufacturer\"]")
|
||||||
|
|
||||||
|
datasheetSelector = cascadia.MustCompile(".av_datasheet_description a")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Get Metadata connected to specified part
|
// Get Metadata connected to specified part
|
||||||
@ -65,5 +69,47 @@ func (c *Connection) GetMeta(p Part) (Meta, error) {
|
|||||||
result[headline] = data
|
result[headline] = data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// insert datasheets
|
||||||
|
nodes = datasheetSelector.MatchAll(doc)
|
||||||
|
temp := make(map[string]string)
|
||||||
|
|
||||||
|
for _, node := range nodes {
|
||||||
|
|
||||||
|
if node.FirstChild == nil || node.FirstChild.Type != html.TextNode {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
name := node.FirstChild.Data
|
||||||
|
link := ""
|
||||||
|
|
||||||
|
// find href of link
|
||||||
|
for _, k := range node.Attr {
|
||||||
|
if k.Key == "href" {
|
||||||
|
link = k.Val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if link == "" {
|
||||||
|
// no link found
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
temp[name] = link
|
||||||
|
}
|
||||||
|
|
||||||
|
result["datasheets"] = temp
|
||||||
|
|
||||||
|
// get MPN
|
||||||
|
node := mpnSelector.MatchFirst(doc)
|
||||||
|
if node != nil && node.FirstChild != nil {
|
||||||
|
temp["mpn"] = node.FirstChild.Data
|
||||||
|
}
|
||||||
|
|
||||||
|
// get Manufacturer
|
||||||
|
node = manufacturerSelector.MatchFirst(doc)
|
||||||
|
if node != nil && node.FirstChild != nil {
|
||||||
|
temp["manufacturer"] = node.FirstChild.Data
|
||||||
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
46
part.go
46
part.go
@ -14,33 +14,42 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Part struct {
|
type Part struct {
|
||||||
Number int `json:"article_artid"`
|
Number int
|
||||||
|
Description string
|
||||||
|
}
|
||||||
|
|
||||||
|
// used for the json Decoder
|
||||||
|
// The fields are then copied to Part
|
||||||
|
// (This was done to remove the structure tags).
|
||||||
|
type partInternal struct {
|
||||||
|
Number int `json:"article_artid"`
|
||||||
Description string `json:"article_lang_besch"`
|
Description string `json:"article_lang_besch"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Where to dispatch api queries to
|
||||||
const apiurl = "https://www.reichelt.de/index.html"
|
const apiurl = "https://www.reichelt.de/index.html"
|
||||||
|
|
||||||
type ResponseField struct {
|
// One Response-field from the autocomplete
|
||||||
|
// endpoint (a small excerpt from it)
|
||||||
|
type responseField struct {
|
||||||
NumFound int `json:"numFound"`
|
NumFound int `json:"numFound"`
|
||||||
MaxScore float32 `json:"maxScore"`
|
MaxScore float32 `json:"maxScore"`
|
||||||
|
|
||||||
Docs []Part `json:"docs"`
|
Docs []partInternal `json:"docs"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SearchResponse struct {
|
// The Full response
|
||||||
Response ResponseField `json:"response"`
|
// notice: There are more fields that the server response contains
|
||||||
|
type searchResponse struct {
|
||||||
|
Response responseField `json:"response"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var priceSelector = cascadia.MustCompile("#av_price")
|
||||||
priceSelector = cascadia.MustCompile("#av_price")
|
|
||||||
)
|
|
||||||
|
|
||||||
// Search for a part like using the sites search engine
|
// Search for a part like using the sites search engine
|
||||||
// can be used to resolv partnumbers to internal ones
|
// can be used to resolv partnumbers to internal ones
|
||||||
func (c *Connection) FindPart(query string) ([]Part, error) {
|
func (c *Connection) FindPart(query string) (result []Part, err error) {
|
||||||
resp, err := c.client.Get(apiurl + "?ACTION=514&id=8&term=" + url.PathEscape(query))
|
resp, err := c.client.Get(apiurl + "?ACTION=514&id=8&term=" + url.PathEscape(query))
|
||||||
c.queryCount++
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -52,12 +61,21 @@ func (c *Connection) FindPart(query string) ([]Part, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
reader := json.NewDecoder(resp.Body)
|
reader := json.NewDecoder(resp.Body)
|
||||||
response := SearchResponse{}
|
response := searchResponse{}
|
||||||
if err = reader.Decode(&response); err != nil {
|
if err = reader.Decode(&response); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.Response.Docs, nil
|
result = make([]Part, len(response.Response.Docs))
|
||||||
|
|
||||||
|
for i, j := range response.Response.Docs {
|
||||||
|
result[i] = Part{
|
||||||
|
Number: j.Number,
|
||||||
|
Description: j.Description,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the Price of the Part
|
// Returns the Price of the Part
|
||||||
@ -102,8 +120,8 @@ func (c *Connection) GetPrice(p Part) float32 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// need to convert german decimals (using ,) to american decimals
|
// need to convert german float (using ,) to american decimals
|
||||||
// using .
|
// using . for ParseFloat (since ParseFloat is not localized)
|
||||||
str := strings.Replace(price[:i], ",", ".", 1)
|
str := strings.Replace(price[:i], ",", ".", 1)
|
||||||
ret, _ := strconv.ParseFloat(str, 32)
|
ret, _ := strconv.ParseFloat(str, 32)
|
||||||
return float32(ret)
|
return float32(ret)
|
||||||
|
Loading…
Reference in New Issue
Block a user