added Manufacturer and MPN to Meta
This commit is contained in:
		
							parent
							
								
									ddf4b8fad5
								
							
						
					
					
						commit
						50edffe63a
					
				@ -8,10 +8,11 @@ import (
 | 
			
		||||
 | 
			
		||||
type Connection struct {
 | 
			
		||||
	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) {
 | 
			
		||||
	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)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,7 @@ import (
 | 
			
		||||
 | 
			
		||||
// gets the product image of a reichelt article using the internal Part number
 | 
			
		||||
// 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) {
 | 
			
		||||
	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")
 | 
			
		||||
	metaItemNameSelector  = cascadia.MustCompile(".av_propname")
 | 
			
		||||
	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
 | 
			
		||||
@ -65,5 +69,47 @@ func (c *Connection) GetMeta(p Part) (Meta, error) {
 | 
			
		||||
		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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										46
									
								
								part.go
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								part.go
									
									
									
									
									
								
							@ -14,33 +14,42 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
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"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Where to dispatch api queries to
 | 
			
		||||
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"`
 | 
			
		||||
	MaxScore float32 `json:"maxScore"`
 | 
			
		||||
 | 
			
		||||
	Docs []Part `json:"docs"`
 | 
			
		||||
	Docs []partInternal `json:"docs"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type SearchResponse struct {
 | 
			
		||||
	Response ResponseField `json:"response"`
 | 
			
		||||
// The Full response
 | 
			
		||||
// notice: There are more fields that the server response contains
 | 
			
		||||
type searchResponse struct {
 | 
			
		||||
	Response responseField `json:"response"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	priceSelector = cascadia.MustCompile("#av_price")
 | 
			
		||||
)
 | 
			
		||||
var priceSelector = cascadia.MustCompile("#av_price")
 | 
			
		||||
 | 
			
		||||
// Search for a part like using the sites search engine
 | 
			
		||||
// 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))
 | 
			
		||||
	c.queryCount++
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
@ -52,12 +61,21 @@ func (c *Connection) FindPart(query string) ([]Part, error) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	reader := json.NewDecoder(resp.Body)
 | 
			
		||||
	response := SearchResponse{}
 | 
			
		||||
	response := searchResponse{}
 | 
			
		||||
	if err = reader.Decode(&response); err != nil {
 | 
			
		||||
		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
 | 
			
		||||
@ -102,8 +120,8 @@ func (c *Connection) GetPrice(p Part) float32 {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// need to convert german decimals (using ,) to american decimals
 | 
			
		||||
	// using .
 | 
			
		||||
	// need to convert german float (using ,) to american decimals
 | 
			
		||||
	// using . for ParseFloat (since ParseFloat is not localized)
 | 
			
		||||
	str := strings.Replace(price[:i], ",", ".", 1)
 | 
			
		||||
	ret, _ := strconv.ParseFloat(str, 32)
 | 
			
		||||
	return float32(ret)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user